YouTube video tracking into Google Analytics

If you have a website with embedded YouTube videos you can track how your visitors interact with the player inside Google Analytics.

This will provide you with an understanding of how people have interacted with your videos, whether they clicked on play, and whether they actually watched it through to the end. We can use this information to gain richer insights into how each of our videos are being used, which videos users actually watch, and which ones they turn off.

In this blog post we will focus on the required setup for new asynchronously loaded YouTube Player API: the IFrame API. This is the latest version of the YouTube embed code. If you’re using an earlier version of the YouTube embed code, the below steps won’t work. You’ll need to either upgrade your embed method, or find an alternative approach.

Required Setup Steps

Below we will run through the steps required to implement YouTube video tracking on your website:

    1. Create a element in the body that will hold the YouTube video:
      <body>
          <script>
              ----code here----
          </script>
      </body>
    2. We follow this with the beginning of our script block which loads the YouTube iFrame API:
      var tag = document.createElement('script');
      tag.src = "http://www.youtube.com/player_api";
      var firstScriptTag = document.getElementsByTagName('script')[0];
      firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    3. Once the API for the player is loaded it calls the onYouTubePlayerAPIReady() function. The next part of our script block listens for this call. You’ll need to add the below code beneath the code you added in step 2. When you do this, you’ll need to change the videoID as well as the video height and width.
      var player;
      var lastAction = '';
          function onYouTubePlayerAPIReady() {
              player = new YT.Player('player', {
                  height: '390',
                  width: '640',
                  videoId: 'u1zgFlCw8Aw',
                  events: {
                      'onStateChange': onPlayerStateChange
                  }
              });
          }
    4. For every video player status change, the function onPlayerStateChange() is called by the YouTube iFrame API. What we do is the below code block is to trigger a Google Analytics event triggered depending on the current status which is included in the data property of the event parameter (event.data). Add the following code beneath the code from step 3 and that will finish up our script block.
      function onPlayerStateChange(event) {
          switch (event.data){
              case YT.PlayerState.PLAYING:
                  _gaq.push(['_trackEvent','video', 'Playing', player.getVideoUrl()]);
                  break;
              case YT.PlayerState.ENDED:
                  _gaq.push(['_trackEvent','video', 'Completed', player.getVideoUrl()]);
                  break;
              case YT.PlayerState.PAUSED:
              if (lastAction != 'paused'){
                  _gaq.push(['_trackEvent','video', 'Paused', player.getVideoUrl()]);
              lastAction = 'paused';
              }
                  break;
                  }
              }
      

 

The Complete Code

To save you the trouble of pasting all the code together, we’ve got the complete code below. Be sure to follow the instructions and change all the highlighted values!

    var tag = document.createElement('script');
    tag.src = "http://www.youtube.com/player_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 

    var player;
    var lastAction = '';
        function onYouTubePlayerAPIReady() {
            player = new YT.Player('player', {
                height: '390',
                width: '640',
                videoId: 'u1zgFlCw8Aw',
                events: {
                    'onStateChange': onPlayerStateChange
                }
            });
        }

        function onPlayerStateChange(event) {
            switch (event.data){
                case YT.PlayerState.PLAYING:
                    _gaq.push(['_trackEvent','video', 'Playing', player.getVideoUrl()]);
                    break;
                case YT.PlayerState.ENDED:
                    _gaq.push(['_trackEvent','video', 'Completed', player.getVideoUrl()]);
                    break;
                case YT.PlayerState.PAUSED:
                    if (lastAction != 'paused'){
                    _gaq.push(['_trackEvent','video', 'Paused', player.getVideoUrl()]);
                    }else{
                        lastAction = 'paused';
                    }
                    break;
                }
            }

It is worth noting the case for YT.PlayerState.PAUSE, that is, when we pause the video. To account for this case we’ve saved the previous action in the variable ‘lastAction’, and if our previous action was ‘paused’, then we don’t register an event. This is to avoid triggering countless GA events when using the scrub option (dragging the play location ball).

