• Courses
    • Courses
    • Course bundles
  • Blog
  • Resources
    • Youtube channel
    • E-books and Guides
    • GTM Recipes
    • View All Resources
    • GTM Community
    • GA4 community
  • Services
  • About
    • About
    • Contact
  • Login
  • Courses
    • Courses
    • Course bundles
  • Blog
  • Resources
    • Youtube channel
    • E-books and Guides
    • GTM Recipes
    • View All Resources
    • GTM Community
    • GA4 community
  • Services
  • About
    • About
    • Contact
  • Login

March 29, 2025

Google Tag Manager Video Tracking Guide: Beyond Youtube

Updated: March 29th, 2025

Tracking pageviews is far from enough to understand what website visitors are doing on your site. You should also consider other interactions, such as clicks, views of particular elements, video interactions, etc.

In today’s landscape of video players, the most popular embedded video player is Youtube (I have no stats to support this; just saying this based on what I’ve seen on other websites). But what if your website uses a different player (like Vimeo or a generic HTML5 player)?

That’s not a problem because you can track them with GTM.

I’ll show you how to track videos with Google Tag Manager. I’ll cover YouTube video tracking, Vimeo video tracking, and several other players as well. At the end of the article, I will also share ready-made GTM templates/recipes.

Subscribe and Get the Ebook - Mastering GA4 event tracking

Here’s what you will learn in this article

  • So, what’s the plan?
  • Chapter 1. How to track Youtube videos with GTM
    • Step 1. Create a Youtube Video Trigger
    • Step 2. Enable built-in Youtube video variables
    • Step 3. Create a Google Analytics 4 tag
    • Step 4. Test the setup
  • Chapter 2. Track Vimeo video player with GTM (custom solution)
    • It all starts with identifying the video player
    • Step 1. Create a variable “Is Vimeo player present on a page”
    • Step 2. Vimeo Auto-Event Listener
    • Step 3. Data Layer Variables and a Custom Event Trigger
    • Step 4. Create a GA4 Tag
    • Step 5. Test the setup
    • The entire process, in a nutshell
  • Chapter 3. Six GTM Video Tracking Recipes
  • Final words

 

So, what’s the plan?

First, we’ll look at the most common video tracking example in Google Tag Manager: Youtube video trigger. Then, I’ll show you how it’s done with a video player that GTM does not support by default – Vimeo.

And finally, I’ll also give you some ready-made solutions (recipes) designed for various embedded video players.

Ready? Let’s go.

Google Tag Manager Ebook Bundle

Chapter 1. How to track Youtube videos with Google Tag Manager

If you are in a hurry, I have created a ready-made Youtube video tracking recipe. Download it, import, configure it (according to instructions), and it will automatically start tracking Youtube videos on your website in no time.

But if you want to understand the ins and outs of YouTube video tracking, then continue reading.

Here are the steps you need to complete to track YouTube videos with Google Tag Manager.

Why would you want to configure YouTube tracking with GTM and GA4 if GA4 already offers built-in functionality? Well, GA4’s built-in YouTube video does not work on all websites, so sometimes, you might need to customize it.

Here’s how you can track YouTube videos with Google Tag Manager:

  1. Create a YouTube video trigger
  2. Enable built-in video variables in GTM
  3. Create a Google Analytics 4 event tag
  4. Test the setup and publish.

Let’s take a closer look at each step individually.

 

Step 1. Create a YouTube Video Trigger

It all starts with a trigger. In Google Tag Manager, go to Triggers > New > Trigger Configuration and choose Youtube Video, then enter the following settings:

You can change the Percentage threshold to anything you like; just separate them with a comma. Also, you can enable Pause, Seeking, and Buffering tracking. I typically track Start, Complete, and Progress (e.g., user watched 25% of the video).

Also, even though the Add JavaScript API support to all YouTube videos is an Advanced setting, I enable it by default because it increases the chance that YouTube video tracking will work.

 

Step 2. Enable built-in YouTube video variables

In Google Tag Manager, go to Variables > Configure and enable all video-related variables.

 

Step 3. Create a Google Analytics 4 tag

In this tutorial, I presume that you have already installed Google Analytics 4 via Google Tag Manager (and you have a Google Tag). If not, read this tutorial first.

Now, it’s time to send the YouTube video data to Google Analytics. In Google Tag Manager, go to Tags > New > Google Analytics > Google Analytics: GA4 Event and enter the following settings.

It seems like a lot is happening. Let me explain:

  • I recommend following the same naming convention for video tracking used in Enhanced Measurement. In the previous steps, I had only mentioned three details to capture – the start/ completion of the video and the percentage of video watched.
  • All the event parameters that I have included are optional. If you think that some of them are not valuable, go ahead and remove them. I (once again) decided to follow the naming convention of Enhanced Measurement.

In the triggering section, I select the previously created YouTube video trigger.

 

Step 4. Test the setup

Once you have completed all previous steps, it’s time to test. Enable the Preview and Debug mode, and navigate to the section of the page with the video player.

First, you should start seeing YouTube Video events in the preview mode. If you don’t see them, read this troubleshooting guide.

Click one of them and check whether your Google Analytics tag has fired.

If yes, confirm this by navigating to Google Analytics 4 DebugView to check if the events have registered there.

Note: If you want to use these details in your GA4 reports, don’t forget to register parameters as video_percent or video_title as custom dimensions because, for some reason, they are still not available by default.

Subscribe and Get the Ebook - conversion tracking handbook

Chapter 2. How to track Vimeo video player with Google Tag Manager (custom solution)

You might think, “YouTube tracking looks simple, but I have a different embedded video player on my website. What will work in my case? The built-in YouTube video tracking in Google Tag Manager won’t work. Instead, you need to find a custom solution.

 

It all starts with identifying the video player

Before worrying about the actual tracking, you must first identify what kind of video player it is. While it may be evident with most video players, this may differ with some.

