5

My aim is to get the total number of listens so I was thinking I could save a 'listen' count to the audio file's post meta using update_post_meta()

Is there a hook that fires each time an audio file is played?

Background: I'm using wp_audio_shortcode() to output the (mediaelement) player.

Refs:

8

Yes, the play event fires on the <audio> element, so you could target it eg $('audio.wp-audio-shortcode').on('play', function (event) { //etc });. A number of other events are also available, eg ended, playing, pause.

Here's some code I'm trialing at the moment that may help you (in "functions.php"):

add_action( 'wp_footer', function () {
    ?>
    <script>
    jQuery(document).ready(function() {
        (function ($) {
            var srcs = []; // Array of sources already sent to cut down on posts to server.
            $('audio.wp-audio-shortcode, .wp-audio-playlist audio').on('play', function (event) {
                // this.src should be the url (guid) of the audio file
                if (this.src && $.inArray(this.src, srcs) === -1) {
                    srcs.push(this.src);
                    $.post( '<?php echo admin_url( 'admin-ajax.php' ); ?>', {
                            action: 'wpse168584_audio_stats',
                            guid: this.src.replace(/\?.+$/, ''), // Remove any query vars.
                            nonce: '<?php echo wp_create_nonce( 'wpse168584_audio_stats_' ); ?>'
                        }, null, 'json'
                    );
                }
            });
        })(jQuery);
    });
    </script>
    <?php
} );
function wpse168584_audio_stats() {
    $ret = array( 'error' => false );

    if ( ! check_ajax_referer( 'wpse168584_audio_stats_', 'nonce', false /*die*/ ) ) {
        $ret['error'] = __( 'Permission error', 'wpfm' );
    } else {
        if ( ! isset( $_REQUEST['guid'] ) || ! ( $guid = $_REQUEST['guid'] ) ) {
            $ret['error'] = __( 'Params error', 'wpfm' );
        } else {
            global $wpdb;
            $sql = $wpdb->prepare( 'SELECT ID FROM ' . $wpdb->posts . ' WHERE guid = %s LIMIT 1', $guid );
            if ( $post_id = $wpdb->get_var( $sql ) ) {
                // Use hex format to save space, 8 bytes for IPv4, 32 for IPv6.
                $ip = bin2hex( inet_pton( preg_replace( '/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR'] ) ) );
                if ( ! ( $meta = get_post_meta( $post_id, '_wp_attachment_metadata', true ) )
                || ! isset( $meta['plays_ips'] )
                || ! in_array( $ip, $plays_ips = explode( ';', $meta['plays_ips'] ) ) ) {
                    $plays_ips[] = $ip;
                    // If data getting too big, drop off oldest ip (FIFO).
                    if ( strlen( $meta['play_ids'] ) > 1000 ) array_shift( $plays_ips );
                    // Save as string to save space.
                    $meta['plays_ips'] = implode( ';', $plays_ips );
                    $meta['plays'] = isset( $meta['plays'] ) ? $meta['plays'] + 1 : 1;
                    update_post_meta( $post_id, '_wp_attachment_metadata', $meta );
                }
            }
        }
    }

    wp_send_json( $ret );
}
add_action( 'wp_ajax_nopriv_wpse168584_audio_stats', 'wpse168584_audio_stats' );
add_action( 'wp_ajax_wpse168584_audio_stats', 'wpse168584_audio_stats' );

Then to see the "plays" meta data when you go into admin and edit an audio item (it appears in the read-only meta data box on the top right under bitrate):

add_filter( 'media_submitbox_misc_sections', function ( $arr ) {
    $arr['plays'] = __( 'Play Count:' );
    return $arr;
} );
  • $( 'audio.wp-audio-shortcode' ).on( 'play', function (event) { // etc }) is absolutely fantastic, just what I was looking for. And thanks for the heads up about the ended, playing and pause events – henrywright Nov 19 '14 at 0:01

protected by Community Feb 21 at 11:42

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.