In the example above , we use:

_gaq.push(['_trackEvent','video', 'Playing', player.getVideoUrl()]);

For those who need a refresher on event parameters, this represents:

Category > video
Action > Playing
Label > Video URL (taken dynamically from the API)

If you want to customise your javascript tracking setup, you can check the player status using integer values or namespaced ones (like in our example).

The possible values returned according the status are:

Integer values Namespaced
  • -1 : no started yet
  • 0 : ended
  • 1 : playing
  • 2 : paused
  • 3 : buffering
  • 5 : video cued.
  • YT.PlayerState.ENDED
  • YT.PlayerState.PLAYING
  • YT.PlayerState.PAUSED
  • YT.PlayerState.BUFFERING
  • YT.PlayerState.CUED

Setting up Goals

Now that your tracking is all working, you can set up event-based goals in Google Analytics. You might want to set up the completion event as a goal, as this indicates that a user has fully engaged with your video content.



  • C

    Thanks for this info. I am thinking it is exactly what I need for monitoring video playback from my blogger blog. I have run into a challenge that I hope you can help me figure out. Let’s assume each blog entry has a video, and I use this code to display said video. It works perfect when the blog entries are viewed on their own pages. However, when the blogs are aggregated, such as on the main page, I may have 5 videos on the same html page. What I am finding is that only the last entry on the page actually works. The various scripts (which are the same with the exception of the video specific data) are basically conflicting, and the last one to load is the only one that works.

    I have tried making each “div ID” unique. I thought that would work, as each instance of the script would only be looking for their specific “div ID”. It didn’t work. Nothing displays for the first 4 entries, and the 5th works fine.

    I am not familiar enough with javascript coding to solve this without some help. I do have the ability to put the javascript into the main html code, to load only once…if I can figure out how to work out the individual videos.

    To summarize with a simplified question:

    How would you go about doing this with two (or more) videos on the same page?

    Thank you!

  • http://himedlooff.com/ Mike

    “The Complete Code” might have a typo in it. Specifically the block `case YT.PlayerState.PAUSED:` where there is an `if/else` in the code above it in step 4 there is only an `if`. The addition of the `if/else` will break the code. Stick with the `if` with no else version from step 4.

  • http://www.blogger.com/profile/09757704801593874137 tudor

    i have been searching for this info for days and nothing came out until this page. thank you so much. Event tracking on youtube videos worked just fine for my blog, but what about adobe flash videos. how do i track them exactly? Thanks a lot!!

  • http://www.blogger.com/profile/09557830299694753760 David Yang

    Only “Playining” and “Paused” being tracked as event. Unfortunately, “Completed” could not be tracked as an event for some reason.
    I used default code without changing anything.

  • http://www.blogger.com/profile/09557830299694753760 David Yang

    “Completed” could not be tracked as an event. Analytics only tracked “Playing” and “Paused” event. By the way, I am using the default code and did not change it at all.

  • http://www.blogger.com/profile/05844384131243177830 Kelly Miyashiro

    Wait… If lastAction is not paused, do something. Otherwise set it to paused again? So… it never gets set to paused.

  • Anonymous

    player_api can be loaded automatically if you add &enablejsapi=1 to the video url.
    steps 1 and 2 are useless.

  • Anonymous

    Thanks for this information. I was able to get it to work on some videos I have embedded on the site however if my page had more than one video the code was broken and the videos were no longer visible. Did anyone else have this issue? Also do you have any insight for pages with more than one video?

  • tsilias

    Thanks mate! Any help for multiple videos on one page?

  • Abhishek Yoga

    Thanks! But this code doesn’t seem to load the youtube video. When I embed the video through iframe script provided by Youtube, the video appears. I am using a CMS, weebly to edit and build my website. I need to start event tracking a video I placed on my Home page. Kindly guide me to do so. Thanks!