If your case is the latter, do this. In your browser, open developer tools (in Chrome, that’s F12 (on Windows)) and then go to the Elements tab. Then click this button.

Now, click on the player. Now try to browse and locate some clues mentioning the player provider’s name. For example, in this case, the player that I’m inspecting is the JW player.

If you can’t find the name, it is probably an HTML5 video player.

Once you identify the name of the video player, just google [ video player name ] tracking with Google Tag Manager, and you should find some guide or tutorial.

Let’s imagine that, in our case, we see the “Vimeo” logo at the corner of the embedded video player.

 

Step 1. Create a variable “Is Vimeo player present on a page”

We will need to add lengthy code to the container to track Vimeo players with Google Tag Manager on a page. Loading that code on every page is not optimal and will affect the page loading speed, which is why we need to activate that code ONLY on those pages when the Vimeo player is embedded.

To do that, first, we need to create a Custom JavaScript variable and paste the following code:

function () {
  for (var e = document.getElementsByTagName("iframe"), x=0; x < e.length; x++) {
    if (/^https?:\/\/player.vimeo.com/.test(e[x].src)) {
      return true;
    }
  }
  return false;
}

If the page has a Vimeo player embedded in it, this variable will return true.

Then, create a Pageview trigger and use that Custom JavaScript variable in it. If the Vimeo player is present, this trigger will be activated. If there is no Vimeo player, that trigger will remain silent.

Check it in Preview and Debug mode, and you should get something like this.

 

Step 2. Vimeo Auto-Event Listener

Now, it’s the Vimeo Listener’s turn. A listener is a function (or a bunch of functions) built to keep looking for certain interactions on a page. In this case, the listener will be looking for Vimeo player interactions. If it spots one, it will make that data visible in the Preview and Debug mode.

Create a Custom HTML tag and paste the following code. The original code was created by Bounteous, but to make it more convenient for GA4, I have modified the code (a bit).

<script type="text/javascript" id="gtm-vimeo-tracking">

;(function(document, window, config) {

  'use strict';

  // The API won't work on LT IE9, so we bail if we detect those UAs

  if (navigator.userAgent.match(/MSIE [678]\./gi)) return;
  config = cleanConfig(config);

  var handle = getHandler(config.syntax);
  if (document.readyState !== 'loading') {
    init();
  } else {
    document.addEventListener('DOMContentLoaded', function() {
      init();
      document.addEventListener('load', init, true);
    });
  }

  function init() {
    var videos = filter_(selectAllTags_('iframe'), isVimeo);
    if (!videos.length) return;
    loadApi(function() {
      forEach_(videos, listenTo);
    });
  }

  function isVimeo(el) {
    return el.src.indexOf('player.vimeo.com/video/') > -1;

  }

  function loadApi(callback) {
    if (isUndefined_(window.Vimeo)) {
      loadScript('https://player.vimeo.com/api/player.js', callback);
    } else {
      callback();
    }
  }

  function listenTo(el) {
    if (el.__vimeoTracked) return;
    el.__vimeoTracked = true;
    var video = new Vimeo.Player(el);
    var percentages = config._track.percentages;
    var eventNameDict = {
      'play': 'play',
      'pause': 'pause',
      'complete': 'ended'
    };
    var cache = {};
    video.getVideoTitle()
      .then(function(title) {
        forEach_(['play', 'pause', 'complete'], function(key) {
          if (config.events[key]) {
            video.on(eventNameDict[key], function() {
              handle(key, title);
            });
          }
        });
        if (percentages) {
          video.on('timeupdate', function(evt) {
            var percentage = evt.percent;
            var key;
            for (key in percentages) {
              if (percentage >= percentages[key] && !cache[key]) {
                cache[key] = true;
                handle(key, title);
              }
            }
          });
        }
      });
  }

  function cleanConfig(config) {
    config = extend_({}, {
      events: {
        'play': true,
        'pause': true,
        'complete': true
      },
      percentages: {
        each: [],
        every: []
     }
    }, config);
    forEach_(['each', 'every'], function(setting) {
      var vals = config.percentages[setting];
      if (!isArray_(vals)) vals = [vals];
      if (vals) config.percentages[setting] = map_(vals, Number);
    });
    var points = [].concat(config.percentages.each);
    if (config.percentages.every) {
      forEach_(config.percentages.every, function(val) {
        var n = 100 / val;
        var every = [];
        var i;
        for (i = 1; i < n; i++) every.push(val * i);
        points = points.concat(filter_(every, function(val) {
          return val > 0.0 && val < 100.0;
        }));
      });
    }
    var percentages = reduce_(points, function(prev, curr) {
      prev[curr + '%'] = curr / 100.0;
      return prev;
    }, {});
    config._track = {
      percentages: percentages
    };
    return config;
  }

  function getHandler(syntax) {
    syntax = syntax || {};
    var gtmGlobal = syntax.name || 'dataLayer';
    var uaGlobal = syntax.name || window.GoogleAnalyticsObject || 'ga';
    var clGlobal = '_gaq';
    var dataLayer;
    var handlers = {
      'gtm': function(state, title) {
        if (state.indexOf('%') === -1 && state.indexOf('play') === -1) {
          dataLayer.push({
            event: 'video',
            video_provider: 'vimeo',
            video_action: state,
            video_title: title.toLowerCase(),
            video_percent: undefined
            });
        } else if (state === '0%'){
          dataLayer.push({
            event: 'video',
            video_provider: 'vimeo',
            video_action: 'start',
            video_title: title.toLowerCase(),
            video_percent: undefined
          });
        } else if (state.indexOf('play') === -1) {
          dataLayer.push({
            event: 'video',
            video_provider: 'vimeo',
            video_action: 'progress',
            video_percent: state,
            video_title: title.toLowerCase()
          });
        }
      },
      'cl': function(state, title) {
        window[clGlobal].push(['_trackEvent', 'Videos', state, title]);
      },
      'ua': function(state, title) {
        window[uaGlobal]('send', 'event', 'Videos', state, title);
      }
    };
    switch(syntax.type) {
      case 'gtm':
        dataLayer = window[gtmGlobal] = window[gtmGlobal] || [];
        break;
      case 'ua':
        window[uaGlobal] = window[uaGlobal] || function() {
          (window[uaGlobal].q = window[uaGlobal].q || []).push(arguments);
        };
        window[uaGlobal].l = +new Date();
        break;
      case 'cl':
        window[clGlobal] = window[clGlobal] || [];
        break;
      default:
        if (!isUndefined_(window[gtmGlobal])) {
          syntax.type = 'gtm';
          dataLayer = window[gtmGlobal] = window[gtmGlobal] || [];
        } else if (uaGlobal&& !isUndefined_(window[uaGlobal])) {
          syntax.type = 'ua';
        } else if (!isUndefined_(window[clGlobal]) && !isUndefined_(window[clGlobal].push)) {
          syntax.type = 'cl';
        }
        break;
    }
    return handlers[syntax.type];
  }

  function extend_() {
    var args = [].slice.call(arguments);
    var dst = args.shift();
    var src;
    var key;
    var i;
    for (i = 0; i < args.length; i++) {
      src = args[i];
      for (key in src) {
        dst[key] = src[key];
      }
    }
    return dst;
  }
  function isArray_(o) {
    if (Array.isArray_) return Array.isArray_(o);
    return Object.prototype.toString.call(o) === '[object Array]';
  }
  function forEach_(arr, fn) {
    if (Array.prototype.forEach_) return arr.forEach.call(arr, fn);
    var i;
    for (i = 0; i < arr.length; i++) {
      fn.call(window, arr[i], i, arr);
    }
  }
  function map_(arr, fn) {
    if (Array.prototype.map_) return arr.map.call(arr, fn);
    var newArr = [];
    forEach_(arr, function(el, ind, arr) {
      newArr.push(fn.call(window, el, ind, arr));
    });
    return newArr;
  }
  function filter_(arr, fn) {
    if (Array.prototype.filter) return arr.filter.call(arr, fn);
    var newArr = [];
    forEach_(arr, function(el, ind, arr) {
      if (fn.call(window, el, ind, arr)) newArr.push(el);
    });
    return newArr;
  }
  function reduce_(arr, fn, init) {
    if (Array.prototype.reduce) return arr.reduce.call(arr, fn, init);
    var result = init;
    var el;
    var i;
    for (i = 0; i < arr.length; i++) {
      el = arr[i];
      result = fn.call(window, result, el, arr, i);
    }
    return result;
  }
  function isUndefined_(thing) {
    return typeof thing === 'undefined';
  }
  function selectAllTags_(tags) {
    if (!isArray_(tags)) tags = [tags];
    return [].slice.call(document.querySelectorAll(tags.join()));
  }
  function loadScript(src, callback) {
    var f, s;
    f = document.getElementsByTagName('script')[0];
    s = document.createElement('script');
    s.onload = callCallback;
    s.src = src;
    s.async = true;
    f.parentNode.insertBefore(s, f);
    function callCallback() {
      if (callback) {
        callback();
        s.onload = null;
      }
    }
  }
})(document, window, {
  'events': {
    'play': true,
    'pause': false,
    'complete': true
  },
  'percentages': {
    'every': 25,
    'each': [0, 90]
  }
});

