5

Video player event tracking

Video player event tracking

This article will explain our best practices around tracking video players on your site. This is done through javascript events. There are examples for each of the following players:

  • YouTube
  • Vimeo

YouTube

You can embed your Youtube video using their iFrame API.

<div id="player"></div>
<script type="text/javascript">
// This code loads the IFrame Player API code asynchronously.
  var tag = document.createElement('script');
  tag.src = "https://www.youtube.com/iframe_api";
  var firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  // This function creates an <iframe> (and YouTube player)
  // after the API code downloads.var player;
  function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
      height: '390',
      width: '640',

      videoId: 'M7lc1UVf-VE',
      events: {
        'onStateChange': onPlayerStateChange
      }
   });

}
</script>

If you want to embed the video directly, you may do so, but be sure to give the iframe tag an id that you can reference with javascript. You must also append the following query string to the iframe’s src attribute to enable the JS API on your domain:

"?enablejsapi=1&origin=http://<YOURDOMAIN>.com"

For example:

<iframe id="player2" src="http://www.youtube.com/embed/M7lc1UVf-VE?
enablejsapi=1&origin=http://example.com" frameborder="0"></iframe>

Then you can use the following script to add events to the existing player (with id=player2):

// <![CDATA[
// This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// This function takes the existing <iframe> (and YouTube player)
// with id 'player1' and adds an event listener for state changes.
var player;
function onYouTubeIframeAPIReady() {
  player = new YT.Player('player1', {
    events: {
      'onStateChange': onPlayerStateChange
    }
  });
}
// ]]>

Once you have your player set up (whether inserted programmatically or passed explicitly) and the event listener bound, this function will listen for state changes and fire an event to Segment based on the player’s state:

// <![CDATA[
function onPlayerStateChange(event) {
  switch(event.data) {
    case YT.PlayerState.PLAYING:
      analytics.track('Video Played', {
        video: player.getVideoData().title,
        id: player.getVideoData().video_id,
        duration: player.getDuration()
      })
      break;
    case YT.PlayerState.PAUSED:
      analytics.track('Video Paused', {
        video: player.getVideoData().title,
        id: player.getVideoData().video_id,
        pausedAt: player.getCurrentTime()
      })
      break;
    case YT.PlayerState.ENDED:
      analytics.track('Video Finished', {
        video: player.getVideoData().title,
        id: player.getVideoData().video_id,
        duration: player.getDuration()
      })
      break;
    default:
      return;
  }
}
// ]]>

And voila! You’re sending events for ‘Video Played’, ‘Video Paused’, and ‘Video Finished’ with relevant event properties.

Vimeo

Vimeo has an awesome reference implementation of their player API here and some great docs here.

You can add the video via iFrame like such:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta name="viewport" content="width=700,maximum-scale=1.0,
         user-scalable=yes">
        <title>Vimeo Froogaloop API Playground</title>
        <script>
            /* Don't forget your analytics.js snippet :) */
        </script>
    </head>
    <body>
        <div class="wrapper">
            <hgroup>
                <h1>Vimeo Segment Example</h1>
            </hgroup>
            <div class="container">
                <div>
                    <h2>Vimeo Player 1</h2>
                    <iframe id="player_1" src="http://player.vimeo.com/
                     video/7100569?api=1&amp;player_id=player_1" width
                     ="540" height="304" frameborder="0">
                    </iframe>
                </div>
            </div>

Here is the javascript (there is also some jQuery in there) that is used to listen for events from the video. The events are also mapped to .track() calls.

<script>
$(function() {
    var player = $('#player_1');
    var playerOrigin = '*';

    // Listen for messages from the player
    if (window.addEventListener) {
        window.addEventListener('message', onMessageReceived, false);
    }
    else {
        window.attachEvent('onmessage', onMessageReceived, false);
    }

    // Handle messages received from the player
    function onMessageReceived(event) {
        // Handle messages from the vimeo player only
        if (!(/^https?:\/\/player.vimeo.com/).test(event.origin)) {
            return false;
        }

        if (playerOrigin === '*') {
            playerOrigin = event.origin;
        }

        var data = JSON.parse(event.data);

        switch (data.event) {
            case 'ready':
                onReady();
                break;

            case 'play':
                onPlay(data.data);
                break;

            case 'playProgress':
                onPlayProgress(data.data);
                break;

            case 'pause':
                onPause(data.data);
                break;

            case 'finish':
                onFinish(data.data);
                break;
        }
    }

    // Helper function for sending a message to the player
    function post(action, value) {
        var data = {
          method: action
        };

        if (value) {
            data.value = value;
        }

        var message = JSON.stringify(data);
        player[0].contentWindow.postMessage(message, playerOrigin);
    }

    function onReady() {
        post('addEventListener', 'play');
        post('addEventListener', 'pause');
        post('addEventListener', 'finish');
        post('addEventListener', 'playProgress');
    }
    function onPlay(data) {
        analytics.track('Video Played');
    }

    function onPause(data) {
        analytics.track('Video Paused');
    }

    function onFinish(data) {
        analytics.track('Video Finished');
    }

    function onPlayProgress(data) {
        var quartile;
        if (data.percent % 25 === 0) {
            quartile = data.percent / 25;
            analytics.track('Video Progress', {
                quartile: quartile
            })
        }
    }
});

There you go! You're now sending 'Video Played', 'Video Paused', 'Video Finished', and 'Video Progress' events to Segment!