Reader Question: How Do I Track Lazy Loaded HTML5 Video with GTM?

A reader recently asked my how to track HTML5 video when the <video> tags are loaded on to the page on a link click.

Hi Ed,

I recently came across your “Complete Guide to Google Tag Manager” series, and purchased Part 2 after watching Part 1 on YouTube.

I am stuck on a complicated issue and thought to reach out to you. PillPack’s website has several educational videos hosted by HTML5 video players at different places on the site. I am seeking to track the following metrics on the various videos in Google Analytics: # of plays, # of pauses, and % of progress through the videos (for each video).

Here is a link to PillPack’s site for reference:

I was mainly using the custom HTML, custom javascript and instructions from here to implement tracking in Google Tag Manager: (

I got as far as seeing events firing in the debugger and in the data layer, however, all the events were firing upon page load rather than when I actually played or paused the videos. A second issue is I’m not sure how to differentiate multiple videos using this method. A third issue is that the video player is via a pop-up window (see website), and I’m not sure if this is having an impact on the incorrect tag firings.

Any help, resources or advice on how to set up tracking would be very much appreciated!

Thanks for the question.

Ah, video tracking. The bane of the digital marketers existence!

Well, not really. But it can be tricky due to the large number of JavaScript players available to choose from.

A brief overview of video tracking

Before getting in to the details of the question, you need to understand how most video players work, and can be tracked.

The website in question here is using Plyr. but pretty much all video players work in the same way.

The player is initialised by calling the setup method with a reference to an HTML element where the video will be shown.

The video player does it’s magic and injects the video into our DIV.

To know when a video’s play or stop button is clicked, a listener can be set up on the player instance:

And to track plays and stops in Google Analytics, notice how we also push events and video information to GTM’s dataLayer object, so we can easily create tags and triggers which execute on the stoppedVideo or playedVideo event and utilise the video data.

Back to the question…choices to make

In the case of the reader’s website, the developers have not implemented the video listeners or pushed any information to the data layer. If we want to track these videos we need to go one of two ways.

  1. Ask the developers to implement the data layer pushes (recommended).
  2. Hack something together using custom JavaScript in Google Tag Manger.

The first options is ALWAYS my recommended approach. But it isn’t alway possible but to internal processes, politics and timeframes.

For fun, let’s explore option 2.

(Going down this route requires JavaScript, CSS and HTML knowledge, plus a whole lot of hacking around until something finally works.)

Initialising video listeners with a Custom HTML tag in GTM

Usually, we could add our own event listeners to the video player instance in a custom HTML tag in Google Tag Manager. Calling the get method on Plyr’s JavaScript library with no arguments returns an array of video instance objects:

Loop through them all and add event listeners, as shown below.

But this won’t work for on

Why? Because the videos are not all initialised on page load. The video player is initialised after a visitor clicks a thumbnail (example shown in screenshot below). They are lazily loaded on to the page.

Pillpack video launcher

Our Custom HTML tag in GTM, which fires on page load or DOM load, therefore does not have access to the player instance (because it hasn’t yet been created by the Plyr).

That’s why the code the reader mentioned in the tutorial he linked to doesn’t work. It expects the video HTML elements to have been initialised when it runs.

There’s no method in the Plyr library to listen for videos being initialised either (there probably are in other video player libraries) so that option is out.

Workarounds and hacks

We could create a timer and check for new player instances every n seconds, but that feels a little bit of a hack to me. Would work though.

Another option would be to download the Plyr library from GitHub and customise it, adding a call back we could hook in to whenever a new player is initialised. However, we’d still have to get the developers to upload this new version of the library to the website. The whole point of this exercise is getting things done without them.

A workable solution

(I want to re-iterate what I said before. The most robust solution to most analytics tracking is to provide your developers which comprehensive data layer specifications, and in this case, ask them to write code to push information to the data layer when a video is initialised, played, stopped, etc. This solution is something you would use as a stop gap whilst that code is being implemented.)

An interim solution is to listen for clicks on any links which active a new video, and then attach listeners to the new video instance.

This code would be set in a Custom HTML tag in GTM. You’d also have to create variables to track the event data, and a Custom Event based trigger set to fire when event is ‘videoEvent’.

Pulling it all together

By now you should understand:

  • How JavaScript video players initialise content
  • How to listen for changes to a video player’s state
  • Why lazily loaded HTML5 videos cause problems, such is the case for
  • Why the video script used by the reader wasn’t working as expected
  • Why the recommended solution is to get the developers to implement a more complete data layer

Assuming the reader still wants to use the 3rd party script mentioned, and has no access to developer time, here’s the complete solution.

1. Re-write the video tracking script

I’m going to modify the video tracking script presented in the reader’s question to ensure the event listeners are added to lazily loaded video elements as well as those already present on the page.

Here’s the updated code:

2. Set up GTM

Create a new Custom HTML tag in GTM called JS Video Listeners. Copy the code above into it.

Create a new trigger called P DOM Ready to execute on DOM ready, and attach it to the JS Video Listeners tag.

The result should look like this:

GTM video tracking tag

Next, create 4 variables, called dl_event_category, dl_event_action, dl_event_label and dl_event_value. Each should be of type Data Layer and read the values being pushed to the data layer by the video tracking script.

I’ve shown an example below for the event action.

GTM Video Tracking Event Variable

Next, create a custom event trigger which will fire when the gaEvent event is pushed to the data layer by the video tracking script. Call it E Received Generic Event.

GTM received generic event trigger

For more information on generic events see this article.

Finally, create a Universal Analytics event tag to send the data to Google Analytics when the E Received Generic Event trigger fires.

GTM Received Generic Event

Save everything. Preview the container and check all is well. Then publish.


Video tracking isn’t always easy, especially when videos are being lazily loaded on to the page. But there is always a workaround using google old JavaScript and some Google Tag Manager magic.

I’ve you’ve enjoyed this article please do share it. And if you have any questions yourself drop me an email and you may get featured in a blog post!

Ed Brocklebank (aka Metric Mogul) is an analytics and digital marketing consultant. He helps business of all sizes become more data-driven through measurement, strategy and activation. He works as a Strategic Analytics Director at Jellyfish in London, as well as delivering training on behalf of Google and formerly General Assembly.