/*
 * v1.0.1
 * Created by the Google Analytics consultants at http://www.lunametrics.com
 * Written by @notdanwilkerson
 * Documentation: https://github.com/lunametrics/vimeo-google-analytics/
 * Licensed under the MIT License
 * Modified by Julius Fedorovicius at https://www.analyticsmania.com
 */
</script>

Don’t forget to assign the previously created Window Loaded Trigger:

Checkpoint! Let’s see what we’ve created so far:

  • We started with creating a Pageview Trigger, which checks whether there is a Vimeo video player embedded in the web page (thanks to a Custom JavaScript variable).
  • A Vimeo Auto-Event Listener (as a Custom HTML tag) fires when the Pageview Trigger mentioned above activates. Every time a Vimeo player interaction occurs, the listener will dispatch a Data Layer event with the following data:
    • Event Name: video (this value never changes)
    • video_action (play, progress, or complete)
    • video_percent
    • video_title
    • video_provider
  • If you want to test this now, enable the Preview and Debug mode, navigate to the embedded Vimeo player, and try interacting with it. You should start seeing video events on the Preview mode’s left side.
Subscribe and Get the Ebook - working with reports in ga4

Step 3. Create Data Layer Variables and a Custom Event Trigger

Google Tag Manager does not recognize Data Layer events (as triggers) or other data (as variables) by default. So if you wish to transfer some information to other tools (e.g., Google Analytics), you need to “teach” GTM to fetch certain information (with the help of Data Layer Variables).

After configuring them, it’s time to create a Custom Event Trigger. Vimeo Auto-Event Listener sends all interactions as Data Layer events under “video”.

dataLayer.push({
event: "video",
  ...
});

So the next thing you should do is to create a Custom Event Trigger which listens to ALL video events. Later, we will assign it to Google Analytics 4 Tag.

In GTM, go to Triggers > New > Custom Event and enter the following settings:

 

Step 4. Create a Google Analytics 4 Event Tag

Last but not least, Google Analytics. Now you need to send an event and pass the corresponding data. Create a new tag, select Google Analytics > Google Analytics: GA4 Event as Tag Type, and enter all three Data Layer variables.

Every time a video event is created, Google’s servers will receive a GA4 Event, with actual data dynamically replacing the default values in all three variables. The event name will highlight the status of the video.

 

Step 5. Test test test

