6 Nov 2017
Built-in tracking of YouTube videos in Google Tag Manager
Reading time: 11 mins.

Built-in tracking of YouTube videos in Google Tag Manager

In a previous article we took an in-depth look at the recurring subject of how to track embedded YouTube videos using Google Tag Manager. Back then, the only way to do it was via custom scripts that connected manually to YouTube’s JavaScript API and acted as event listeners, sending the relevant data and notifications to GTM.

gtm.video killed the custom script
gtm.video killed the… custom… script?

Although this method still works (for the time being, if you’re using a similar setup, there’s no need to change it), in most cases it’s now obsolete, given that Google Tag Manager has finally added native YouTube integration with its own automated events, triggers and built-in variables.

Let’s take a closer look at what it consists of, how it works and what data it gives us, along with a couple of practical examples.

1. The trigger

As with any other form of automated tracking, such as clicks or page loads, in order to trigger an internal processor and for GTM to start detecting the corresponding events, all we need to do is create a suitable trigger. In this instance, it will appear under Other > YouTube video:

Nuevo tipo de trigger: Video youtube

Once we’ve selected the trigger, we can then view the configuration options, which mostly comprise the types of interaction we want to measure:

Trigger Youtube Video

The following options are available:

  • Start: this generates a GTM event at the start of playback (note: the trigger does not fire again if playback is resumed after a pause).
  • Complete: this generates a GTM event at the end of the video (i.e. after it’s played in full).
  • Pause, Seeking, and Buffering: this generates a GTM event when playback is interrupted, whether manually (i.e. paused, fast-forwarded or rewound) or while waiting for the content to load (buffering).
  • Progress: this generates a GTM event when the playback progress bar reaches a certain point, whether expressed as a percentage (X% played) or a time threshold (X seconds played). We can specify several different points, as long as we separate them with commas.
  • Add JavaScript API Support: as was the case with tracking using a customized event processor, in order to interact with the video it needs to have been loaded with an activated YouTube API (this is done by adding the parameter &enablejsapi=1 to its URL). This option adds the parameter retroactively, if necessary. As a result – and despite the fact that it might cause a “flickering” effect on the page by reloading the videos – I recommend selecting this option, unless we manually check that all of the videos to be measured already have it.
  • Fire on… like the rest of the triggers, we can choose whether the trigger fires every time (All Videos) or just in certain instances (Some Videos), in which case we’ll need to specify the additional conditions (Variable – Value). So, for example, we can limit tracking to certain pages (using the conditions of Page URL, Page Path, etc.), or create a custom trigger for a tag that applies to a single video or specific case.

Watch out! Progress-type events do not mean that the video has been played in full up to the specified point, only that the current point of playback (progress bar) has been reached or passed. If the user manually jumps to a certain point in the video, any Progress-related trigger corresponding to an earlier point in playback will immediately be fired. However, it will not be fired more than once, even if the user jumps back and forward again.

2. The variables

Once we’ve created the trigger, we can activate the Preview mode and test it before creating a tag that will use it.

If everything’s been done correctly up to this point, the debug console will display a gtm.video event for each of the configured interactions, accompanied by additional data associated with the video and the event. This will help us to identify the video and event and will also provide information for tags and scripts. The data layer that’s generated will look something like this:


Datalayer evento gtm.video

As with any other data sent to the data layer, we can access it via custom data layer variables. However, in this instance, we don’t need to create them. Preset variables have already been added to GTM for this purpose, so all we need to do is go into Configure Built-In Variables and select the ones we need:

Variables integradas: Video

Once we’ve selected them, the fields are automatically completed with the corresponding values.

Variables Video

The associated GTM variables, plus their corresponding preset variables and internal names in the data layer, are as follows:

  • Event (event): gtm.video
  • Video Provider (gtm.videoProvider): the platform that provides the video. At the moment, there’s only youtube, but the option is there for the future… 😉
  • Video Status (gtm.videoStatus):  the current status of the video, which in turn identifies the specific action that has fired the event. The potential values are: start, complete, pause, buffering, progress
  • Video URL (gtm.videoUrl): the complete canonical URL of the webpage with the embedded video, e.g. https://www.youtube.com/watch?v=XXXXXX
  • Video Title (gtm.videoTitle): the title or name of the video.
  • Video Duration (gtm.videoDuration): the duration of the video in seconds.
  • Video Current Time (gtm.videoCurrentTime): the position (in seconds) of video playback at the time of the event. This is a useful variable to combine with gtm.videoStatus = 'progress'.
  • Video Percent (gtm.videoPercent): the position (in percentage of total running time) of video playback at the time of the event. This is a useful variable to combine with gtm.videoStatus = 'progress'.
  • Video Visible (gtm.videoVisible): a particularly interesting variable! ? It returns a true or false response depending on whether or not the video is visible in the browser window at the time of the event.

There’s also another type of data that doesn’t have a built-in variable associated with it. gtm.videoElapsedTime indicates the time elapsed (in seconds) since the last interruption (i.e. a pause or buffering). If we want to use this option, we have to manually create the corresponding data layer variable {{Video Elapsed Time}}:

