Get some stats

I’m doing a weekly micropodcast. It’s difficult to count listeners, but by a conservative accounting, as of this writing, there have been 2593 total downloads of 18 total episodes, for an average of 144 per episode. How do I know? My web server logs and this shell script:

#!/bin/sh

count_downloads_for_episodes() {
    local _start_episode _end_episode _num_episodes _total_downloads _episode _downloads
    _start_episode="$1"
    _end_episode="$2"

    _num_episodes=$(expr ${_end_episode} - ${_start_episode} + 1)
    _total_downloads=0
    for _episode in $(jot ${_num_episodes} ${_start_episode}); do
        _downloads=$(count_downloads_for_episode ${_episode})
        _total_downloads=$(expr ${_total_downloads} + ${_downloads})
        echo "${_episode}: ${_downloads}"
    done

    echo "total: ${_total_downloads}"
    echo "average:" $(expr ${_total_downloads} / ${_num_episodes})
}

count_downloads_for_episode() {
    local _http_status_of_interest _logfiles _episode _downloads
    _episode="$1"

    _http_status_of_interest=200
    _logfiles='logs/access logs/access-ssl'
    _downloads=$(grep "GET /.*ai3m${_episode}\.mp3" ${_logfiles} | grep " ${_http_status_of_interest} " | wc -l)
    echo ${_downloads}
}

main() {
    local _start_episode _end_episode
    if [ $# = 2 ]; then
        _start_episode="$1"
        _end_episode="$2"
    elif [ $# = 1 ]; then
        _start_episode="$1"
        _end_episode="$1"
    else
        _start_episode=1
        _end_episode=$(ls src/*.mp3 | sed -e 's|src/ai3m||' -e 's|\.mp3||' | sort -n | tail -1)
    fi

    count_downloads_for_episodes ${_start_episode} ${_end_episode}
}

main "$@"

There are thousands more HTTP status 206es in the logs, which are excluded on the assumption that they represent partial downloads and shouldn’t count toward the total. If you can suggest how I might more accurately and/or standardly count podcast downloads without relying on external services, I’m interested.

Attract more listeners

One way I’ve been trying to expand my audience is by announcing each week’s episode via social media. As a heavy Twitter user, I’ve noticed that certain kinds of media — such as YouTube videos and animated GIFs — can be played directly within tweets, without needing to leave an app or click a link. I wanted Twitter to be presenting my podcast in this way, on the hypothesis that the easier it is to listen, the more folks will try listening.

Twitter calls this multimedia feature the Player Card, one of several types of “Cards”, and gives developers a way to implement it for their sites. As I was changing my episode template, I noticed a bug in the CMS’s expansion of some of the directives. For instance, when I gave ikiwiki this input:

[[!meta  name="twitter:card" content="player"]]

I expected it to generate this output, which is what Twitter would want:

<meta name="twitter:card" content="player" />

But it did this instead:

<meta name="twitter:cardcontent="player" />

Fix a bug

Ikiwiki has lots of tests, but I didn’t see any for the plugin that processes these directives. So I reviewed the docs and the code and wrote some tests (warning: Perl (warning: hey, I like Perl!)) for a bunch of the other variants of the meta directive — partly in case there were more bugs lurking, partly to make the neighborhood safer for future contributors, and mainly to avoid creating new bugs when I fixed mine. Between the time I’d invested in reading and exercising other code in the same plugin, the bug being pretty obvious to begin with, and tests that told me whether I was done yet, it was a quick fix.

Great success (?)

Now that my Player Card validates, when I (or anyone) tweets a new episode of Agile in 3 Minutes, some browsers and Twitter clients display a nice little widget for playing the audio. In Safari on OS X:

twitter-player-card.png

Give it a try. How’s it work? How’s it look? Bug reports gratefully accepted.