As with all Google Tag Manager deployments, we need to test it. Enable GTM Preview and Debug mode, go to a page with an embedded Vimeo player, and click Play. If configured correctly, this will trigger a video event in Preview and Debug mode’s event stream. Click it and see whether the GA4 tag has fired.

Also, don’t forget to check Google Analytics DebugView reports. You can access them by navigating to Admin > DebugView.

 

The entire process, in a nutshell

  • We created a Custom JS variable that returns true if the page has a Vimeo player embedded.
  • Then we created a Pageview Trigger that triggers when it detects the embedded Vimeo video player in the web page (thanks to the Custom JavaScript variable)
  • Then, we created a Custom HTML tag (a Vimeo Auto-Event Listener). And it will fire on all pages where the Vimeo player is embedded. Important: even if you haven’t interacted with the player yet, that tag will still be fired.
  • Every time a Vimeo player interaction occurs, the listener will dispatch a Data Layer event with the following data:
    • Event Name: video (this value never changes)
    • video_action (play, progress, or complete)
    • video_percent (works only with progress events)
    • video_title
  • You have created Data Layer Variables and one Custom Event Trigger (for the video event).
  • Finally, you created a Google Analytics 4 tag that fires on the video event and will send the values of those 3 Data Layer Variables to Google Analytics.

Chapter 3. Six Google Tag Manager Video Tracking Recipes

Believe it or not, but the flow that I have described in the Vimeo player tracking section applies to a bunch of other non-Youtube video players:

  • HTML5 Video player (supports various players). The listener is created by David Vallejo.
  • JW Player. The listener is created by Pat Grady and David Vallejo.
  • Vidyard
  • Wistia. A solution created by the team of Bounteous.

Since most GTM Recipes are created by distinct authors, their naming convention is also diverse. So I unified them a bit.

They will be using GA4’s naming convention (e.g., parameters such as video_title, video_provider). All recipes will send video_progress and video_complete events. Some recipes will send video_play (while others will use video_start). That’s because some recipes send video_play every time a visitor hits play in the same video (even though he/she clicked pause several seconds ago). To avoid duplicate video_start events, I went with video_play sometimes.

Maybe I will find more time in the future to fix this.

Feel free to download any of these Google Tag Manager Recipes and start tracking video players in no time. Didn’t I tell you that Google Tag Manager Video Tracking was pretty easy?

HTML5 video Tracking Recipe for Google Tag Manager

HTML5 Video Tracking Recipe

Tracks interactions of the HTML5 video player (play, pause, etc.)
Get the recipe

JW Player Tracking Recipe for Google Tag Manager

JW Player Tracking Recipe

Tracks interactions of embedded JW player (play, pause, complete, etc.).
Get the recipe

Vidyard Listener Recipe for Google Tag Manager

Vidyard Tracking Recipe

Automatically tracks interactions of the embedded Vidyard player (play, pause, etc.).
Get the recipe

Vimeo Recipe For Google Tag Manager

Vimeo Tracking Recipe

Tracks interactions of the embedded Vimeo player (play, pause, etc.).
Get the recipe

Wistia Tracking Recipe for Google Tag Manager

Wistia Tracking Recipe

Automatically tracks interactions with embedded Wistia videos.
Get the recipe

Youtube Tracking Recipe Image

YouTube Tracking Recipe

Automatically tracks interactions with embedded YouTube video players on your site.
Get the recipe

I’ve noticed that the HTML5 recipe doesn’t play well with others (well, at least some of them). Sometimes, it overtakes all interactions, and other video listeners stop working. So ensure that HTML5 auto-event listener does not fire on the same page as the JW player, etc.

Everything else should be fine. If you notice any bugs, please let me know.

 

Video tracking with Google Tag Manager: Final words

When it comes to video tracking with Google Tag Manager, the first thing that comes to mind is the tracking of embedded YouTube videos.

I don’t blame you since this is the world’s most popular video hosting platform.

But if you are dealing with a non-youtube video player, that is still possible with some custom solutions.

In this blog post, I’ve explained how you can track YouTube and non-youtube videos embedded on your site.

To save you some time, I’ve also included a bunch of recipes you can download, import, configure, and start tracking videos in minutes. Just download any of them, import them to your GTM account, and start tracking videos in the blink of an eye.

All these Google Tag Manager video tracking solutions follow the same principle, so once you master one, you’ll conquer all of them.

Julius Fedorovicius
In Google Tag Manager Tips
78 COMMENTS
CW
  • Sep 20 2017
  • Reply

Thanks for this! Downloaded the HTML5 container & implementation went smoothly, but when I track in GA in real-time, I'm seeing the following -
undefined (category) - undefined (action)
Video - Pause
Video - Play

The undefined numbers are skyrocketing while the actual 'Video' events remain pretty conservative. I'd still consider myself green when it comes to GTM, yes, but everything looks okay on the back end - references are in place for the event categories & such, but they're showing up as 'undefined' when I preview.

Thank you!

    Julius Fedorovicius
    • Sep 20 2017
    • Reply

    Hi,

    Maybe you have entered wrong keys in the Data Layer variable? Those keys are case sensitive. It means that variableName does not equal to variablename. You can share with me a link to your preview and debug mode so I could take a closer look.
    If you don't want to post it in public, shoot me an email to julius [at] analyticsmania.com.

    Cheers

      CW
      • Sep 20 2017
      • Reply

      Awesome - thanks for the prompt reply, Julius! Will email you separately.

    CW
    • Sep 21 2017
    • Reply

    UPDATE! Looks like this 'undefined' issue was probably caused by server maintenance, as everything appears to be firing properly today.

    The variables automatically populated in the format of 'eventLabel', but the reference in the tag is to 'gaEventLabel' - just make sure the variables are updated to match the script.

    Also, since our client's videos were uploaded with a random string of letters/numbers as the URL, I changed the event label to reference the page path that the video was being viewed on instead - that way we could clearly see which topic (& therefore, which video) was being viewed. Worked for our particular case, but may not work for everyone.

    Anyway, the HTML5 container is awesome & everyone should implement it. Thanks Julius!