Our time is ruuunning out, can't push it uuunderground

3. Use case: integration with Google Analytics

Now that we know how the trigger and its associated variables work, we can use them with any GTM tag. The most common use will be tracking embedded videos using Google Analytics.

For example, let’s say we want to use Analytics to measure the most frequent interactions (play, pause, completed playback in intervals of 25%, and complete) for all of the YouTube videos on our website, with Google Tag Manager. We’ll use the following format:

  • Tracking type: Event
  • Event category: Video
  • Event action: Play, Pause, Played X%, Complete
  • Event tag: Video URL

Here’s the step by step:

1) Trigger

We’ll create a general YouTube Video trigger, selecting all of the possible actions, and choosing Percentage: 25,50,75 (for 100%, the “Complete” option is sufficient) in Progress.

Alguien debe tirar del trigger

2) Auxiliary variables

If we want to make the name of the event action more legible prior to sending it to Analytics, filter it, or adapt it to a specific format (e.g. the one we were using beforehand, with manual tracking), we have two options. One: create separate triggers and tags for each type of action. Two: process the name of the action beforehand (via {{Video Status}}) using an intermediate auxiliary variable. The second option would be much less tedious.

In this example, we’ve created {{Video Action}} with a simple lookup table:

Variable custom: Video Action

As we can see in the use case for {{Video Percent}}, this intermediate pre-process step allows us to be creative, combine data, and reorganize actions. For example, we could have renamed “Complete” as “Played 100%”.

3) Tag

Now we’ll create the corresponding Universal Analytics tag:

Etiqueta GA Youtube

Of course, we’ll complete the rest of the configuration options for the tag using the common values from our tracking setup. In this example, we’ve assumed that we’ve already compiled everything in a single Google Analytics Settings variable({{GA Config}}) and if you haven’t already done that, you should! 😉

Watch out! We have to be especially careful with the Non-interaction hit field. Normally, we’d leave this setting on False by default, given that the majority of actions represent user interactions. But that’s not always the case.

In particular, if we have autoplay videos on our website, they’ll automatically generate certain events (Play, Progress, etc.) as soon as the page is loaded. This will invalidate the figures for bounce rate. On this occasion at least, it’s better to leave the setting on True, even though this may be problematic for landing-type pages where there are hardly any interactions other than the one with the video. Or even better, we could avoid using autoplay altogether, because it’s a damn nuisance! ?

Finally, we add the generic trigger we’ve already created to the tag.

...y su activador

Note that this implementation doesn’t only include manual interruptions (Pause), but also those caused involuntarily due to waiting (Buffering, as a separate action). If, for whatever reason, we don’t want to record these, we can’t configure them separately from other pauses in the trigger, but we can modify them by giving them additional conditions that effectively discard them:

NOBODY likes buffering :(

4. Use case: tracking conversions

Here’s another common example of tracking (this one’s slightly more advanced). Let’s imagine we have a campaign in which we are contacting users via a webpage containing a video, and our goal is for users to watch that video. How can we measure these conversion events in order to calculate the impact of the campaign?

For argument’s sake, let’s say that the video is considered “watched” if a user plays at least 75% of it, in an active window. In this case, we can create a custom trigger:

  • We’ll only select the Progress/Percentage/75 events, and just in case, Complete (be careful here, in case the platform we are sending the conversion to doesn’t detect duplicated hits correctly).
  • Then we identify the specific video by the ID in its URL. There are also other alternatives, such as filtering by page, etc.
  • While we’re here, we might as well take advantage of the detect visibility function, so we’ll add it as a condition. We’ll discard cases in which the user has navigated away from the area of visibility, even though the video keeps playing

So we’ll end up with the following:

Ejemplo trigger video avanzado

Once it’s been created, all we then have to do is add it as a trigger to the corresponding tag(s): AdWords, DoubleClick, Twitter, Facebook, Analytics hit for goals or funnels… whichever corresponds to each platform we wish to notify of the conversion. We won’t list any examples, as there are so many! ?.

Impressions and conclusions

We’re pretty pleased with our first trials of automated tracking. In particular, it’s worth noting that the tracking works with dynamic or lazy-loaded videos (i.e. videos that were not already included in the page’s original source code, but were loaded afterwards), which is something that always presented an additional problem for custom processors.

On the minus side, we’ve found some instances where tracking didn’t work, whether occasionally or not at all. We suspect that the tracking may fail where non-standard embedding code is used, or when the option of adding enablejsapi doesn’t work consistently, especially for videos that load “late”. We hope to continue investigating the issue, and if there are any bugs, we hope to iron them out.

Error-tracking is also missing, so for cases where information regarding errors is important, it may be better to continue using custom processors.

Returning to the plus side, we were pleasantly surprised to see that visibility detection is built in. Between this and the fact that it was already included natively in AMP, we’re gradually getting closer to a unified solution to another of the classic problems of advanced analytics.

Likewise, the inclusion of the provider field leads us to think that there may be scope for the integration of new video platforms in the future… or at least, for now, it gives us a shared data structure so that we can do it ourselves. 🙂