YouTube Tracking In Google Analytics & Google Tag Manager

May 11, 2015
By Dan Wilkerson

UPDATE: Now includes percentage viewed tracking.

My colleague Sayf Sharif has long been an advocate of tracking YouTube videos with Google Analytics. Our LunaMetrics YouTube tracking script has been copied, cloned, forked, and borrowed more than a few times. It’s time to bring our script up to date with the latest changes in Google Analytics and Google Tag Manager.

Also, Google recently finished the process of deprecating version two of their data API, which our script has depended on for fetching video titles. If you are using an old version of the script, you’ll see all of your videos titles set to https://youtube.com/devicesupport as of a few days ago.

After a little tinkering, we’ve updated the GitHub repo with version 7 of the illustrious LunaMetrics YouTube Google Analytics tracking code. Let’s take a look at what’s inside.

What’s New

This latest version is a plug-and-play tracking solution for tracking user interaction with YouTube videos in Google Analytics. It will detect if Google Tag Manager, Google Analytics (Universal), or Google Analytics (Classic) is installed on the page, in that order, and fire events when users interact with the video.

It includes support for delivering hits directly to Universal or Classic Google Analytics, or for pushing Data Layer events to be used by Google Tag Manager. It also supports percentage viewed tracking. You can find the code on our GitHub repo.

Installation

This plugin will play nicely with any other existing plugin that interfaces with the YouTube Iframe API, so long as it is loaded after any existing code. Otherwise, if another function overwrites the window.onYouTubeIframeAPIReady property, it will fail silently.

Universal or Classic Google Analytics Installation:

The plugin is designed to be plug-and-play. By default, the plugin will try and detect if you have Google Tag Manager, Universal Analytics, or Classic Google Analytics, and use the appropriate syntax for the event. If you are not using Google Tag Manager to fire your Google Analytics code, store the plugin on your server and include the lunametrics-youtube-v7.gtm.js script file somewhere on the page. You can host the script on your own server, or you can make use of the freely hosted jsdelivr copy.

Google Tag Manager Installation

Create a new Custom HTML tag and paste in the below:

In the space between the <script> and </script> tags, paste in the contents of the lunametrics-youtube.gtm.js script, found here. You can set the Trigger to All Pages, or you can use a Custom JS Variable to detect if a YouTube video is present and use that instead, like so:

function() {

  var iframes = document.getElementsByTagName('iframe');
  var embeds = document.getElementsByTagName('embed');
  var i;

  function isYouTubeVideo(potentialYouTubeVideo) {

    var potentialYouTubeVideoSrc = potentialYouTubeVideo.src || '';

    if( potentialYouTubeVideoSrc.indexOf( 'youtube.com/embed/' ) > -1 || 
        potentialYouTubeVideoSrc.indexOf( 'youtube.com/v/' ) > -1 ) {

      return true;

    }

  }

  for(i = iframes.length - 1; i > -1; i--) {
  
    var _iframe = iframes[i];
    var test = isYouTubeVideo(_iframe);

    if(test) {
      return true;
    }

  }

  for(i = embeds.length - 1; i > -1; i--) {

    var _embed = embeds[i];
    var test = isYouTubeVideo(_embed);

    if(test) {
      return true;
    }

  }

  return false;

}

Configuration

Once everything installed on your own site, this script will fire a Google Analytics event with the following settings:

  1. Event Category: Videos
  2. Event Action: (Action, e.g. Play, Pause)
  3. Event Label: (URL of the video)

Configuring Which Events Fire

If you are not using Google Tag Manager to fire your Google Analytics code, you might want to configure the script to fire or not fire certain events. By default, it will fire:

  • Play events
  • Pause events
  • Watch to End events
  • 10, 25, 50, 75, & 90% View Completion events

To change which events are fired, edit the configuration at the end of the script. For example, if you’d like to fire Play events and not fire Pause events:

( function( document, window, config ) {

   // ... the tracking code

} )( document, window, {
  'events': {
    'Pause'    : false,
    'Play': true
  }
} );

The available events are Play, Pause, and Watch To End. These are all enabled by default, which you can see and modify at the bottom of the script file.

Forcing Universal or Classic Analytics

By default, the plugin will try and fire Data Layer events, then fallback to Universal Analytics events, then fallback to Classic Analytics events. If you want to force the script to use a particular syntax for your events, you can set the ‘forceSyntax’ property of the configuration object to an integer:

( function( document, window, config ) {

   // ... the tracking code

} )( document, window, {
  'forceSyntax': 1
} );

Setting this value to one of the following numbers:

  • 0 will force the script to use Google Tag Manager events
  • 1 will force it to use Universal Google Analytics events
  • 2 will force it to use Classic Google Analytics events

NEW – Enabling Percentage Viewed Tracking

By default, percentage viewed tracking is enabled. Configure it by adjusting the percentageTracking object’s properties at the end of the script. The object has two properties: each and every. The each property accepts and array of numbers, and will fire an event once that percentage is reached. The every property accepts an integer, and will fire every n%.

( function( document, window, config ) {

   // ... the tracking code

} )( document, window, {
  'percentageTracking': {
    'every': 25,  // Tracks every 20% viewed, e.g. 25%, 50%, & 75% 
    'each': [10, 90] // Tracks 10% and 90% completion
  }
} );

NOTE: Google Analytics has a 500 hit per-session limitation, as well as a 20 hit window that replenishes at 2 hits per second. For that reason, it is HIGHLY INADVISABLE to track every 1% of video viewed.

Google Tag Manager Configuration

Once you’ve added the script to your container (see Google Tag Manager Installation), Data Layer events will occur for all of the following:

  • Play
  • Pause
  • Watch to End

Create the following Variables:

  • Variable Name: videoUrl
    • Variable Type: Data Layer Variable
    • Data Layer Variable Name: attributes.videoUrl
    • This is the URL of the video on YouTube
  • Variable Name: videoAction
    • Variable Type: Data Layer Variable
    • Data Layer Variable Name: attributes.videoAction
    • This will be the action the user has taken, e.g. Play, Pause, or Watch to End

video-variables

Create the following Trigger:

  • Trigger Name: YouTube Video Event
    • Trigger Type: Custom Event
    • Event Name: youTubeTrack

youtube-event-trigger

Create your Google Analytics Event tag

  • Tag Type: Google Analytics
    • Choose a Tag Type: Universal Analytics (or Classic Analytics, if you are still using that)
    • Tracking ID: <Enter in your Google Analytics tracking ID>
    • Track Type: Event
    • Category: Videos
    • Action: {{videoAction}}
    • Label: {{videoUrl}}
    • Fire On: More
      • Choose from existing Triggers: YouTube Video Event

youtube-GA-Event

Getting Video Titles

Because of the deprecated YouTube API, this script no longer provides the titles of the videos. We chose to go with the most consistent method, which means that instead of the human-readable titles you would have gotten as your Event Label before, you’ll now see the URL of the video itself, e.g. https://www.youtube.com/watch?v=dQw4w9WgXcQ.

Once you have the video URL, you can use something like Excel or Google Spreadsheets to help convert those into readable titles. Another option would be to use a Google Tag Manager Lookup Table to translate the URLs into titles before sending the information to Google Analytics. We have a spreadsheet to help convert URLs to Titles, as well as blog about quickly creating lookup tables.

Coming Soon

We have added percentage completion tracking to the script, and are looking for suggestions on how we could improve the script with further functionality. Let us know on the GitHub repo or in the comments below.