Three podcasters fix a WordPress plugin bug (with chat logs) - Thomas Bibby

On Worst Case Scenario, the podcast I host with Baz Taylor and Dave Sims, we use a WordPress plugin called Seriously Simple Podcasting to host our podcast feed. It’s a fantastic minimalist plugin with little bloat and works very well for us.

We also installed an add-on called Seriously Simple Stats which would give us download counts for each episode of the podcast.

However the plugin wasn’t showing the client information properly and this was annoying Dave.

Screen Shot 2016-07-20 at 20.12.17
The three of us poked at it at various points during the day, and despite not being WordPress experts (and in my case, being very far from a PHP expert), we managed to get it working.

Screen Shot 2016-07-20 at 19.49.28

Podcast app User agent Strings

Here are some user agent strings reported by one or two podcast apps:

  • “AppleCoreMedia/ (iPhone; U; CPU OS 9_3_2 like Mac OS X; en_ie)” – native iOS podcast app, amongst other things
  • “Pocket Casts” a podcast app that is particularly popular on Android
  • “Overcast/1.0 Podcast Sync (x subscribers; feed-id=y; +” – from Marco Arment’s Overcast app, which helpfully tells you how many subscribers you have in the agent string
  • “iTunes/12.4.2 (Macintosh; OS X 10.11.5) AppleWebKit/601.6.17” – downloads from the Mac version of iTunes

Here’s the bit of the plugin that detects what client you’re using

if ( stripos( 'itunes', $user_agent ) !== false ) {

$referrer = 'itunes';

Hm. There was no entry for AppleCoreMediaPlayer, which was why downloads from the native podcast app were being detected as ‘Other’. But we tried downloading episodes from iTunes on the Mac and that was still recorded as Other.

In fact, apart from plays from the website, every client was being recorded as ‘Other’ – except for Pocket Casts. What was going on?

Screen Shot 2016-07-20 at 19.44.03When your needle and your haystack are the same size

Screen Shot 2016-07-20 at 19.46.40The stripos($haystack, $needle) function in PHP looks to see if a string $needle is in the string $haystack, if it is, it returns an integer with the position of $needle in $haystack, otherwise it returns false.

Absentmindedly, I typed ‘php’ in a mac terminal expecting to get an error, but instead getting a blank prompt, indicating I could type PHP code enclosed in <?php ?> and hit ctrl-D to make it run (why does OS X ship with PHP? I have no idea). I tried a smaller test case:

Screen Shot 2016-07-20 at 19.51.22

Those of you reading probably have the aha! moment by now, but it took a bit of probing from Baz before I got it:

Screen Shot 2016-07-20 at 19.52.53

And that was also the reason why Pocket Casts was showing up correctly – because the entirety of the user agent string is “Pocket Casts”!  Anyhow, changing the function around to read

if ( stripos( $user_agent , 'itunes' ) !== false ) {

$referrer = 'itunes';
and adding AppleCoreMedia to the list got everything working fine. Well almost.

Double hits from the iOS podcasts app

We then hit another problem:

Screen Shot 2016-07-20 at 19.57.11

Turns out any downloads from the iOS Podcasts app were being counted twice. It seems like Podcasts first sends a HEAD request for the mp3 file, presumably to get size information so it can populate the progress indicator, with the user agent “Podcasts/2.4”. The app then sends a normal GET request for the mp3 file with the AppleCoreMedia user agent mentioned earlier.

Screen Shot 2016-07-20 at 20.01.55

Being lazy I just added a return statement if we detected the Podcasts user agent:

if(stripos( $user_agent,'podcasts/' ) !== false ) {

I submitted it as a pull request and the maintainer merged it within a few hours. It was fun chatting away with Baz and Dave on iMessage while we tried to fix it.