During our GTM+UA webinar I was asked about tracking YouTube videos with the help of Google Tag Manager and Universal Analytics. I quickly demonstrated how we’re doing it in our WASP playground.
Here’s a step by step guide to the macros, tags and rules required to track YouTube video embeds on your website.
A note for Google Analytics users: For sake of demonstration I’m showing Universal Analytics, but you could easily replace the Universal Analytics Event by a regular Google Analytics one and everything will work fine.
We will use the YouTube JavaScript API to expose user interactions with the video. In order for this to work, each of your YouTube embeds will need to include “enablejsapi=1” to the link of the video, for example:
<iframe src="//www.youtube.com/embed/Rvw0uxuYBCo?enablejsapi=1" width="420" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe>
Note: the “Is Youtube present” macro could be modified to automatically add the enablejsapi if it’s not there, but this will result in a quick flash of the Youtube frame.
Note: by default, related videos will be shown and tracked. If you want to disable this, add “&rel=0” to the Youtube embed link.
Under Behavior/Events/Top Events, you will see an event category named “video”, with event actions named “pause”, “play”, 0%, 25%, 50%, 75% and 100%. The event label will be the unique identifier of the video.
If you want to get details about how individual videos are performing, follow those steps:
You have two options here, either use this macro to automatically detect when a video is embedded on a page, or use a rule to include the Youtube Listener tag only on pages where you know there’s a video.
Macro Name: | Youtube is present |
Macro Type: | Custom JavaScript |
Custom JavaScript: | // Return "true" if there is at least one Youtube video on the page function () { for (var e = document.getElementsByTagName('iframe'), x = e.length; x--;) if (/youtube.com\/embed/.test(e[x].src)) return true; return false; } |
Macro Name: | event |
Macro Type: | Custom Event |
Macro Name: | dataLayer action |
Macro Type: | Data Layer Variable |
Data Layer Variable Name: | action |
Macro Name: | dataLayer label |
Macro Type: | Data Layer Variable |
Data Layer Variable Name: | label |
Tag Name: | Youtube Listener |
Tag Type: | Custom HTML Tag |
Firing Rule: | Youtube present |
HTML: | <script type="text/javascript"> // OPTIONAL: Enable JSAPI if it's not already on the URL // note: this will cause the Youtube player to "flash" on the page when reloading to enable the JS API for (var e = document.getElementsByTagName("iframe"), x = e.length; x--;) if (/youtube.com\/embed/.test(e[x].src)) if(e[x].src.indexOf('enablejsapi=') === -1) e[x].src += (e[x].src.indexOf('?') ===-1 ? '?':'&') + 'enablejsapi=1'; var gtmYTListeners = []; // support multiple players on the same page // attach our YT listener once the API is loaded function onYouTubeIframeAPIReady() { for (var e = document.getElementsByTagName("iframe"), x = e.length; x--;) { if (/youtube.com\/embed/.test(e[x].src)) { gtmYTListeners.push(new YT.Player(e[x], { events: { onStateChange: onPlayerStateChange, onError: onPlayerError } })); YT.gtmLastAction = "p"; } } } // listen for play/pause, other states such as rewind and end could also be added // also report % played every second function onPlayerStateChange(e) { e["data"] == YT.PlayerState.PLAYING && setTimeout(onPlayerPercent, 1000, e["target"]); var video_data = e.target["getVideoData"](), label = video_data.video_id+':'+video_data.title; if (e["data"] == YT.PlayerState.PLAYING && YT.gtmLastAction == "p") { dataLayer.push({ event: "youtube", action: "play", label: label }); YT.gtmLastAction = ""; } if (e["data"] == YT.PlayerState.PAUSED) { dataLayer.push({ event: "youtube", action: "pause", label: label }); YT.gtmLastAction = "p"; } } // catch all to report errors through the GTM data layer // once the error is exposed to GTM, it can be tracked in UA as an event! // refer to https://developers.google.com/youtube/js_api_reference#Events onError function onPlayerError(e) { dataLayer.push({ event: "error", action: "GTM", label: "youtube:" + e }) } // report the % played if it matches 0%, 25%, 50%, 75% or completed function onPlayerPercent(e) { if (e["getPlayerState"]() == YT.PlayerState.PLAYING) { var t = e["getDuration"]() - e["getCurrentTime"]() <= 1.5 ? 1 : (Math.floor(e["getCurrentTime"]() / e["getDuration"]() * 4) / 4).toFixed(2); if (!e["lastP"] || t > e["lastP"]) { var video_data = e["getVideoData"](), label = video_data.video_id+':'+video_data.title; e["lastP"] = t; dataLayer.push({ event: "youtube", action: t * 100 + "%", label: label }) } e["lastP"] != 1 && setTimeout(onPlayerPercent, 1000, e); } } // Crossbrowser onbeforeunload hack/proxy // https://developer.mozilla.org/en-US/docs/WindowEventHandlers.onbeforeunload window.onbeforeunload = function (e) { var e = e || window.event; // For IE and Firefox prior to version 4 if(e) e.returnValue = 'na'; // For Safari return 'na'; }; window.onbeforeunload = trackYTUnload; function trackYTUnload() { for (var i = 0; i < gtmYTplayers.length; i++) if (gtmYTlisteners[i].getPlayerState() === 1) { // playing var video_data = gtmYTlisteners[i]['getVideoData'](), label = video_data.video_id+':'+video_data.title; dataLayer.push({ event: 'youtube', action: 'exit', label: label }); } } // load the Youtube JS api and get going var j = document.createElement("script"), f = document.getElementsByTagName("script")[0]; j.src = "//www.youtube.com/iframe_api"; j.async = true; f.parentNode.insertBefore(j, f); </script> |
If you are using Google Analytics instead of Universal Analytics, simply change the Tag Type to Google Analytics and everything will work fine.
Tag Name: | Youtube Event |
Tag Type: | Universal Analytics |
Tracking ID: | UA-XXXXXX-Y |
Track Type: | Event |
Event Tracking Parameters: | |
Category: | {{event}} |
Action: | {{dataLayer action}} |
Label: | {{dataLayer label}} |
Firing rule: | Youtube event |
Rule Name: | Youtube present |
Conditions: | {{event}} equals gtm.dom AND {{youtube is present}} equals true |
Rule Name: | Youtube event |
Conditions: | {{event}} equals youtube |
That’s it! Now you can track Youtube video embeds on your own website thanks to Google Tag Manager and Universal Analytics.
Don’t forget to use Google Tag Manager “debug & preview” with WASP to make sure everything works fine before you publish.
This topic, and many more, are covered in our GTM+UA Master Class. Please visit the Cardinal Path training page for free and custom training options.
Check out the new, and up to date version by Nicky Yuen.
Hungry for more? Check out our annual Analytics Rising Virtual Conference. Sign up today!
Director of Strategic Services - Create innovative company-wide solutions and digital measurement strategies to deliver maximum value and insight for Cardinal Path clients.
One of the most common questions we get about GA4 isn’t really about GA4, itself.…
Using engagement data to improve website performance is a near-universal use-case for users of Google…
Google announced on April 23 that it will again delay third-party cookie deprecation (3PCD) in…
This website uses cookies.