How to track YouTube videos on your website

When you want to track YouTube videos embedded on your site, you need to set up custom tracking in Tag Manager. In this article, we’ll show you how to do it.

To set up YouTube video tracking, follow these steps:

  1. Go to Menu > Tag Manager.
  2. Navigate to Variables.
  3. Click + Create new variable.
  4. Name the variable. For example, YouTube is present.
  5. In Variable type, select Custom JavaScript.
  6. A variable for tracking YouTube videos in Piwik PRO.
  7. In Code editor, paste the following code:
  8. // 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.*\/embed/.test(e[x].src)) return true;
        return false;
    }
    A variable for tracking YouTube videos in Piwik PRO.

    Note: This variable returns “true” if the current page has a YouTube iFrame.

  9. Click Save.
  10. Navigate to Triggers.
  11. Click + Create new trigger.
  12. Name the trigger. For example, YouTube is present.
  13. In Event type, select Page view.
  14. A trigger for tracking YouTube videos in Piwik PRO.
  15. In Trigger conditions, set the following condition: YouTube is present is true.
  16. A trigger for tracking YouTube videos in Piwik PRO.

    Note: This trigger will fire a tag when a YouTube iFrame is on a current page.

  17. Click Save.
  18. Click + Create new trigger again.
  19. Name the trigger. For example, YouTube event.
  20. In Event type, select Event.
  21. A trigger for tracking YouTube videos in Piwik PRO.
  22. In Data layer event settings, set the following condition: Event name contains youtube.
  23. A trigger for tracking YouTube videos in Piwik PRO.

    Note: This trigger will fire a tag when the event is youtube. The youtube event is defined in the JavaScript code through the data layer that is presented in step 22. 

  24. Click Save.
  25. Navigate to Tags.
  26. Click + Create new tag.
  27. Name the tag, for example YouTube listener, and select Custom asynchronous tag template.
  28. In Tag HTML code, type the following code:
  29. <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.*\/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.*\/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 = "https://www.youtube.com/iframe_api";
    j.async = true;
    f.parentNode.insertBefore(j, f);
    </script>
    A tag for tracking YouTube videos in Piwik PRO.

    Note: This tag enables YouTube player API if it is missing and uses it to identify events like play, pause, complete, progress, and more. It then pushes an event to the data layer so that Piwik PRO can track it. For more about events in the YouTube player, see this article.

  30. In Tag triggers, click + Existing trigger.
  31. Select YouTube is present — a trigger created in step 13.
  32. A tag for tracking YouTube videos in Piwik PRO.
  33. Click Save.
  34. Click + Create new tag.
  35. Name the tag, for example YouTube tracking event, and select Piwik PRO Custom Event.
  36. In Piwik PRO Custom Event setup, set the following:
    • Category: {{event}}
    • Action: {{action}}
    • Name: {{label}}
    A tag for tracking YouTube videos in Piwik PRO.

    Note: This tag will send event data to reports in Analytics. By default, Tag Manager knows the value from data layer events, and we don’t need to set them as variables.

  37. In Tag triggers, click + Existing trigger.
  38. Select YouTube event — a trigger created in step 18.
  39. A tag for tracking YouTube videos in Piwik PRO.
  40. Click Save.
  41. Test your tags in debug mode.
  42. When you’re happy how the tags work, click Publish.

Now Piwik PRO will be tracking events on YouTube videos embedded on your website. You’ll be able to see tracked data in the custom event report and session log report.

Was this article helpful?

Be the first to rate this article.

Technical Support

If you have any questions, drop us a line at support_SPC@piwik_SPC.pro.

We’re happy to help!