Meg
  • Sep 26 2017
  • Reply

Thanks so much for all of this - I have managed to get embedded Vimeo videos sorted perfectly, however I am having trouble trying to figure out how to track Vimeo videos that load in a PopUp window ... I am not sure how to tell GTM to fire the tag after the pop up is opened ... do you have any information on how to do this that you could point me at?

    Julius Fedorovicius
    • Sep 26 2017
    • Reply

    Without knowing the full context, I'd say that maybe you should try to initiate the Vimeo listener when the certain button is clicked (which opened the video popup).

      Dan
      • Feb 3 2021
      • Reply

      I am curious if there is a tested solution for this as well.

Jannette
  • Nov 14 2017
  • Reply

This is great! One issue. When I'm in preview mode, I can see that the data layer is being populated with the appropriate video category, actions and label. I see it progress with actions for '50%', 'Paused video' and '100%', etc... However, when I look in Real Time events in GA, the only video category ever is 'Video' and the only action ever is "Play". I don't see the other actions - or even what they're defined as. It's strange is that the event action is 'Played video' - but in GA the event action is 'Play'. And the event category should be 'HTML5 Video' but in GA the event category is just 'Video'. Why the discrepancy? Appreciate your help!

    Julius Fed
    • Nov 14 2017
    • Reply

    Hey,

    1. Make sure that you have removed all filters from Real-time reports. They are displayed as blue tags (above the real-time reports)
    2. Make sure that you did not add another video listener (by accident).
    3. If you want me to do a further troubleshooting, send me an email to julius [at] analyticsmania.com with the following screenshots:
    a) Preview and Debug console (Data Layer Tab) once the video event is dispatched.
    b) Settings of Google Analytics event tag
    c) Settings of the trigger which fires that Google Analytics event tag.

Jackson Y
  • Nov 19 2017
  • Reply

Hi, I have implemented the vimeo tracking. It's working awesome.

Just a quick question:
I assume the Event Action (25%, 50%, 75%) are fired when they meet the threshold.. that means, if I want to find out how many people viewed 25%, I will have to take 50% deduct by 25% to get the actual viewers that viewed 25%, am I correct?

So its a compounding summation?

Is there an easier way that each percentage are unique to their own?

    Julius Fed
    • Nov 21 2017
    • Reply

    Hey,

    With this tracking, you cannot be sure that a visitor viewed 25% or 50% percent. It's possible that a user skipped video to 24%, then the event fired at 25% threshold. Without further hesitation, a visitor skipped to 49% percent and another event of 50% fired.

    As a result, you'll have two events in Google Analytics, 25% and 50%. But actually, in total, a person viewed only about 5 percent of a video. These listeners are not so smart to calculate the REAL duration of the watched video.

    I would not depend on a calculation you suggested, although I have nothing better to offer :)

    I believe that Google Tag Manager's built-in Youtube trigger now tracks how much a visitor viewed of your video.

      Jackson Y
      • Nov 21 2017
      • Reply

      Ah yes, but I am using Vimeo, so I am not so sure the YouTube listener will be tracking that.

      Oh speaking of the video skipping, it won't happen on my site with vimeo, because I have hid all the titles and timebar.

      Thanks for this great piece of article anyway!

Sameek
  • Feb 1 2018
  • Reply

So I tried implementing exactly the same example as mentioned above but the data layer is not being pushed on click of the video . The auto event listener tag is getting fired though. Can anyone please advice what could be the possible reason for the problem?

Thanks

    Julius Fed
    • Feb 1 2018
    • Reply

    Hi, which listener are you using and which video player do you wish to track (the web address of the video would be very helpful)? Usually, the videos are not tracked by listeners if that video appears in a popup.

Bronson O'Quinn
  • Feb 19 2018
  • Reply

This is great! Thank you so much.

The only issue I've encountered is that some of my client's HTML5 videos come from Facebook embedded iframes. Because these URLs don't have extensions, they return the Label "(not set)". Their markup doesn't have any useful identifiers, though, so I'm wondering if there's a way to just skip them and analyze them separately?

Here's an example of the markup to see what I mean:

    Julius Fed
    • Feb 19 2018
    • Reply

    You could create a trigger exclusion which does not fire the video event when the eventLabel = (not set), or something like that. This way you'd skip all video events which are from that strange player.

    Honestly, I have never tracked Facebook embedded videos before, so I cannot give you precise tips. Sorry.

Falk
  • Mar 9 2018
  • Reply

Could this also track the # of minutes a certain video was watched per month? And # of unique viewers per video per month? Could you point me in the right direction of how to get that configured with Google Analytics & VIMEO? (And if Vimeo BUSINESS would be required (which integrates with GA) or if VIMEO PRO would be enough.) Thanks!! :)

    Julius Fed
    • Mar 14 2018
    • Reply

    Hi, no idea what Vimeo PRO is so I cannot give you advice here.

    As for # of watched minutes, this would require more custom JavaScript and unfortunately, I'm not the right guy to write it (my JS skills are too limited). But here's the idea (maybe you'll find some developer who could help you):
    - A visitor watches a video. When the video completes, custom JavaScript could fire a dataLayer event with a custom metric, a number of watched minutes. Not custom dimension but custom metric. That event could be passed with GTM GA Event tag to Google Analytics (with that custom metric)
    - When a visitor watches a bit of some video and tries to leave the page, another custom JavaScript code should fire a data layer event, also with custom metric (number of minutes watched). That event should also be handled by GTA GA Event tag.

    As for a number of unique viewers per video, go to event reports in GA, click the youtube event and drill down till you reach Event Label (which is video title). In that report, you'll also see "Unique events" metric which is what you need. Also, don't forget to change the date to 30 days.

Falk
  • Mar 14 2018
  • Reply

Thank you very much for the detailed reply, Julius!
I found a programmer on Upwork who will/can implement what I am looking for.
I will pass this on as food for thought. Thanks again!!

Cee
  • Mar 27 2018
  • Reply

Thank you, very helpful. Does it track Brightcove video as well?

Thank you!
C

    Julius Fed
    • Apr 3 2018
    • Reply

    Hi, I haven't tried it. The best way for you to find out is to try by yourself :)

Becca
  • Apr 6 2018
  • Reply

Hi!

Relatively new to Google Tag Manager/GA and your blog has been an amazing help! Quick question for you - I installed the YouTube container from the link I copied below. THINK I set-up the proper goal in GA.

In preview mode, I see the tags firing properly on the site, but I don't see any corresponding event information in GA real-time view. Any thoughts I where I messed up? Do I need to set-up custom metrics to get the information?

Thank you!!

https://www.analyticsmania.com/google-tag-manager-recipes/youtube-built-in/

    Julius Fed
    • Apr 6 2018
    • Reply

    Hi, you probably inserted the Google Analytics Settings Variable in the GA Tracking ID field of the Google Analytics Tag. GA Settings Variable must be inserted ONLY in the GA Settings drop-down.

      Becca
      • Apr 7 2018
      • Reply

      Thank you! I really appreciate your reply.

Profesor Berkeley
  • Aug 3 2018
  • Reply

Is it posible tracking Spotify videos? How I do that?
Could you direct me? throw me a little light about it? Thank you!

    Julius
    • Aug 3 2018
    • Reply

    I never tried it. Import HTML5 video tracking recipe and give it a try. Maybe it will work.

Alexandre Sattamini
  • Sep 21 2018
  • Reply

Hello Julius

I have a little issue with this implementation. It did work just fine in the beginning. But then I realized something:

My website has an online course platform where the user can watch different videos from one single discipline. The thing is that the URL does not change. Videos are accessed through clicks that do not change de URL. It is like a dynamic JavaScript. So I noticed the first video play is captured, but not the following ones.

Can you help with any insight about that?

    Julius Fedorovicius
    • Sep 24 2018
    • Reply

    Hey, here's an idea (but I haven't properly tried it so beware and test it properly):
    - Use Lunametrics custom youtube video listener.
    - Fire it every time a video player appears on the screen (with help of Element Visibility trigger).

    In theory, every time a Lunametrics code is fired, it should check the page for new players available. However, take this with a grain of salt and test it properly.

      Alexandre Sattamini
      • Sep 24 2018
      • Reply

      Hey Julius. Thanks a lot. I will try it.

      In fact I got some conflict between the vimeo javascript tag (custom js) with the site’s code. Users reported some autoplay issues

      But I know this is normal with custom javascript tags

      I will try the option you pointed

Tanguy
  • Nov 7 2018
  • Reply

Hi!
I just implemented the YouTube recipe on a WordPress websites. It works fine on classic content, but popup videos loaded through the Elementor page builder won't be tracked. Do you have an idea how I could solve this?

    Tanguy
    • Nov 9 2018
    • Reply

    I added the the visibility trigger, which works fine for this. However the YouTube Video trigger won't fire after this one. Any tips to connect both?

      Julius Fedorovicius
      • Nov 11 2018
      • Reply

      You don't need to connect two triggers (I mean Youtube trigger and the Visibility trigger). First of all, try to implement the Lunametrics solution https://www.bounteous.com/insights/2015/05/11/updated-youtube-tracking-google-analytics-gtm?ns=l. Maybe it will work out of the box.

      If it does not, then use the Visibility Trigger to fire Lunametrics' Youtube Tracking Listener. Meaning that once the popup appears, then launch the Youtube Listener (Custom HTML tag). That Listener will start listening to Youtube Player's interactions and will send the interactions to the Data Layer. After that, create the Custom Event trigger to catch those Youtube interactions.

        Dan
        • Feb 3 2021
        • Reply

        Are you saying regardless of whether the video is in a modal/popup or embedded on the page it will be tracked? All that needs to be changed would be using the Element Visibility trigger instead of a the
        Page View - DOM Ready trigger?

Leslie
  • Jan 1 2019
  • Reply

Hello there! Thank you for your awesome work! I was curious, is there a recipe that you recommend or have for "Flowplayer" Thank you!

    Julius Fedorovicius
    • Jan 2 2019
    • Reply

    I haven't tried to track that player. Have you tried the HTML5 video recipe?

      Leslie
      • Jan 12 2019
      • Reply

      I'm working to set that up. But I'm asking about flowplayer because we have several players on our site and I want to track all of them including flowplayer.

        leslie
        • Jan 14 2019
        • Reply

        hello again! now I see what you were asking. HTML5 recipe handles flowplayer too. awesome! it seems to be working :)

Simon
  • Jan 23 2019
  • Reply

Hi Julius,
I've implemented the HTML5 recipe on a clients site, however they have 2 videos present and I only would like to track one of them. One is in the header and on loop, so doesn't need tracking.

The one I need tracking is near the bottom of the page - https://www.forzafinance.co.uk

GTM is firing for both, but how do I explictly state it to only push play data to GA for the 2nd video?

Thanks in advance.
Simon

    Julius Fedorovicius
    • Feb 1 2019
    • Reply

    Hey, Simon. With every dataLayer.push there is a variable called eventLabel. You can use it to distinguish which video is playing.

    That header video's eventLabel is "forza-vid-web-2.mp4".

    So you could update your Custom Event trigger to ignore those events that contain "forza-vid-web-2.mp4" eventLabel belonging to that header video.

Jana
  • Jan 28 2019
  • Reply

Hi Julius, thank you for sharing your knowledge. It helped me a lot. I have a question regarding the interpretation of the data being sent to GA. I am struggling to understand which number indicates the amount of users actually watching the video (no matter the lenght)? Because it is my unterstanding that one user who constantly pauses and jumps further in the timeline can trigger multiple actions like 25% and paused video.

Or do i have to elimiate all the other actions in the javascript part in ordner to track unique amount of users who came in contact with the video?

    Julius Fedorovicius
    • Jan 28 2019
    • Reply

    Hey. To answer that question, create an advanced segment in GA and include sessions with at least one "video play" (or whatever you called those actions). Then (with that segment selected) go to Audience > Overview and you'll see the number of all users that are included in that segment. That's the number of users who have played the video (regardless of the watched length).

      Jana
      • Jan 28 2019
      • Reply

      Thank you so much!

Santiago
  • Mar 28 2019
  • Reply

Hi,
I also had the GA variable inserted both on the drop down and on the overwrite. I unselected overwrite and now it's tracking in google analytics (before I could see the events in the datalayer but not in google analytics). I also was using duracell's GTM plugin and had selected the media event's so I had 2 listeners running at the same time.
Now it works. Thanks very much for this!

tania
  • Jul 15 2019
  • Reply

You rock Julius! Thanks so much!

danny
  • Oct 16 2019
  • Reply

hello Julius, i have 2 videos in one page. the first video is in html5 and second video is youtube embed. i'm using your html5 video container. and it only tracks the youtube video events. why can't it track the html5 video?

    Julius Fedorovicius
    • Oct 23 2019
    • Reply

    Maybe that video player is very much modified, therefore, the HTML5 listener cannot spot it. It's difficult to give you advice without knowing more information.

Tanguy
  • Jun 8 2020
  • Reply

Hi and thanks for this very useful method.

I've got a Vimeo video embed on my homepage (WP using Elementor builder), I followed the steps closely but I can't make it work.
In debug mode the cHTML - Vimeo Listener Tag fires properly but nothing happens in the events list when I interact with the video.

Any clue?
Thanks!

    Julius Fedorovicius
    • Jun 8 2020
    • Reply

    With that amount of information you provided, not really :)

Chris
  • Jun 26 2020
  • Reply

How would you set up a custom report in GA to get the best insights? Now all the values from Event action(look-up table) just split up the data for the different videos.
Event label - Video titel + page path
Event action - look-up table

Thank you!!

    Julius Fedorovicius
    • Jun 26 2020
    • Reply

    Depends on your question/hypothesis. What question do you want to answer? An example of a question might be: do visitors who have watched the video tend more to convert? In that case, you can create an advanced segment where a visitor watched any video and then converted. Another segment might be all users. Is that advanced segment performing better?
    By having that segment in mind, you can also check video titles. Which video titles are appearing more often in the session of "converted visitors".

    This might be one of the examples.

    First, you raise a question. Then you try to answer that with the data you have. Simply looking at a certain report without having anything particular in mind will get you nowhere (at least in most cases from my experience)

      Chris
      • Jun 26 2020
      • Reply

      Thanks, Ok now I understand how to use the information I receive.

Steven
  • Jul 24 2020
  • Reply

Hi Juluis,

I work for a church that has started using Living as One (probably a more niche video host that's geared towards churches) I was wondering if you knew of anyone building recipes for live stream videos that might work for tracking that? I've tried all the containers here to see if they would work and none did.

    Julius
    • Jul 25 2020
    • Reply

    Hi, live stream videos work in a different way and ready made listeners don't work - just as you have found out.

    You would need to cooperate with a developer here and he/she should check if it is technically possible to track those players at all.

Al
  • Aug 12 2020
  • Reply

hi julius,

is there any way to create automated email triggers linked to video progress? I.e. if a subscriber only watched 25%, they get a certain email but 50% gets a different one, so on so forth? or do i need to use a completely different method to do that? basically i am trying to create an automated marketing system that tracks individual behaviour on consuming my videos so my response is appropriate not just one-ring-to-rule-them-all method. and not break the bank doing it. thanks in advance!

    Julius
    • Aug 12 2020
    • Reply

    I would not recommend using GTM for that (GTM can be blocked by ad blockers). Also, you would need to do some additional coding or integrate some email marketing platform. I would be looking for some other solution for this and, most likely, cooperate with a developer to integrate it.

Laura
  • Sep 15 2020
  • Reply

Hi!! I can notice in my DataStudio report that the event was triggered when the person viewed 10% of the video, then another trigger for 25% progress, then another one at 50% and so on... all of these "events" came from the same person (because, of course, the person watched the video until the end and all my progress triggers were fired.

How do I make GTM tell Analytics to only count one trigger once the final action as happened? I mean: if the person watched it completely, Analytics Label should say: watched (or finished). But, on the contrary, I am counting multiple events for the same person: when they START watching the video, when they make multiple progress and when they have finished watching the video. How do I fix this? I am getting heaps of events in my data now.

Thanks,
Laura

    Julius Fedorovicius
    • Sep 15 2020
    • Reply

    Update your custom event trigger. Include an additional condition where the action is related just to a completed video. The exact settings depend on the video player.

    Or you can create a filter in Data Studio to include only those events that are related to the "video completed" event.

Tammy Allen
  • Dec 14 2020
  • Reply

Hi Julius,

Really appreciate this guide. I followed your YouTube steps but did not yield the desired results...instead of seeing 'YouTube Video' in the side panel, all I see is 'Click' with no tags fired. Any insight as to why?

Tammy

    Julius
    • Dec 14 2020
    • Reply

    Hi, read this https://www.analyticsmania.com/post/youtube-tracking-google-tag-manager-solved/

Brittney
  • Feb 8 2021
  • Reply

Hello,

I was thrilled to find the HTML5 video tracking GTM json. I've implemented in GTM and it works in preview mode, however, it does not work once deployed. There is nothing in realtime for videos and I've even waited a few days and see no history of video plays.

What could be going wrong with this?

    Julius
    • Feb 8 2021
    • Reply

    Hi, maybe you will find some solutions here https://www.analyticsmania.com/post/google-analytics-real-time-reports-not-working/

      Brittney Wilson
      • Feb 9 2021
      • Reply

      Julius,

      You are amazing.This guide had the exact answer.

      In the "Tracking ID" field I was trying to use a variable that was the tracking ID. Once I copied the tracking ID into that field directly, magically it started working.

      I still don't quite understand how it seemed to work fine in preview, as I don't see any changes in the preview.

      Thank you for your assitance.

charles
  • Mar 3 2021
  • Reply

Hi, do you have any guide on how to setup Google Tag Manager for Uscreen videos?

    Julius
    • Mar 3 2021
    • Reply

    No

Moghise
  • Dec 31 2021
  • Reply

Hello.
The video I wanted was uploaded to another video sharing site.
How can I track it in Tag Manager?
The html5 and youtube method is not practical for me.

    Julius Fedorovicius
    • Jan 4 2022
    • Reply

    Try to find out what is the provider of that other site. Then google is they support GTM tracking. If not, you are out of luck.

Brendan Butler
  • Jan 18 2022
  • Reply

Hi Julius,

Thanks for the recipes and tips. I had a question. We use the built in vimeo integration to track all our vimeo videos on episerver. Basically you add your tracking code into the vimeo account. I have now been tasked with tracking a self hosted HTML 5 video. Will the recipe for html you have posted play well with our vimeo implementation? I ask as analytics and reporting are essential to the business so I can't make a mistake. Have you ever seen it cause a problem with vimeo and if so any advice to avoid them?

    Julius Fedorovicius
    • Jan 26 2022
    • Reply

    Never tried this. The best way for you to find out is to try and see what happens.

Eileen
  • Mar 28 2022
  • Reply

This might be a dumb question, but I'm relatively new with GTM. I'm trying to track an HTML5 video that is running across different pages on our website. Would I have to create a tag for each page, or is there a way to track it with one tag? The video is hosted on our website.

    Julius Fedorovicius
    • Apr 13 2022
    • Reply

    No need to create separate tags for each video

Brianna
  • Mar 10 2023
  • Reply

Hi! I'm trying to create 3 different YouTube videos on a singular landing page with no luck of them firing on Tag Assistant. They all were built in on the site using Elementor, so there is no click class, text, or other element codes on the back end to identify. Any tips would be appreciated!

Kuldip
  • Mar 14 2023
  • Reply

Hi, I've used the Vimeo recipe to install the tags and tested everything including the GA4 debug view and everything seemed to be working fine. However, I've since noticed the vimeo_video tags only fire on certain videos and not others. Where its not firing the the event listener loads. Its only then that playing and pausing doesn't trigger the tag.

I'm using wordpress and the issue seems to be related to videos on a particular content types. Any idea of how I can trouble shoot this?

Colin Hardie
  • Oct 30 2023
  • Reply

Great guide as always. I got as far as adding the triggers, the tags and the variables and witnessing the Youtube video fire just fine in Debug mode.

I'm unclear how I then make this appear within my GA4 account though. Anyone got a steer for me?

Manuel
  • Feb 21 2024
  • Reply

Hello,

First of all, thank you very much for the Vimeo script. I wanted to share some thoughts that might be of interest and could help to improve the script. These are minor things but could be helpful for readers, as they initially caused me some confusion.

Regarding the handler, I have removed the 'ua' and 'cl' parts in my case because I didn't see the logic, especially for 'cl', which if I'm not mistaken, is from Urchin.

Similarly, even though the 'gtm' handler is initialized by default if not specified, I think it would be helpful to include in the initialization part the syntax object with the type 'gtm'. It means:
})(document, window, {
'syntax': { 'type': 'gtm' },
'events': {
'play': true,
'pause': false,
'complete': true
},
'percentages': {
'every': 25,
'each': [0, 90]
}
});

Also, in the part that checks if the browser is less than IE9, perhaps trigger an event to see in which cases videos are not tracked, although this could be analyzed from browsers using GA4.

Thank you very much for this great post

Ali Dan-Bouzoua
  • Mar 4 2024
  • Reply

Integrate with Google Analytics

JWP does not support GA4 via Google Tag Manager (GTM).

https://docs.jwplayer.com/platform/docs/analytics-integrate-with-google-analytics

John
  • Apr 25 2024
  • Reply

I've implemented the Vimeo version and it's working great; however, it would be really useful to also capture the video_URL, as we have some videos that have the same video title for both landscape and portrait variations on the same page and it would be helpful to be able to differentiate between the two.
Is there an easy way of amending the custom script to include this element, or would I need to engage a developer to amend the code?

Chris
  • Oct 4 2024
  • Reply

Hi there, this worked like a charm for YouTube, thank you. I also use Amazon S3 embedded videos (membership access). Do you have videos on that? I'd love to see those. Your videos are very easy to follow and understand. That is appreciated.

    Julius Fedorovicius
    • Oct 4 2024
    • Reply

    I don't have tutorials on that.

Leave a comment Cancel reply

Your email address will not be published. Required fields are marked *


 

Hi, I'm Julius Fedorovicius and I'm here to help you learn Google Tag Manager and Google Analytics. Join thousands of other digital marketers and digital analysts in this exciting journey. Read more
Analytics Mania
  • Google Tag Manager Courses
  • Google Tag Manager Recipes
  • Google Tag Manager Resources
  • Google Tag Manager Community
  • Login to courses
Follow Analytics Mania
  • Subscribe to newsletter
Recent Posts
  • Google Tag Manager Server-Side Tagging with Stape
  • How to Preserve Ad Click IDs with Server-side Tagging
  • LinkedIn Conversions API with Google Tag Manager. The Guide.
Analytics Mania - Google Tag Manager and Google Analytics Blog | Privacy Policy
Manage Cookie Settings