YouTube Tracking In Google Analytics & Google Tag Manager

YouTube Tracking In Google Analytics & Google Tag Manager

By /

May 11, 2015

blog-youtube-google-analytics

UPDATE: Now includes percentage viewed tracking.

My colleague Sayf Sharif has long been an advocate of tracking YouTube videos with Google Analytics. Our LunaMetrics YouTube tracking script has been copied, cloned, forked, and borrowed more than a few times. It’s time to bring our script up to date with the latest changes in Google Analytics and Google Tag Manager.

Also, Google recently finished the process of deprecating version two of their data API, which our script has depended on for fetching video titles. If you are using an old version of the script, you’ll see all of your videos titles set to https://youtube.com/devicesupport as of a few days ago.

After a little tinkering, we’ve updated the GitHub repo with version 7 of the illustrious LunaMetrics YouTube Google Analytics tracking code. Let’s take a look at what’s inside.

What’s New

This latest version is a plug-and-play tracking solution for tracking user interaction with YouTube videos in Google Analytics. It will detect if Google Tag Manager, Google Analytics (Universal), or Google Analytics (Classic) is installed on the page, in that order, and fire events when users interact with the video.

It includes support for delivering hits directly to Universal or Classic Google Analytics, or for pushing Data Layer events to be used by Google Tag Manager. It also supports percentage viewed tracking. You can find the code on our GitHub repo.

Installation

This plugin will play nicely with any other existing plugin that interfaces with the YouTube Iframe API, so long as it is loaded after any existing code. Otherwise, if another function overwrites the window.onYouTubeIframeAPIReady property, it will fail silently.

Universal or Classic Google Analytics Installation:

The plugin is designed to be plug-and-play. By default, the plugin will try and detect if you have Google Tag Manager, Universal Analytics, or Classic Google Analytics, and use the appropriate syntax for the event. If you are not using Google Tag Manager to fire your Google Analytics code, store the plugin on your server and include the lunametrics-youtube-v7.gtm.js script file somewhere on the page. You can host the script on your own server, or you can make use of the freely hosted jsdelivr copy.

Google Tag Manager Installation

Create a new Custom HTML tag and paste in the below:

In the space between the <script> and </script> tags, paste in the contents of the lunametrics-youtube.gtm.js script, found here. You can set the Trigger to All Pages, or you can use a Custom JS Variable to detect if a YouTube video is present and use that instead, like so:

Configuration

Once everything installed on your own site, this script will fire a Google Analytics event with the following settings:

  1. Event Category: Videos
  2. Event Action: (Action, e.g. Play, Pause)
  3. Event Label: (URL of the video)

Configuring Which Events Fire

If you are not using Google Tag Manager to fire your Google Analytics code, you might want to configure the script to fire or not fire certain events. By default, it will fire:

  • Play events
  • Pause events
  • Watch to End events
  • 10, 25, 50, 75, & 90% View Completion events

To change which events are fired, edit the configuration at the end of the script. For example, if you’d like to fire Play events and not fire Pause events:

The available events are Play, Pause, and Watch To End. These are all enabled by default, which you can see and modify at the bottom of the script file.

Forcing Universal or Classic Analytics

By default, the plugin will try and fire Data Layer events, then fallback to Universal Analytics events, then fallback to Classic Analytics events. If you want to force the script to use a particular syntax for your events, you can set the ‘forceSyntax’ property of the configuration object to an integer:

Setting this value to one of the following numbers:

  • 0 will force the script to use Google Tag Manager events
  • 1 will force it to use Universal Google Analytics events
  • 2 will force it to use Classic Google Analytics events

NEW – Enabling Percentage Viewed Tracking

By default, percentage viewed tracking is enabled. Configure it by adjusting the percentageTracking object’s properties at the end of the script. The object has two properties: each and every. The each property accepts and array of numbers, and will fire an event once that percentage is reached. The every property accepts an integer, and will fire every n%.

NOTE: Google Analytics has a 500 hit per-session limitation, as well as a 20 hit window that replenishes at 2 hits per second. For that reason, it is HIGHLY INADVISABLE to track every 1% of video viewed.

Google Tag Manager Configuration

Once you’ve added the script to your container (see Google Tag Manager Installation), Data Layer events will occur for all of the following:

  • Play
  • Pause
  • Watch to End

Create the following Variables:

  • Variable Name: videoUrl
    • Variable Type: Data Layer Variable
    • Data Layer Variable Name: attributes.videoUrl
    • This is the URL of the video on YouTube
  • Variable Name: videoAction
    • Variable Type: Data Layer Variable
    • Data Layer Variable Name: attributes.videoAction
    • This will be the action the user has taken, e.g. Play, Pause, or Watch to End

video-variables

Create the following Trigger:

  • Trigger Name: YouTube Video Event
    • Trigger Type: Custom Event
    • Event Name: youTubeTrack

youtube-event-trigger

Create your Google Analytics Event tag

  • Tag Type: Google Analytics
    • Choose a Tag Type: Universal Analytics (or Classic Analytics, if you are still using that)
    • Tracking ID: <Enter in your Google Analytics tracking ID>
    • Track Type: Event
    • Category: Videos
    • Action: {{videoAction}}
    • Label: {{videoUrl}}
    • Fire On: More
      • Choose from existing Triggers: YouTube Video Event

youtube-GA-Event

Getting Video Titles

Because of the deprecated YouTube API, this script no longer provides the titles of the videos. We chose to go with the most consistent method, which means that instead of the human-readable titles you would have gotten as your Event Label before, you’ll now see the URL of the video itself, e.g. https://www.youtube.com/watch?v=dQw4w9WgXcQ.

Once you have the video URL, you can use something like Excel or Google Spreadsheets to help convert those into readable titles. Another option would be to use a Google Tag Manager Lookup Table to translate the URLs into titles before sending the information to Google Analytics. We have a spreadsheet to help convert URLs to Titles, as well as blog about quickly creating lookup tables.

Coming Soon

We have added percentage completion tracking to the script, and are looking for suggestions on how we could improve the script with further functionality. Let us know on the GitHub repo or in the comments below.

Dan Wilkerson is a Software Engineer at LunaMetrics. He is passionate about web technology, measurement, and analysis. Dan is the winner of the 1999 Forge Road Elementary School Science Fair for his groundbreaking report on how magnets work. (ICP, take note.) Dan has worked at LunaMetrics in social media, as our marketing manager, and now in our analytics department.

  • Frédéric Gaye

    Hi Dan,
    Very nice solution but it seem have a “little” bug with GTM. We have a “flash” on youtube video (when page loading video disappears briefly then reappears). Except this point all is fine.
    PS : Yes, add percentage completion tracking will be a nice idea.

    • Dan Wilkerson

      Hi Frédéric,

      This is expected behavior – if your video embed doesn’t have the proper parameters (?enablejsapi=1&origin=www.hostname.com) or is an older style object, the tracking won’t work. The script detects these issues and reloads the video. If you don’t want that to happen, you can add those parameters to the src attribute of the video you’ve embedded.

      Dan

    • Dan Wilkerson

      Hey Frédéric,

      Just wanted to let you know that we’ve added percentage tracking to the script. Check it out in the repo and leave me some feedback.

      Dan

  • Katya De Palma

    HI Dan, thanks for ur guidelines. Just a info: you suppose to do it with Version 2, but I can manage the same with the version 1 of gtm?
    I mean I fixed all the event /tag /macro in V1 but doesn’t work.
    many thanks for ur help.
    k.

    • Dan Wilkerson

      Hi Katya,

      Sure can, but they’re migrating everyone to v2 on June 1st.

      Dan

  • Sarah Peduzzi

    What voodoo magic is this? Much learning. So excite.

    • Dan Wilkerson

    • Dan Wilkerson

      Aw yiss.

  • Amanda Dominy

    I don’t seem to be able to get this to work at all. I have a WordPress site, with a Bootstrap theme that already uses JQuery. I have enqueued the script lunametrics-youtube-v7.gtm.js in the header, after jquery. I’m using Universal Analytics, and I’m happy with the events you have by default, so I have not configured anything else. I’m using the standard iframe embed code (eg: ). Here is a link with an example video on our site: http://www.encounters.co.za/siren-of-faso-fani/

    I don’t know what else is going wrong?

    (PS: I added a space to the iframe code because I couldn’t figure out how to [pre] code here…

    • Dan Wilkerson

      Hi Amanda,

      The newest version removes the jQuery dependency.

      When I look at the video on the page, it’s being served via player.cxtn.net, not a standard YouTube Iframe. Are you using a plugin of some kind to deliver this video? That’s why it’s not working, as far as I can tell.

      Dan

      • Amanda Dominy

        Hi there, yes, I installed a plugin from vidanalytic.com in the mean time to track the views. I will disable it now for a couple of days – would you mind taking another look?

        • Dan Wilkerson

          Hi Amanda,

          You’ve got another file loaded in after the YouTube tracking script that is overwriting the window.onYouTubeIframeAPIReady endpoint with it’s own function. This happens before the Iframe API is loaded in and can call the LunaMetrics script, so you don’t see an error or anything it’s simply lost. If you want to have both scripts, you’ll need to add logic to them both to detect if there is already a function registered at that endpoint and to concatenate their execution, Check this file for more. http://www.encounters.co.za/wp-content/plugins/slideshow-jquery-image-gallery/js/min/all.frontend.min.js?ver=2.2.23

          Dan

          • Amanda Dominy

            Ah! Thanks so much – I’ll see if I can do without the slideshow plugin, or better yet, do it natively in Bootstrap.

          • Amanda Dominy

            Ok, I’ve removed that plugin (replacing my slideshow with a native bootstrap carousel). I can see now that the enablejsapi bit is properly added to my videos, and it’s being served from youtube, but I’m still not seeing any events triggering in my analytics account (looking at the Real Time events, last 30 min). Could it be a caching problem? Thanks so much for the help and feedback, in advance.

          • Dan Wilkerson

            Hi Amanda,

            Sorry, missed this comment. It looks like your Yoast Google Analytics plugin is renaming the default Universal Analytics function to __gaTracker. This is something I can fix in the code, but for now, you’ll just want to find and replace:

            with

            And that should fix it.

            Dan

          • Amanda Dominy

            Aha! Success! Thank you so much!!

  • Tiaan Van Zyl

    Hi Dan,

    I have a noob question – should the custom HTML tag fire on all page of the website?

    Oh yes, this is pretty cool!

    Thanks
    Tiaan

    • Dan Wilkerson

      Hey Tiaan,

      It can, but you’re adding extra code execution that you don’t really need. You might instead create a custom JS variable that checks for any YouTube videos on the page and returns ‘true’ if it sees one, then use that as a firing Trigger.

      Dan

      • Tiaan Van Zyl

        Hey Dan,

        Thanks for the feedback. I actually did a quick search within Google and found the following javascript code to detect if there is a youtube video present. I will create a trigger when this code snippet fires, then the trigger should fire on any pageview (type) of the custom html tag? –

        function () {

        for (var e = document.getElementsByTagName(‘iframe’), x = e.length; x–;)

        if (/youtube.com/embed/.test(e[x].src)) return true;

        return false;

        }

        Thanks,
        Tiaan

      • PeaceInEurope

        Hi Dan Wilkerson,

        I don’t how to create it. I went to “Variables”. Then i went to user-defined variables. Then i clicked on “New”. Then i chose the type “custom JavaScript”
        What do i type in to find any YouTube Video on my website?

        • Dan Wilkerson

          You could use Tiaan’s code from above, but if you want to a little more thorough, you could use this:

  • http://escapestudio.hr Zorin Radovancevic

    Hi Dan,

    tested the script and it works nicely – thanks!

    One question though with UA simple implementation GA debug reported ‘Unrecognized Positional Argument: false’. I have changed your js and instead of false used {nonInteraction: 1|0} and no more warnings were present.

    Kind regards,
    Zorin

    • Dan Wilkerson

      Hi Zorin,

      Good catch! Pushed a fix to the repo. Much appreciated.

      Dan

  • Lucas

    Hi Dan, great video! It was exactly what I needed to start tracking videos on the company site. I was researching on Google Tag Manager and it stated that we can also add the GA tracking code to our Tag Manager container. In this case, can I remove the older GA script?

    • Dan Wilkerson

      Hi Lucas, I’d suggest doing some additional research on migrating to GTM. It’s often not as simple as just removing the old code; we recommend running a test property in parallel with identical configuration to your on page code for awhile, then switching the UA numbers when you’re good to go.

      • Lucas

        Got it. thanks!

  • http://www.hijos-del-atomo.com/ Christian Orellana

    Thank you very much! This was easy to set up and works nicely, specially with embedded playlists. It would be great to add % completion tracking!

    • Dan Wilkerson

      Hi Christian, we just added this feature a few days ago. Take a look in the repo and send me some feedback!

      • http://www.hijos-del-atomo.com/ Christian Orellana

        Hey Dan, thanks so much for the heads-up! I just tested the new version and seems to work great. Easy to set up on Google Tag Manager, too. The only thing that I expected but did not work out of the box, was that it would also track % viewed for videos played after the first video, like in related videos. This is important to me because I like to see what *other* videos my users are watching on my page, so I can include those videos later too.

        Right now, I get % tracked for the first video. If the video ends and I click a new related video, I just get the Play and Watch to End events pushed to the DataLayer, but no % played. Is this expected?

        Thanks!

        • Dan Wilkerson

          Hi Christian,

          Good catch. I can make a fix; I’d appreciate if you could open an issue in the repo, if you’ve got a minute. I’ll post here when I get it fixed – probably in the next two weeks.

          Dan

          • http://www.hijos-del-atomo.com/ Christian Orellana

            Done! Thank you very much!

          • Dan Wilkerson

            @borghal:disqus This should be fixed with our latest version

          • http://www.hijos-del-atomo.com/ Christian Orellana

            Looks like it’s working. Thank you, @disqus_ZlOkX51Bk6:disqus!

  • Bellatrice

    Hello Dan!
    Thank you for this script
    Unfortunately I can’t use it because of following error shown in ga debugger. Can you advice me anything for getting rid of it? Many thanks of advance.

    Failed to execute ‘postMessage’ on ‘DOMWindow’:
    The target origin provided (‘http://www.youtube.com’) does not match
    the recipient window’s origin (‘https://www.youtube.com’).

    • Dan Wilkerson

      Hi Bellatrice,

      The script tries to set the origin parameter based on the hostname of the document that contains it, but only if the video already does not have an origin set. Can you share a link with me so I can take a look?

      Dan

      • Bellatrice

        We are trying to run the script in our test environment, beafore adding it to the working webpage available for external users. I would be really glad to show it, but there is no way I can:(

      • Bellatrice

        I’ve attached some screenshots, mb they and following information can help:

        1. There are no other scripts that fire Youtube API at the page

        2. Youtube iframes don’t have origin of jsapi parameter set

        3. The name of script was changed to video.js but we havent changed anything inside

        4. More information about the error from the code line

        f.J=function(a){a.id=this.m;var b=[];Ba(new Aa,a,b);a=b.join(“”);var b=this.f,c,d=Ha(this.c.src);c=d[1];var e=d[2],g=d[3],d=d[4],k=””;c&&(k+=c+”:”);g&&(k+=”//”,e&&(k+=e+”@”),k+=g,d&&(k+=”:”+d));c=k;b=0==c.indexOf(“https:”)?[c]:b.c?[c.replace(“http:”,”https:”)]:b.h?[c]:[c,c.replace(“http:”,”https:”)];for(c=0;c=a.length)throw T;if(b in a)return a[b++];b++}};return c}throw Error(“Not implemented”);}

        Thank you!

  • Alex Hadimulya

    I want to do the same tracking for youtube videos that are loaded via fancybox. For example, click on a link and the video opens up. What modifications do i need to make to take into account the delayed trigger for the fancybox?

    • Dan Wilkerson

      Hi Alex,

      You can try firing the script when the user clicks on something that opens the Fancybox.

      Dan

  • Craig Hodgkins

    I thought we had everything good but we keep getting the following error:

    Uncaught TypeError: player.getVideoUrl is not a functiononStateChangeHandler @ (index):477YT.Player.events.onStateChange @ (index):421f.P @ www-widgetapi.js:13f.A @ www-widgetapi.js:23f.R @ www-widgetapi.js:31W.l @ www-widgetapi.js:30g @ www-widgetapi.js:19

    • Dan Wilkerson

      Hi Craig,

      It’s difficult to say why you’re seeing this without a firsthand look; can you share a link I can take a look at?

      Dan

  • Kimberly

    I can’t seem to get the GTM Github link to the js script code to work, the link is: https://raw.githubusercontent.com/lunametrics/youtube-google-analytics/master/lunametrics-youtube-v7.gtm.js

    And shows “not found” when I click. Hoping to get that script so I can set up YouTube tracking on my site!

  • Neil Odiaz

    Hi, Unfortunately, I can’t get this to work. Here is my sample page: http://softdev.ninja/yt-tracking.html. Anyone can help me on this? Thanks in advance.

    • Dan Wilkerson

      Hey Neil,

      There was a two-day window where there was a bug which would stop the script from pushing to the dataLayer. We pushed a fix, so if you try the latest version you should be good:

      https://raw.githubusercontent.com/lunametrics/youtube-google-analytics/master/lunametrics-youtube.gtm.js

      Dan

      • Neil Odiaz

        Already updated the js file but still doesn’t work. I followed your steps above but no luck.

        • Dan Wilkerson

          Hi Neil,

          I took another look and it appears like that fixed it (see attached).

          Have you configured a Google Analytics Event tag in your GTM account to fire on the youTubeTrack event?

          Dan

  • Tom

    Hello Dan,

    Sorry if this is a stupid question. But where can I see all the results in Google Analytics? (how many people paused the video, etc.) I can only find the real time data. But is there a page where you can see the history of the results? Or do I have to take another step in Google Analytics?

    Thanks in advance,

    Tom

    • Dan Wilkerson

      Hi Tom,

      If you see events firing in the Real Time reports, you can view the data in the Behavior -> Events -> Top Events report. There you’ll see the Event Category ‘Video’, which you can click on to drill into more detailed data.

      Dan

  • Varis

    For some reason, functions for fetching player data didnt work, for example, player.getVideoUrl(); returned a javascript error of undefined function in Chrome. I had to replace it with “player.B.videoUrl”

    • Dan Wilkerson

      Hello Varis,

      If you fire this script twice or in conjunction with another tracking script, that issue will occur. Your current fix is brittle; ‘B’ is the annotated minified reference for an internal method in the YouTube Iframe API, and will change if they add, remove, or adjust the variables in the script before minification.

      If you do come up with a full solution, please pull it to the Repo!

      Dan

  • Abiodun

    Hello Dan,

    Great post!

    Under “Configuring Which Events Fire” Seems you missed on what Trigger the YouTube tag to fire if using GTM. See attached image.

    • Dan Wilkerson

      Hi Abiodun,

      Good idea, I’ll add a note about that. Typically you can fire it on every page, or you can add a Variable that detects if a YouTube video is present and then fires it.

      Dan

  • Marcos Alonso

    Hi Dan,

    You´ve done a really nice job here. Congrats!

    I tried to implement it on my website, but my Event Action or Label are comming as Undefined, although I configured the variables videoAction and videoUrl as shown in your post. Do you have any idea on what am i doing wrong?

    • Marcos Alonso

      After a little analysis, I found that the event “undifined” of the category “videos” where sent in some pages without any video.
      So i created another Google Analytics Tag which is configured to be fired in All Pages. But now I don´t have any event.

      The age with the video is:

      below you can find some prints n(they´re in portugueese, but i think you can understand them 😉

  • FacelessMan

    For others that are going to use this script, make sure that if you are using a URL that doesn’t read exactly “youtube.com/embed” or “youtube.com/v” that you add in the following potentialYouTubeVideoSrc.indexOf( ‘nontraditionalyoutubeurl.com’ ) > -1 || with the other two if constraints in the function checkifyoutubevideo.

    All in all a pretty sweet little plugin.

    • Dan Wilkerson

      Could you share an example of a specific domain this might apply to? I’m happy to add some logic for common non-traditional syntaxes, or a configuration option. I’m also happy to look at anything you’d like to pull in to the repo.

      Dan

      • Peter Livsey

        Hi
        I think an example of what FacelessMan is referring to is youtube-nookie.com. Our website uses this version of the URL for linking in Youtube videos so I have to modify part of the script to check for these URLs rather than youtube.com in the checkIfYouTubeVideo function.
        Peter

  • Caleb

    Do you think it would be possible to track multiple YouTube videos that exist on the same page?

    • Dan Wilkerson

      Hi Caleb,

      By default, this script will track multiple videos on the page.

      Dan

      • Caleb

        Thanks for the quick reply. I appreciate it!

  • Chris

    Hi Dan,

    Thanks for the post and very useful script. We’re trying to get it to work here: http://www.cucs.org/about-us with no success. I believe we followed your instructions to the letter. We currently have two analytics properties: one using Classic Analytics and another where we’re testing Universal Analytics using Tag Manager. That’s the one we’re trying to get to work. According to preview mode, the custom html tag fires but the event tag doesn’t. All other event tracking — downloads, external links, etc. — seems to work fine. Thoughts? Any advice will be greatly appreciated!

    • Dan Wilkerson

      Hi Chris,

      I took a peek and it’s difficult to say why that’s happening without seeing your GTM. There is a strange error showing up in console, which seems to be emanating from within the YouTube script; because it’s minified, it’s difficult for me to square exactly what is going on. Could you check that no modifications were made?

      Dan

      • Chris

        Dan,

        Thanks for taking a look. I went back and redid the custom html tag using the code exactly as I found it here: https://raw.githubusercontent.com/lunametrics/youtube-google-analytics/master/lunametrics-youtube.gtm.js. I’m not seeing the syntax error, but it’s still not working. Let me know if there’s anything else I can supply and thanks again for the help!

        • Dan Wilkerson

          YouTubes Iframe API is throwing an ‘Untrusted Origin’ warning; it looks like maybe your origin parameter on your video is not URI encoded. Could you replace origin=http://www.cucs.org with origin=http%3A%2F%2Fwww.cucs.org in your on-page html and see if that does the trick?

        • Chris

          Oops. Spoke too soon. Seems to be working now. Must have been a typo in there somehow. Thanks for checking, though.

  • Rien Moeyaert

    I have a case in which I replace a certain iframe with another iframe when clicked on a thumb-image. When this happens, and you watch the new video, this video doesn’t get tracked. Is there anyway I could for example recall the init from lunametrics code in my own javascript?

    • Dan Wilkerson

      Hi Rien,

      Just invoke window.onYouTubeIframeAPIReady and you should be all set.

      Dan

      • Rien Moeyaert

        Tried that, but didn’t work for me. So I added a window.init = init; and invoked that. I don’t know why invoking window.onYouTubeIframeAPIReady didn’t work. Because it returns a function is my guess.

        • Dan Wilkerson

          Hi Rien,

          There’s an easy fix for that; add () to the end of window.onYouTubeAPIReady and you’ll be set.

          Dan

  • http://inseo.lt/ Justinas Kundrotas

    Hi Dan,

    awesome script and totorial, I’ve tested on one of my sites and it works like a charm. But I’m having issues when trying to get it work with Youtube video tracking in Slider Revolution (WP plugin). Sample URL is https://eldesalarms.com/product/esim364/ . Is it possible to make this work with videos that play in the slider?

    Thank you for the great script and support!

    Regards,
    Justin

  • Bill Miksich

    Dan:
    The script and instructions were great. Thanks for putting this together!

  • Alexander Aagreen

    Hi, setup av everything worked very well – but one thing is still missing – how do I get the percentage event to fire?

    • Alexander Aagreen

      I cant see it in my GA-profile?

      • Dan Wilkerson

        Remove the filter Play|Pause… etc from your Trigger; that screenshot is old and should be replaced. If that doesn’t fix it, let me know.

        Dan

        • Santi Albert

          Hi Dan, nice post and guide! It worked perfectly except what Gaute and Alexander comment. That’s the percentage event issue.

          I wanted to do what you say of removing the filter “Play|Pause|Watch to End” on the “YouTube Video Event”, but if I do that, GTM doesn’t let me save the Trigger (screenshot attached) 🙁

          What should I do?

          Many many thanks!

          • http://inseo.lt/ Justinas Kundrotas

            Hello, Santi, just remove the whole condition with the “videoAction” and you should be all set with % tracking.

    • Gaute Gjerløw Remen

      It fires, but does not show up in GA..

  • Gaute Gjerløw Remen

    Hi Dan!

    I am implementing this awesome solution to a website. I have followed the instructions in detail, but the only thing that fire is the Custom HTML (The script). When I play a youtube video, no tag is fired.

    • Alexander Aagreen

      You probably only set up the tag that fires the event to GTM. After that, you need to set up the tag that sends the event data from GTM to Google Analytics – its all a bit further down in the instructions. Please let me know if you get the percentage event to work and if I could have a screenshot of how its looks in GA

      • Gaute Gjerløw Remen

        It did indeed work on any other site I was testing on. The site I was testing on was hiding the tag, so I need to rewrite some of the code to make it fit my purpose. I am not seeing the percentage either in GA, only Play and Pause…

        • Dan Wilkerson

          Gaute, Remove the filter Play|Pause… etc from your Trigger; that screenshot is old and should be replaced. If that doesn’t fix it, let me know.

          Dan

          • Gaute Gjerløw Remen

            Great, I will try that and post the result 🙂 Thanks alot!

  • Mark Pfeffer

    Hi Dan,

    Thanks for taking the time to write this out.

    I’m using the YouTube IFrame Player API to do things onPlayerStateChange, loadVideoById, etc.

    I’ve tried adding the lunametrics script last so that my code doesnt overwrite onYouTubeIframeAPIReady. Unfortunately, my YouTube events are not being detected.

    I tried manually embedding an iFrame instead of using the YouTube API, and when I do this it works perfectly. I lose all the other functionality that I need, however. Any ideas? Thanks a bunch.

    • Dan Wilkerson

      Hi Mark,

      Hm. Basically it’s conflicting with the current YouTube Player object bound to that HTML element. It’s an open issue on the repo, but I don’t know when I’ll get to it. What needs to happen is instead of trying to execute both scripts, the YouTube tracking script needs to detect if an element already has been instantiated with a Player, then extend the onEvent function, if necessary. It would also help to add detection to see if that already has been bound to.

      In the meanwhile, you’re not going to be able to use this script and your custom code without monkeying around a bit. Sorry for the issues.

      Dan

  • AJ

    Hey Dan. I have a really odd one here with this. I’ve had this working momentarily on multiple instances, but then it stops—originally when I went to publish it. We’re trying to get it going on a YouTube embed at http://www.tourismtofino.com/yourtofino/ I’ve tried a number of things written here, have purposely broken it multiple times, but still to no avail. Anything we’re somehow missing?

    Any help would be greatly appreciated.

    AJ

    • Dan Wilkerson

      Hi AJ,

      My guess is that it’s because the HTML containing the video gets reworked by your fitvids jquery plugin, which breaks the YT.Player objects association with the iframe itself. I would try deferring firing the script until after the YouTube video has been rendered on the screen; have you tried using the gtm.load event? That, or you could wrap the whole thing in a timer.

      One other item (just to make things a little smoother) – add &origin=http:%2F%2Fwww.tourismtofino.com to the iframe src attribute. This will prevent the video from being ‘refreshed’ by the script and flickering.

      Dan

      • Kim

        HI Dan,
        I am also using the fitvids jquery plugin. When I add the script to the footer file, the entire website goes to a blank white screen, although I think it may be intermittent like AJ’s. I tried adding a timeout function, but thought I should check if there is a known conflict with fitvid before going any further. Have you seen any success with the two plugins together?

  • Peter Livsey

    Hi

    Thanks for providing this solution. I’ve implemented the tracking on our website using GTMv2 and it’s working successfully where we have Youtube videos embedded directly on a website page.

    However we use an accordion feature to allow sections of the content to be expanded by users and most of our youtube videos are included in these. For some reason the youbtube videos when they are contained within an accordion don’t track any events. Running GTM in debug mode the tags just doesn’t fire on the page. An example of one of our pages with a video included like this is http://www.durham.gov.uk/article/5444/Stanley-pupils-launch-video-to-boost-youth-vote – I can’t see why the tags wouldn’t fire on this page.

    Any suggestions would be helpful.
    Peter

    • Mark Pfeffer

      Having a similar problem as you Peter. My videos pop up in a hidden modal when a button is clicked, but do not get caught by tag manager. Please let me know if you find a solution.

      Thanks,
      Mark

      • Dan Wilkerson

        Hi Mark,

        See my above comment to Peter.

        Dan

    • Dan Wilkerson

      Hi Peter,

      It’s not working because the video s are not in the DOM when it first runs (on page load).

      Add window.onYouTubeAPIReady(); to the code that loads in your YouTube videos, or immediately after it. This causes the script to check for newly added videos and bind to them.

      Dan

  • MattC

    What if we are getting a ‘Uncaught TypeError: b.getVideoUrl is not a function’

    I added the script to the head
    I added the custom html, and setup for it to be loaded on all pages
    I created both DLV’s and the Event, and the Tag
    But when i go to a page with youtube videos nothing happens.

    In testing after the page loaded we tried window.onYouTubeIframeAPIReady then window.onYouTubeIframeAPIReady()
    at 1st this failed, because http != https and just kept generating error after error infinitely, so i updated my url to https and re-ran the window.onYouTubeIframeAPIReady() and now it gives the started error up top.

    Thoughts?

    • Dan Wilkerson

      Matt, remove the script from the and you should be set. What’s happening is you’re firing the same code twice; once in GTM and once on the page. This causes the YouTube Player object to get bungled up. It’s an open issue on the repo, if you’d like to take a crack at it. For now, removing the script from the should solve your problem.

      Dan

      • MattC

        Thanks, is there a good way to exe the window.onYouTubeIframeAPIReady()?

        I’ve tried:
        window.onYouTubeIframeAPIReady();
        (function(){window.onYouTubeIframeAPIReady();})();
        $(document).ready(function(){window.onYouTubeIframeAPIReady();});
        None seem to work, the video loads and starts playing and has no tracking until I open the console and exe it myself.

        • Dan Wilkerson

          You need to invoke it after the YouTube video has loaded on the page. How you determine that will be up to you. One way I’ve seen it done is to use the onload event from the iframe and fire it then; just beware that this can cause it to fire two times, so you’ll need to add checking for that.

          Another simple way is to add a timeout that fires it after the code that loads the YouTube iframe, e.g.:

          function openYTModal(id) {

          // Code that creates the modal and inserts the video

          // After the bit that appends the video to the DOM
          setTimeout(function() {
          onYouTubeIframeAPIReady();
          }, 1000);

          }

          You’re video isn’t loaded by the browser when you fire the script, so it misses.

          Dan

  • http://www.usaforexsignal.com Penny Algarin

    fabulous post

  • Mark

    Possibly a dumb question, but I just put the hosted script in the header of my wordpress site and am using Universal Analytics. Will this give me Event Tracking for the embeds in my Analytics?

    • Dan Wilkerson

      Hi Mark,

      Yes, is should. It automatically detects if GTM, UA, or GA Classic are available, and sends the hits to the first one it matches in that order. You can override this behavior by using the forceSyntax option, as noted in the docs on GitHub.

      Dan

      • Mark

        Thanks, Dan. Where in analytics would this info be? I can’t seem to locate it. Thanks again!

        • Dan Wilkerson

          Hi Mark,

          This data will be recorded in the Behavior -> Events -> Top Events report, under the Videos Category.

          • Mark

            Thanks a lot for following up.

      • Mark

        I see it now. Thanks so much for your reply, Dan.

  • Peter Livsey

    Hi, is anyone else having problems with the tracking of videos at the moment? Our GA hasn’t tracked any video events since the weekend. Nothing has been changed on our implementation. I’ve tried running in preview mode and the youtube present variable is being set as true but playing the video doesn’t cause the event to be triggered.
    Thanks

    • Dan Wilkerson

      Hi Peter,

      This is because the YouTube iframe isn’t in the DOM when the script runs, but rather after someone clicks on the button to show the video. The tag is not impacting this; to fix this, add some code that invokes onYouTubeIframeAPIReady after a user clicks the ‘Open’ button. Be sure to only do this once, or it will get messy (a known issue we’ve got tagged in the Repo). Something like this should do it:

      Hope this helps.

      Dan

      • Peter Livsey

        Many thanks, I don’t think we’d have got this working without your help 🙂

      • Nate

        Hey there, I think I have a similar problem at my site (northernmonday.com) but no sure where the code above is supposed to live. Please advise.

  • Sam

    Thanks for this, I did find it tricky to set-up.

    I created the custom html tag containing the script from the link.

    I didn’t do the next steps as it seemed you had to provide the url of the video, since we have 30+ videos I missed the point.

    We only need to track when someone starts and watches a video to the end, can I now track this from just publishing the custom html tag?

    If so what will the event category be?

    Thanks,

    Sam

    • Sam

      Added |25%|50%|75% to the tag so can now track at what point people stop watching.

      This is so awesome!! Analytics can just be so exciting sometimes!

      • Dan Wilkerson

        Glad you like it!

        Dan

  • Amanda

    Great instructions, I was able to get this to work on my YouTube videos that are embedded with an standard iframe but I can’t get to work on the videos that are wrapped in a div container. Any thoughts on how to activate the YouTube Listener when using a div container?

    Thanks

    Amanda

    • Dan Wilkerson

      Hi Amanda,

      Can you share an example page with me so I can take a look? A tag should make no difference, but if they’re nested in an iframe tag, that would cause a problem.

      Dan

  • http://happinesshunt.co/ Ronen Teva

    Simply great.
    Thank you!

    • Dan Wilkerson

      You’re welcome!

      Dan

  • http://bigleapcreative.com/ Lisa Gerber

    Hi Dan, I scrolled through the comments and didn’t see anyone else with this issue so I must be doing something wrong – when I publish the tag, I get this error: Parse error. primary expression expected, line 361, character 2.

    Here is line 361 – 365:

    } )( document, window, {
    ‘events’: {
    ‘Play’: true,
    ‘Pause’: true,
    ‘Watch to End’: true

    Any ideas? and thank you!

    • Dan Wilkerson

      Hi Lisa,

      This is tricky to diagnose without seeing the code; can you share a page where this is running? It looks like there’s either a missing or extra curly bracket in there somewhere.

      Dan

      • http://bigleapcreative.com/ Lisa Gerber

        Dan, it’s not running on any pages because GTM won’t publish it. Will it help to show a screen grab? the issue is at line 361, character 2, according to the error message (again, thank you for you time!!) :

        • Dan Wilkerson

          Hi Lisa,

          Can you send a screenshot of the whole thing please? Is the whole script between a and tag?

          • http://bigleapcreative.com/ Lisa Gerber

            Hi – I can’t grab the screen shot of the whole thing since it requires a scrolls so I just copied and pasted the code here. I hope that works:

            // ;(function( document, window, config ) {

            ‘use strict’;

            window.onYouTubeIframeAPIReady = (function() {

            var cached = window.onYouTubeIframeAPIReady;

            return function() {

            if( cached ) {

            cached.apply(this, arguments);

            }

            // This script won’t work on IE 6 or 7, so we bail at this point if we detect that UA

            if( !navigator.userAgent.match( /MSIE [67]./gi ) ) {

            init();

            }

            };

            })();

            var _config = config || {};

            var forceSyntax = _config.forceSyntax || 0;

            var dataLayerName = _config.dataLayerName || ‘dataLayer’;

            // Default configuration for events

            var eventsFired = {

            ‘Play’ : true,

            ‘Pause’ : true,

            ‘Watch to End’: true

            };

            // Overwrites defaults with customizations, if any

            var key;

            for( key in _config.events ) {

            if( _config.events.hasOwnProperty( key ) ) {

            eventsFired[ key ] = _config.events[ key ];

            }

            }

            //*****//

            // DO NOT EDIT ANYTHING BELOW THIS LINE EXCEPT CONFIG AT THE BOTTOM

            //*****//

            // Invoked by the YouTube API when it’s ready

            function init() {

            var iframes = document.getElementsByTagName( ‘iframe’ );

            var embeds = document.getElementsByTagName( ’embed’ );

            digestPotentialVideos( iframes );

            digestPotentialVideos( embeds );

            }

            var tag = document.createElement( ‘script’ );

            tag.src = ‘//www.youtube.com/iframe_api’;

            var firstScriptTag = document.getElementsByTagName( ‘script’ )[0];

            firstScriptTag.parentNode.insertBefore( tag, firstScriptTag );

            // Take our videos and turn them into trackable videos with events

            function digestPotentialVideos( potentialVideos ) {

            var i;

            for( i = 0; i -1 ||

            potentialYouTubeVideoSrc.indexOf( ‘youtube.com/v/’ ) > -1 ) {

            return true;

            }

            return false;

            }

            // Turn embed objects into iframe objects and ensure they have the right parameters

            function normalizeYouTubeIframe( youTubeVideo ) {

            var a = document.createElement( ‘a’ );

            a.href = youTubeVideo.src;

            a.hostname = ‘www.youtube.com’;

            a.protocol = document.location.protocol;

            var tmpPathname = a.pathname.charAt( 0 ) === ‘/’ ? a.pathname : ‘/’ + a.pathname; // IE10 shim

            // For security reasons, YouTube wants an origin parameter set that matches our hostname

            var origin = window.location.protocol + ‘%2F%2F’ + window.location.hostname + ( window.location.port ? ‘:’ + window.location.port : ” );

            if( a.search.indexOf( ‘enablejsapi’ ) === -1 ) {

            a.search = ( a.search.length > 0 ? a.search + ‘&’ : ” ) + ‘enablejsapi=1’;

            }

            // Don’t set if testing locally

            if( a.search.indexOf( ‘origin’ ) === -1 && window.location.hostname.indexOf( ‘localhost’ ) === -1 ) {

            a.search = a.search + ‘&origin=’ + origin;

            }

            if( youTubeVideo.type === ‘application/x-shockwave-flash’ ) {

            var newIframe = document.createElement( ‘iframe’ );

            newIframe.height = youTubeVideo.height;

            newIframe.width = youTubeVideo.width;

            tmpPathname = tmpPathname.replace(‘/v/’, ‘/embed/’);

            youTubeVideo.parentNode.parentNode.replaceChild( newIframe, youTubeVideo.parentNode );

            youTubeVideo = newIframe;

            }

            a.pathname = tmpPathname;

            if(youTubeVideo.src !== a.href + a.hash) {

            youTubeVideo.src = a.href + a.hash;

            }

            return youTubeVideo;

            }

            // Add event handlers for events emitted by the YouTube API

            function addYouTubeEvents( youTubeIframe ) {

            youTubeIframe.pauseFlag = false;

            new YT.Player( youTubeIframe, {

            events: {

            onStateChange: function( evt ) {

            onStateChangeHandler( evt, youTubeIframe );

            }

            }

            } );

            }

            // Returns key/value pairs of percentages: number of seconds to achieve

            function getMarks(duration) {

            var marks = {};

            // For full support, we’re handling Watch to End with percentage viewed

            if (_config.events[ ‘Watch to End’ ] ) {

            marks[ ‘Watch to End’ ] = duration * 99 / 100;

            }

            if( _config.percentageTracking ) {

            var points = [];

            var i;

            if( _config.percentageTracking.each ) {

            points = points.concat( _config.percentageTracking.each );

            }

            if( _config.percentageTracking.every ) {

            var every = parseInt( _config.percentageTracking.every, 10 );

            var num = 100 / every;

            for( i = 1; i < num; i++ ) {

            points.push(i * every);

            }

            }

            for(i = 0; i < points.length; i++) {

            var _point = points[i];

            var _mark = _point + '%';

            var _time = duration * _point / 100;

            marks[_mark] = Math.floor( _time );

            }

            }

            return marks;

            }

            function checkCompletion(player, marks, videoId) {

            var duration = player.getDuration();

            var currentTime = player.getCurrentTime();

            var playbackRate = player.getPlaybackRate();

            player[videoId] = player[videoId] || {};

            var key;

            for( key in marks ) {

            if( marks[key] <= currentTime && !player[videoId][key] ) {

            player[videoId][key] = true;

            fireAnalyticsEvent( videoId, key );

            }

            }

            }

            // Event handler for events emitted from the YouTube API

            function onStateChangeHandler( evt, youTubeIframe ) {

            var stateIndex = evt.data;

            var player = evt.target;

            var targetVideoUrl = player.getVideoUrl();

            var targetVideoId = targetVideoUrl.match( /[?&]v=([^&#]*)/ )[ 1 ]; // Extract the ID

            var playerState = player.getPlayerState();

            var duration = player.getDuration();

            var marks = getMarks(duration);

            var playerStatesIndex = {

            '1' : 'Play',

            '2' : 'Pause'

            };

            var state = playerStatesIndex[ stateIndex ];

            youTubeIframe.playTracker = youTubeIframe.playTracker || {};

            if( playerState === 1 && !youTubeIframe.timer ) {

            clearInterval(youTubeIframe.timer);

            youTubeIframe.timer = setInterval(function() {

            // Check every second to see if we've hit any of our percentage viewed marks

            checkCompletion(player, marks, youTubeIframe.videoId);

            }, 1000);

            } else {

            clearInterval(youTubeIframe.timer);

            youTubeIframe.timer = false;

            }

            // Playlist edge-case handler

            if( stateIndex === 1 ) {

            youTubeIframe.playTracker[ targetVideoId ] = true;

            youTubeIframe.videoId = targetVideoId;

            youTubeIframe.pauseFlag = false;

            }

            if( !youTubeIframe.playTracker[ youTubeIframe.videoId ] ) {

            // This video hasn't started yet, so this is spam

            return false;

            }

            if( stateIndex === 2 ) {

            if( !youTubeIframe.pauseFlag ) {

            youTubeIframe.pauseFlag = true;

            } else {

            // We don't want to fire consecutive pause events

            return false;

            }

            }

            // If we're meant to track this event, fire it

            if( eventsFired[ state ] ) {

            fireAnalyticsEvent( youTubeIframe.videoId, state );

            }

            }

            // Fire an event to Google Analytics or Google Tag Manager

            function fireAnalyticsEvent( videoId, state ) {

            var videoUrl = 'https://www.youtube.com/watch?v=&#039; + videoId;

            var _ga = window.GoogleAnalyticsObject;

            if( typeof window[ dataLayerName ] !== 'undefined' && !_config.forceSyntax ) {

            window[ dataLayerName ].push( {

            'event' : 'youTubeTrack',

            'attributes': {

            'videoUrl': videoUrl,

            'videoAction': state

            }

            } );

            } else if( typeof window[ _ga ] === 'function' &&

            typeof window[ _ga ].getAll === 'function' &&

            _config.forceSyntax !== 2 )

            {

            window[ _ga ]( 'send', 'event', 'Videos', state, videoUrl );

            } else if( typeof window._gaq !== 'undefined' && forceSyntax !== 1 ) {

            window._gaq.push( [ '_trackEvent', 'Videos', state, videoUrl ] );

            }

            }

            } )( document, window, {

            'events': {

            'Play': true,

            'Pause': true,

            'Watch to End': true

            },

            'percentageTracking': {

            'every': 25,

            'each': [ 10, 90 ]

            }

            } );

            /*

            * Configuration Details

            *

            * @property events object

            * Defines which events emitted by YouTube API

            * will be turned into Google Analytics or GTM events

            *

            * @property percentageTracking object

            * Object with configurations for percentage viewed events

            *

            * @property each array

            * Fires an event once each percentage ahs been reached

            *

            * @property every number

            * Fires an event for every n% viewed

            *

            * @property forceSyntax int 0, 1, or 2

            * Forces script to use Classic (2) or Universal(1)

            *

            * @property dataLayerName string

            * Tells script to use custom dataLayer name instead of default

            */

            /*

            * v8.0.3

            * Created by the honest folks at @LunaMetrics, written by @SayfSharif and @notdanwilkerson

            * Documentation: https://github.com/lunametrics/youtube-google-analytics/

            * Licensed under the Creative Commons 4.0 Attribution Public License

            */

          • Nicola

            Hi, I’m having the same issue with the same error. Did you find out the solution? Thanks

          • http://bigleapcreative.com/ Lisa Gerber

            I didn’t find a solution, Nicola.

          • Dan Wilkerson

            Hi Lisa,

            Sorry we disconnected on this. If you’re still interested in using the tool, try using the new container file for import, available in the repo w/ documentation on how to use here:

            https://github.com/lunametrics/youtube-google-analytics#google-tag-manager-installation

            Your error looks like a copying error somewhere along the way, which is tricky to debug once-removed. The import should eliminate that problem entirely. Jim has a good post on how to import containers, if the docs aren’t clear enough:

            http://www.lunametrics.com/blog/2015/08/26/import-container-google-tag-manager/

            Dan

          • Nicola

            Hi Dan,
            I’m having the same problem as Lisa, I copied and pasted the code from here as suggested: https://raw.githubusercontent.com/lunametrics/youtube-google-analytics/master/lunametrics-youtube.gtm.js
            Any ideas?
            thanks

          • Dan Wilkerson

            Sorry Nicola, it’s really hard to debug these things once-removed. I’d suggest trying the Container Import outlined in the docs – that will set up the tags for you. The reason you’re seeing this is a copying error.

  • Melanie

    Hi Dan!

    Thank you for the plugin! It’s working beautifully when I test it locally but when I deploy it the events aren’t being tracked, or fired. I’m using youtube embeds in an angular app. I’ve loaded the cdn at the bottom of my index file along with a window.onYouTubeIframeAPIReady();. Any suggestions on why this would be different between environments would be helpful.

    Thanks again for creating and sharing this!

    • Dan Wilkerson

      Hi Melanie,

      I took a peek at your site – it looks like it’s because the script is being invoked before any video iframes are in the DOM. I tried playing a video and then calling onYouTubeIframeAPIReady in the console and it worked. Try adding a call to onYouTubeIframeAPIReady after a user opens one of the videos on your site.

      Also, I couldn’t help but notice all the pages on your site are 302’ing to your Angular app; that’s going to cause some bad stuff to happen to your organic traffic. You might want to support hash-free routing to those Angular pages, although I think Google has made some progress in properly indexing those pages since I last checked… Also, you’ll want to switch to a 301 redirection! Otherwise, you’ll lose the SEO value of any links pointing to your site. Sorry, I know you didn’t come here for SEO advice, but I can’t resist.

      Dan

  • Jossbox

    Hi Dan,

    i’m a bit of a Google Tag Manager novice. I’ve followed all the instructions but the tags do not seem to be firing.

    The custom HTML youtube listener tag is firing but the videoAction and VideoUrl variables are undefined.

    Any help would be much appreciated

    • Dan Wilkerson

      Hi Joss,

      A user needs to interact with the video in order to generate a dataLayer event, and therefore set those values. Try clicking the play button; you should see youTubeTrack appear under the Summary header, and then those values should be set. If this doesn’t occur, you’re video isn’t on the page when the script loads; try setting it to fire when a user clicks on whatever opens the video, as detailed in some of the other comments above.

      Dan

  • michael

    This is great! Thanks so much!

  • Gary O’Connor

    Hi Dan

    Not having any luck getting the GA-Event – YouTube Tracking to fire. Here are my current settings:

    GA – Event – YouTube Tracking

    • Dan Wilkerson

      Hi Gary,

      Your videos aren’t in the DOM when the script runs, so it can’t bind to them. This is a known issue, unfortunately. Change your firing trigger to the click that opens your video modal window, and that might fix it.

      Dan

  • Nate

    Hi there,

    Thanks so much for this. I am using video embedded using Squarespace, and I can’t easily access the code except for the header & footer (site is http://www.northernmonday.com). When I embed the video directly onto a page, the script works well, but if I embed it into what Squarespace calls a “gallery,” the script doesn’t work. I am wondering if you could check it out quickly and see if there’s a way for me to add some code somewhere to get it to recognize these videos? I would really appreciate it!

    Nate

    • Dan Wilkerson

      Hi Nate,

      This is a known issue; the script can only bind to videos that it sees in the DOM, and since your videos don’t appear until the gallery is opened, it can’t bind to them when it executes. If you’re using GTM, try changing your firing trigger to the click that opens your gallery.

      Dan

  • Zerogravità SNC

    Hi Dan,

    I try to set-up a youtube event

    but even if in the tag manager preview mode I can see the tags working, when I publish the container I can’t see the event tracking in our Google analytics account.

    The click event doesn’t work, neither the youtube event …

    You can see the preview here: https://www.googletagmanager.com/set_cookie?uiv2&id=GTM-5NXXZT&gtm_auth=03mh9JxmQyn9F4hPHFF91g&gtm_preview=QUICK_PREVIEW&gtm_debug=x&url=http://www.zerogravita.com/

    Any ideas?

    • Dan Wilkerson

      Did you configure a Google Analytics Event to fire when the youTubeTrack event is pushed to the dataLayer?

      Dan

      • Zerogravità SNC

        Yes I do…
        But nothing happends.

        • Dan Wilkerson

          Just to confirm this, please paste this in console and check if the Event shows up in the Realtime Reports:

          dataLayer.push({
          ‘event’: ‘youTubeTrack’,
          ‘attributes’: {
          ‘videoUrl’: ‘Testing’,
          ‘videoAction’: ‘Test’
          }
          });

          Thanks!

          Dan

          • Zerogravità SNC

            No.. I can’t see it.

            In GTM preview I see it:
            “Message pushed to Data Layer:
            {event: ‘youTubeTrack’, attributes: {videoUrl: ‘Testing’, videoAction: ‘Test’}}” but nothing in GA.

            My goal settings in GA admin console are:

            Category: youtube

            Action: play

            Label: Riproduzione video

            But I’ve never seen a real time event in my report. Nor in the event report….

            🙁

  • Maria

    Hi, I got this error message : “Uncaught TypeError: b.getVideoUrl is not a function” when the video state changes. I added the code in the GTM with firing rule “All Pages” and didn’t make any changes. So what could cause this error? Thanks in advance!

    • Dan Wilkerson

      Hi Maria,

      Some other script is creating a tracking object associated with the video. Unfortunately, you can’t run both at this time.

      Dan

  • Carlos

    Dan,

    We are working on a single page site (paralax scroll) and we have added four YouTube story videos to the page. I want to be able to track the number of visitors that watch all four videos. I was trying to set up a Goal for this but cannot think of how to accomplish this. Even if we can track “plays” for all 4 that would work, even if they did not get to 100% on all four.

    • Dan Wilkerson

      Hi Carlos,

      This sounds like a job for Segments! Create a goal for each video, then create a segment that just shows users who have completed each goal at least once. The alternative is to add additional code on your own that watches for these interactions and triggers and event to GA.

      Dan

  • Janet

    Hi Dan,
    I was successfully able to get my YouTube tag to fire on my video, which pops up in a modal after clicking a ‘watch video’ button, and then autoplays – per your explanations to others who’ve commented about issues with tagging videos in modals, I simply changed the trigger from gtm.dom to the click of the ‘watch video button.’

    However, I’ve noticed that the tag does not fire if I play the video again (with the modal still open), or if i close the modal and click the ‘watch video’ button again. Do you have any idea how to fix this?

    Thanks!

    • Dan Wilkerson

      Hi Janet,

      The script doesn’t officially support modal’d-in videos. This a known issue, but you’re going to need to engineer your own fix. The problem is the script only binds to videos in the DOM when it fires, and it can’t watch for new videos to appear in the DOM in any efficient manner.

      Dan

  • Adam Thorngren

    Hi Dan,

    Did you know that you can get the video title from the evt.target?

    // the beginning of my onStateChangeHandler( evt, youTubeIframe )
    function onStateChangeHandler( evt, youTubeIframe ) {

    var stateIndex = evt.data;
    var player = evt.target;
    var title = player.getVideoData()[‘title’];

    • Dan Wilkerson

      Hi Adam,

      Yes, I’m aware of that method, but it’s not officially supported and can/will fail. In my tests, it failed often enough to warrant just using the URL instead; our concern was about making this as reliable and drag-and-drop as possible, so the occasional undefined value for a title was enough concern for us to drop it. Feel free to modify your implementation accordingly, but YMMV.

      Thanks for sharing!

      Dan

      • Stephen M. Harris

        We use the getVideoData() method to get video titles, and looking at 6 months of data from multiple websites, I don’t see any as undefined. It’s perfectly valid (and probably wise) not to leverage getVideoData() simply because it’s not documented and thus subject to break without notice. But I haven’t noticed a single missing title, and I’m wondering if you noticed particular circumstances that caused it to fail? Perhaps a particular embed URL parameter?

        Fyi, our convention is to include both the video URL and the title in the event label, so even if the title is missing, the data can be easily retrieved/aggregated. But split data is still can mislead and that possibility is why I’m concerned here.

        • Dan Wilkerson

          Hi Stephen,

          I don’t have any hard data to share with you from testing, but it seemed arbitrary whether the method would or would not be available – I was testing using the same embedded video or playlist over and over, and I could get either version. It was probably unavailable 20% of the time? TBH, even if it were unavailable only 1% of the time, I’d still not use it, just because we want this to be as fool-proof as possible.

          Does your code guard against a thrown exception from the method not being available? If the getVideoData method is undefined, invoking it would throw an error. If that error was uncaught, it could crash the script and prevent the hit from ever being fired, meaning you’d never see it in GA. if you’re tracking JS errors, you might find it in there.

          Dan

          • Stephen M. Harris

            Hey Dan,
            Good point re uncaught errors causing the event not be tracked at all. I added a try/catch clause and and had label default to “(error getting title)” if an error was thrown. With about 188 unique video plays so far, I have not seen an error or blank title.

          • Dan Wilkerson

            Hm, interesting; please keep me updated. I remember getting errors all the time when I was testing it, so I’m hesitant to commit to it. I’m also relying on this (admittedly old) comment from a Googler working on the project:

            https://groups.google.com/forum/m/#!topic/youtube-api-gdata/D0w8wA0UV7A

            Make sure you expand both comments; specifically, he mentions:

            | player.getVideoData() has never been a documented or supported API method. Relying on undocumented/unsupported methods can lead to breakage, as you’ve discovered.

    • http://about.me/hans2103 hans2103

      Hi Adam and Dan,

      Thank you both for your work.
      I’m using the Lunametrics script (https://github.com/lunametrics/youtube-google-analytics) for a while now and it is working like a charm.
      A new client requests to see the video title as “event label” too.
      So I will try to implement the suggestion from Adam.

      combining “video title’ and ‘video url’ like Stephen suggests seems fine to me.

  • Richard Antille

    Hello Dan, great read and information. I implemented every elements as directed via GTM. When setting up goals in analytics, I am unsure as to what is the best approach. I set my goal as event with the following fields: Action – regular expression – {{videoAction}}. Same format for the label. Unfortunately, although the tags are firing, no goal is being hit in analytics. Please let me know if I am doing something wrong. Thank you

    • Dan Wilkerson

      Hi Richard,

      Those values ({{videoAction}}) are placeholders for text that gets substituted in dynamically whenever an Event is fired to Google Analytics. If you want to set a goal based on those Events, you want to configure the goal to look for the substituted value, e.g. Play, not the {{}} values.

      If you want to fire a goal whenever someone plays a video, you’d do this:

      Event Category equals Videos
      Event Action equals Play

      Dan

      • Richard Antille

        thanks Dan. Have a great weekend!

  • Charles Bernard

    Hey Dan,

    I’m also facing a flickering video. It seems to happen right when the tag fires (I’ve confirmed by changing the trigger for a gtm.click event).

    The iframe src uses origin=http:%2F%2Fwww.mydomain.ca, like you suggested. You could find an example at http://www.lebernard.ca/chiens/dossiers-speciaux/canicross/.

    Do you know how I could fix this? Thank you so much,

    • Dan Wilkerson

      Hi Charles,

      I looked at your source code and it doesn’t appear that the origin parameter is set on the video. The reason you may be seeing it is if you’re inspecting the video in the HTML after the script fires, the script dynamically reloads the video with that parameter added. Could you double-check that the origin parameter has been added to that videos src attribute?

      Dan

  • Omer

    HI Dan
    I am already using this and it is great.

    I thought of a nice hack and wondered if it is possible.

    I want to use youtube api output (such as played, 25%,50% etc.) as a trigger in tag manager and then use it for different platform as a retargeting or conversion pixel.

    Do u think it is possible?

    Best
    Omer

    • Dan Wilkerson

      Hi Omer,

      That would work just fine. You could also create a Segment in Google Analytics and remarket to those users that way, if you’ve got the Remarketing feature enabled!

      Dan

      • Omer

        Thanks for replaying.

        I didn’t mean creating list in Google Analytics but create a trigger in the Tag Manager to do remarketing with other platform. Analyitcs is easy 🙂

        Hope it is more clear now.
        Best
        Omer

        • Dan Wilkerson

          Ah, gotcha 🙂 Yes, this will work just fine!

          Dan

        • Julianopx

          Hello Omer. How can I do that? For example with facebook pixel? Thanks!

          • Dan Wilkerson

            Hi Julian,

            I’ll jump in here – create a Trigger that fires on the Custom Event youTubeTrack, with the filter videoAction equals 25%.

            Dan

          • Julianopx

            Thank you Dan. This is huge. Great work.

  • Mike Pellas

    Hi Dan,

    I’m relatively new to this and have a question.

    How well does the script work with WordPress? To the best of my understanding, I have everything loaded correctly but the triggers for play and pause fire at the same time. Can you offer any adivce?

    I’ve experimented with plugins to find one that works with a traditional iframe (or as close to it as possible) and that didn’t seem to work.

    Also, I’m not using a plugin to run GA or GTM. I entered the codes myself. I can get other tags to fire properly.

    Any help you can provide would be greatly appreciated.

    -Michael

    • Dan Wilkerson

      Hi Mike!

      The script operates on the HTML that is sent to the end-user, so you can think of it as independent from WordPress. If you’ve got everything loaded in, I would do a test run and then check the Events report in the Real-Time Analytics report in Google Analytics. If you’re still seeing both Play and Pause fire at the same time, you might have something more nuanced going on.

      In terms of plugins, in general I’ve found this script doesn’t work great with anything other than simply pasting in the YouTube iframe embed code generated on the video itself. This is because plugins tend to wrap the YouTube iframe in yet another iframe, which results in the script being unable to hook into the events emitted by the YouTube iframe itself.

      Dan

      • Mike Pellas

        Dan,

        Thanks for the quick reply!

        I think my next attempt to figure this out will be to plugin the iframe code directly and see if the script works correctly for me then.

        I’ve been checking everything in GTM preview and watching real time in GA. I believe I have GA configured properly as I’m seeing seeing the activity…but still seeing play and pause being recorded at the same time.

        • Dan Wilkerson

          Got a link you can share? I can take a quick look.

          • Mike Pellas

            Thank you so much!

            http://michaelpellas.com/what-ive-learned-to-program/

            It’s a small site that I’m using solely to practice things like this…

            I just added the regular youtube iframe code and verified it. I’m still seeing play and pause firing at the same time.

            Any help you can provide would be greatly appreciated!

          • Dan Wilkerson

            Hi Mike,

            The version you’ve got in GTM is working fine; I know this because I played the video, then typed in ‘dataLayer’ in the developers console (F12 or CMD+SHIFT+J), and inspected the last item that was pushed in there – it was just the Play event (picture attached). I checked the network requests, and the Play event is the only event being sent to Google Analytics. What browser are you using?

            It looks like you’ve also included an older version outside of GTM, which is returning a 404 at the moment.

            Dan

          • Mike Pellas

            Hi Dan,

            I’ve cleared the 404 (it seems it was a WordPress plugin conflict) but I’m still showing play and pause firing at the same time.

            I’ve tried IE, Firefox and Chrome and still get the same results.

            I’m sure it’s something small I’m missing.

            Do you have any additional advice? Thank you for your help so far!

          • Dan Wilkerson

            Hi Mike,

            I looked in your container code, and it looks like you may have two Event Tags – one for Play, and one for Pause, and both are firing on the same Trigger, which looks to be firing on either Play or Pause. Is that correct?

            Dan

          • Mike Pellas

            Hi Dan,

            That’s correct. I think i just got it working thanks to that response and what you asked me. Like I said…I thought it was something small i was missing.

            Thank you so much for your help!

  • http://abacusanalytics.agency/ Adam Powell

    When you when set up your trigger to fire on videoAction matches RegEx Play|Pause|Watch To End, why didn’t you escape the spaces like Play|Pause|Watch To End? For that matter, I’ve been a bit confused by whether or not grouping brackets ( ) is needed, I’m accustomed to seeing RegEx more like (Play|Pause|Watch To End) … Looking over the MDN documentation on JS and RegEx it looks like grouping is only needed if I need to “remember” the match, like for a back-reference and it doesn’t say anything about needing to escape literal spaces so maybe it’s just not needed. I’ve never really been sure but I’ve mostly dealt with RegEx while configuring Apache RewriteRules.

    • Dan Wilkerson

      Hi Adam,

      Yeah, you’re on the right track. I don’t escape spaces in my GTM RegExps (or most anywhere else, for that matter), but there’s probably very good reasons to do so in some conditions. Brackets would be necessary if I were trying to pair those with something else, e.g. “Video Action – Play” would require Video Action – (Play|Pause|Watch to End).

      Dan

  • http://www.wdwvirtualvisit.com WDWVV

    Hi Dan,

    I’m having trouble getting the events to push through to GA. I’ve downloaded and imported the container and triple checked my settings. The Custom HTML loads correctly to the pages through a DOM Ready presence trigger. So it’s recognizing the pages with youtube videos and those without. But as I hit play, it won’t push the events to GA.

    Thanks for any help in advance.

    • Dan Wilkerson

      Hi there,

      Any errors in the console?

      Dan

      • http://www.wdwvirtualvisit.com WDWVV

        Yes actually, it says “Uncaught TypeError: b.getVideoUrl is not a function”, which I read in another comment that suggests another script is conflicting, but as I inspect the site through the console I cannot find any location where another tracking object is being associated with the video.

  • Melanie Bowles

    Hi Dan,

    First of all thank you for the generous tutorial. I am having some trouble getting this to work on a site (http://bit.ly/1P925D4) that uses a video coverflow. I added the “YouTube Video Present” trigger but GTM is not recognizing the videos. Do you have any advice on how I might be able to get this to work? I would greatly appreciate any feedback you can offer.

    Thanks!

    • Dan Wilkerson

      Hi Melanie,

      Your plugin won’t work with ours out of the box, unfortunately. If you’re comfortable editing your code, you can try and add a dataLayer push to when your videos resolve in the DOM, and then re-invoke window.onYouTubeIframeAPIReady() w/ a Custom HTML tag on that event.

      Dan

  • Confused Forever

    I installed everything step by step on http://www.u-pol.co.uk/product-cat/83/raptor%E2%84%A2-bed-liner.htm but the code doesnt work and no events are tracked. Am I missing some steps? I even tried to delete everything and simply import the container.

    • Dan Wilkerson

      Hi there,

      Typically this means you’re either using a plugin to manage your YouTube videos which nests them within another iframe or you’re loading your videos into the DOM after the page load (e.g. I click a button which creates a modal window that shows the video). To fix this, you can try to add a Trigger that fires when the action that leads to the video appearing occurs that fires a Custom HTML tag that re-bootstraps the script:

      Try adjusting the timeout upwards if it doesn’t work when set to 0. This is a very technical problem, though, and site-specific, so I won’t be able to provide help beyond that.

      Dan

      • Confused Forever

        Hi, thanks for the tip, where should I add this timeout code? A new trigger or the custom HTML youtube tracking one only?

      • Darren Carter

        Great stuff, Dan!

        I am trying to do video tracking on a site that uses a modal video deployment, genuinerealpeople.com, but I’m struggling trying to parse your sentence about the potential fix:

        Add a trigger… – Do you mean a GTM trigger?

        …that fires when the action that leads to the video appearing occurs… – So for example, if a click on a specific div id or class is the action that triggers the modal, could I use that click as the firing rule?

        …that fires a Custom HTML tag that re-bootstraps the script – is the Custom HTML tag that you are referring to the setTimeout script example you provided?

        Here’s a shared preview of what I’ve done:
        http://nsem.us/1qEo2BW

        Thanks!

  • Ron Wertz

    Hey there, I love the script and it seems to be firing for our site myronmixonsmokers.com. My GA is returning undefined for the Event Action and (not set) for the Event Label. Not sure what I’m missing on this. I don’t see any errors in the console when I run this.

    Any help is greatly appreciate… thanks!
    Ron

    • Dan Wilkerson

      Hi Ron,

      You’re not using a standard YouTube iframe, but an HTML5 video element instead, which we don’t currently support.

      Dan

      • Ron Wertz

        Hi dan, I’m not sure I fully understand. I mean I do, but I don’t because the videos are wrapped in iframe tags. I guess that’s my confusion. Here is the code:

      • Ron Wertz

        Hi dan, I’m not sure I fully understand. I mean I do, but I don’t because the videos are wrapped in iframe tags. I guess that’s my confusion. Here is the code:

        • Dan Wilkerson

          Hi Ron,

          You’re correct, my apologies; I was a little fast on my once-over. When I checked in console, onYouTubeIframeAPIReady was undefined, which our script sets; it looks like the script isn’t firing in production. I manually inserted it through the console and played your video, and it worked (although it does reload the video to append the missing origin parameter). I’m guessing you don’t have it published live in production.

          Check that your Variables are correctly configured and they are inserted in your Event tag. If you’re unsure, remove the script and Event tag from your container, then import the container in the Repo and try that.

          These kinds of things can be really tricky to debug by proxy, so this is the best support I can give you for now.

          Dan

      • Ron Wertz

        Hey Dan, thanks for the assistance. I ended up implementing a different version that seems to be working.

        Thanks again

  • Kym Ellis

    Hi Dan,

    This is great, managed to get this working just fine. Having a bit of struggle with translating the URLs into titles. I have managed to use the spreadsheet and create a lookup table with the input variable as {{videoUrl}} with all input/output URLs and titles listed.

    Feel like I am missing something simple here?

    Many thanks
    Kym

    • Dan Wilkerson

      Hi Kym,

      Did you change the Event Label to your newly created Lookup Table? Do you see the Title displaying when you debug and select the Variables tab?

      Dan

      • Kym Ellis

        Hi Dan,

        Thanks for getting back to me!

        I solved it!! Realised I was using the short youtu.be URLs in my Lookup Table, needed to use the full URL for each video.

        Awesome, thanks again for taking the time to post this article.

        Kym

        • Dan Wilkerson

          Awesome!

  • Hector

    I am having a bit of trouble understanding, I am somewhat new to this. But I am trying to figure out a way to track if someone made a purchase on my site after watching the video. Does this help? From what I understand this is just to track interaction with the video itself, unless I missed it somewhere. Please help. I will forward this to my programmers I am working with since they understand it better, but I just want to know if what I need is possible.

    • Dan Wilkerson

      Hi Hector,

      Once this tracking is in place, you can visit the Behavior -> Events -> Top Events report and select ‘Ecommerce’ from the metric groups to see the value of orders for sessions with Video events.

      Dan

      • Hector

        Awesome that’s what I needed to know. Will definitely give this a try!

  • E Chandler

    I am a business owner and know nothing about the tech world, and have a situation. An ex associate has posted a negative youtube video that is not related to my company and it pops up when someone Google my company. How do I get that removed?

  • Jeff Schroeffel

    Dan,

    Great job. Had this setup and running in less than 30 minutes. Thanks for the tool.

    P.S. Tell Mike B I said “hi”

    -Jeff

    • Dan Wilkerson

      Will do!

      Dan

  • Alice Palazzolo

    Hey Dan,
    I tried implementing this on my site with the jsdelivr link that you posted above and I keep getting this error: “Executing Google Analytics commands.

    analytics_debug.js:9 Running command: ga(“send”, “event”, “Videos”, “Play”, “https://www.youtube.com/watch?v=lj3iNxZ8Dww”)

    analytics_debug.js:9 Command ignored. Unknown target: undefined”

    We aren’t running GTM at the moment just UA. Do you have any idea why this would be happening?

    • Dan Wilkerson

      Hi Alice,

      That sounds like an on-page code issue – you’re probably using a named tracker. If this is the case, you should see another command above the YouTube command with something like ‘create’, ‘UA-XXXXXX-YY’, {‘name’: ‘rollup’} and then Running command: ga(“rollup.send”, … ). The plugin doesn’t currently support named trackers, but you should be able to fix this by modifying the ga(“send” … ) command in the script to use your named tracker, e.g. ga(“rollup.send”, “event”, “Videos” …);

      Hope this helps!

      Dan

      • Alice Palazzolo

        Hey Dan,
        Thanks for the quick response. It looks like we are using this:

        ga(‘create’, ‘UA-37725717-2’, ‘auto’);

        ga(‘send’, ‘pageview’);

        So im not 100% sure if that is actually named or not ( sorry just took this project over recently). So i am not sure how i could handle this it wouldn’t be auto.send

        Alice

        • Dan Wilkerson

          I found the page in question – some other tracking code is overwriting the default GoogleAnalyticsObject name with __shrtracker, which is what is borking things (and may cause other issues in the future). In your case, the fix will be to change line 329 in the script from var _ga = window.GoogleAnalyticsObject to var _ga = ‘ga’; which will force usage of the default function name.

          Dan

          • Alice Palazzolo

            Thanks! That seems to have resolved the issue! I will look into the __shrtracker I think that has to do with the shareaholic wordpress plugin

  • vdar

    Having troubles to make it work. Using Iframe code for YouTube, but YouTube auto detects whether html5 is supported or not and renders it’s player accordingly. Also loading our videos into the DOM as soon as it is ready and not after load.
    My site is here http://goo.gl/lHlgRL

    • Dan Wilkerson

      Hi vdar,

      It works fine when I extract the YouTube iframe and run the script; it appears you might have other code that is superseding or conflicting with our tracking (screenshot attached). You’ll have to figure out a way to make those work.

      Dan

  • BrianPotterVideo

    Hi Dan,

    First of all, thank you for this excellent guide and the response to technical support questions.

    In my console I’m seeing this error when I play the video:

    TypeError: t.getVideoUrl is not a function

    I can’t determine where the conflict is. This is my page: http://amsunsolar.com/something-more-to-love-about-your-home/

    Would you mind taking a look please?

    • Dan Wilkerson

      Hi Brian,

      It looks like you’ve got the script on the page twice; once in the index HTML, and then again as an include from a CDN (screenshot attached). Remove one of those and it should get itself together.

      Dan

      • BrianPotterVideo

        That did it!! Thanks so much, Dan!

  • Meira Puterman

    Hi Dan

    Thanks so much for the script and step-by-step instructions. Everything worked super… except for the Percentage Played events. I can’t find them. All I can see are the Play, Pause and Watch to End events. I’m using the latest code you referenced (v8.0.4).

    What am I doing wrong?

    Thanks!

    • Dan Wilkerson

      Hi Meira,

      Try removing the videoAction condition on your Trigger. Let me know if that works!

      Dan

  • Andrea Lyn Van

    Thanks for sharing this! We are experiencing one issue with it, however. The event label is appearing as “(not set)” in GA. I didn’t really change anything (other than our GA code as per the directions). If you have any suggestions where to look I would really appreciate it. Thanks! Andrea

    • Dan Wilkerson

      Hi Andrea,

      Open Debug mode in GTM, open the page with the video, play the video, and then click the Data Layer tab in the GTM debug panel.

      Do you see the videoUrl in the data included there?

      Dan

  • teju

    i am having different user watching a video and having a play and pause button my question is how to find which user id is clicking play pause button and how much time using google
    analytics

    • Dan Wilkerson

      Hi Teju,

      This question is a little broad; it sounds like you might benefit from doing an Analytics Academy course to introduce you to some of the basics of using the Google Analytics interface:

      https://analyticsacademy.withgoogle.com/

      Dan

  • teju

    reply me as fast as possible plzzzz

  • Andrea Lyn Van

    Thanks for the script! Unfortunately, I am having a little trouble. While it works properly in my preview mode, after I push it live, it doesn’t fire/collect any data in GA. Any suggestions? Thanks!

    • Dan Wilkerson

      Hi Andrea,

      Did you set up the Google Analytics Event Tag? Can you confirm that there are hits showing up in Google Analytics when previewing it?

      Dan

      • Andrea Lyn Van

        Hi Dan, Yup. I’m gather data on pretty much every other tag in place. Only tag video tag doesn’t seem to be working. Thanks for the help!

        • Andrea Lyn Van

          Here are some screen grabs. Nothing shows up in GA at all under Events. However, I do see I the page I am on when I am in Real-Time. Thanks for your help!

          • Dan Wilkerson

            Hi Andrea,

            A colleague reached out with some suggestions; from what you’re saying, it sounds like you’re not seeing any event data in Google Analytics at all, for any events (even events that are not the YouTube tracking events). I would add the following advice:

            – Verify that you’ve got the correct value plugged in for {{GA Account ID}} (from your Google Analytics -> Property Settings -> Tracking Code menu)
            – Verify the hit is sending in the console (F12 on windows, CMD+OPT+J on Mac – you’ll see a readout from the actual hit)
            – Verify there are no filters on the view you are using that are excluding data

            Dan

  • ARUN AK

    Hi Dan,

    I would like to create a drupal module for this plugin and like contribute it in to drupal community with free of cost. Is there any licences issue to do that?

    Thanks,
    ARUN AK

    • Dan Wilkerson

      Hi Arun,

      You’ll just have to maintain the copyright info in the LICENSE file in the repository!

      Dan

  • ARUN AK

    Hi Dan,

    How can I alter the configuration values dynamically without editing the js file?

    ( document, window, {
    ‘events’: {
    ‘Play’: true,
    ‘Pause’: true,
    ‘Watch to End’: true
    },
    ‘percentageTracking’: {
    ‘every’: 25,
    ‘each’: [ 10, 90 ]
    }
    }

    So that I can create a configuration page for alter the settings.

    I tried with window.document.events but getting error “events not defined”.

    Thanks,
    ARUN AK

    • Dan Wilkerson

      Hi Arun,

      I’m not familiar with Drupal, but would there be anything wrong with wrapping it in an init function and passing in the options as an argument there? e.g.:

      Good luck with your project!

      Dan

      • ARUN AK

        Hi Dan,

        Thanks for quick response. So you are telling it is possible without editing your file?

        https://github.com/lunametrics/youtube-google-analytics/blob/master/lunametrics-youtube.gtm.js

        Thanks,
        ARUN

      • ARUN AK

        I tried with

        //Then

        But no effect..

  • http://internetmarketingcoach.com.au/ Cameron Bailey

    Are you guys thinking of creating a recipe for Vimeo videos?

    • ARUN AK
      • http://internetmarketingcoach.com.au/ Cameron Bailey

        I saw that but the import function here is so much easier!!

        Thanks for the response though.

  • lukas

    Hello Dan. I implemented the tracking as told but there is no Video Urls being displayed in GA.

  • leolion

    Hi,

    I tried to test using Universal or Classic Google Analytics Installation:

    The code is working fine if the youtube is in iframe like below…

    But we are embeding our youtube video using the video unique ID.. and appear on our site like below code:

    I am having an error implementing the second one (see attached screenshot)

    Please advise what i am missing…

    Thank you!
    Leo

    • Dani kate

      I have the same issue as you.. Hope Dan can shed some light if the code is only going to work for iframe embedded videos. Though, without iframe, I am still able to track “play” event only and not others.

      • Dan Wilkerson

        Hi Leo and Dani,

        Those both look like the older-style of Flash-object embeds to me – I believe they’re officially deprecating those style of embeds, per below:

        http://youtube-eng.blogspot.com/2015/01/youtube-now-defaults-to-html5_27.html

        The script actually tries to reformat ‘s into . I’m afraid I won’t be able to be much help here, as these sound like site-specific issues.

        Dan

        • Dani kate

          Thanks Dan for your quick response. I appreciate you being so helpful to your readers.

          Coming to my query – My video code looks like – http://screencast.com/t/wmqusUsWa2

          So, just wondering if the I would be able to work around getting my videos tracked using your script (still under this older-style flash object embed”) with the help of our developers or do I have to instead replace the embed code with tag.

          Here is y website URL – http://bit.ly/24XON3p

          Also, I would like to correct my former statement, I just checked that the event for playing the video is also not being fired. It is just one play event is captured on a page load of my website.

          Hope you can guide me in right direction.

          • Dan Wilkerson

            Hi Dani,

            I’m getting an ‘Error Establishing Database Connection’ screen – looks like I picked a bad time to check your site 🙂 hope that gets resolved quickly.

            That looks like a plugin that reads the HREF attribute and dynamically throws an iframe on the page when you click that link. If that’s the case, the latest version of the script should work with it, no problems. If it’s not working, check the source using Inspect Element and verify your query parameters are being appended to the src attribute of whatever comes into the DOM.

            Dan

  • Jack Kent

    Hi Dan,

    I have an embedded youtube video that is using a non standard URL – http://www.youtube-nocookie.com, in order to minimise leakage:

    I can’t get the tags to fire on the page – is there anything I have to do to get this to happen?

    Thanks,

    Jack

    • Dan Wilkerson

      Hi Jack,

      You’d have to modify the script to allow for that domain, which it currently won’t do. Check the checkIfYouTubeVideo and normalizeYouTubeIframe (something like those, working from memory) functions and see if you can hack it to work for that domain.

      Dan

      • Dan Wilkerson

        Also, I can’t guarantee that they support the JS API with that location, so YMMV!

        Dan

  • Julianopx

    Hello Dan,
    Is there any way to set a Click event trigger at same time at the video event?
    I want to fire a tag when the user hits 10% of the video and after click a button…

    Thank you!

    • Dan Wilkerson

      Hi Julianopx,

      Not out of the box; you’ll have to tweak the code to pass in the percentage as a number, then use that as a blocking exception on your tag (Fire when click on this button, block when attributes.percentageWatched < 10%).

      Dan

  • Shawn

    I can’t get this to track the events when the video is watched on a mobile device? Any tips on getting that to work? Here’s the URL where I have this implemented http://www.4dcircle.com/blog/if-you-could-make-a-building-talk-what-would-you-do-with-that#mant-video=

    • Dan Wilkerson

      Hi Shawn,

      Unfortunately, the code won’t work with iOS devices. I’m unsure about how Android browsers might treat it; I believe we had tested with Chrome on an Android device before and were successful, but it sounds like you’ve had a different experience?

      Dan

  • Jenn Kunz

    Great post, great script- but I do really miss the comments from lunametric’s 2012 youtube plugin post and script. They pretty much still win the internet.

    • Dan Wilkerson

      I couldn’t dare replicate Mr. Sharif’s masterful prose; we all need to know our limits.

      Thanks 🙂

      Dan

  • Shawn Segundo

    Hi Dan,

    Lost yet again, but I am confused on something in analytics reporting, but how can we have 129 events for play, yet in the same report have only 31 events for 0%? Shouldn’t the two numbers be the same?

    • Dan Wilkerson

      Hi Shawn,

      Well, not exactly – to be honest, I’ve never tried a 0% played event, so I’m not sure how the script handles that. But beyond that, a user could trigger a Play event multiple times – if they pause and play the video again, for example. Unique Events shows you how many times a play event was triggered for a video – 32, in your example, which is very close to your 0% count of 31.

      Dan

      • Shawn Segundo

        Thanks Dan!

        • http://www.simplediagrams.com Daniel McQuillen

          Hi Dan,

          Thanks for sharing your thoughts and YouTube + GA wisdom!

          A question about the “Total” vs. “Unique” events you mentioned directly above: you said that the unique number “shows you how many times a play event was triggered for a video” … what then is “total”? How many times *any* category=Video action=play event came through (regardless of label)?

          I’m having a hard time making sense of these two columns. For example, in the screenshot below I’m viewing events with primary dimension label and secondary dimension action. What would it mean then, that for one particular video with “playing” action in this table (where I assume every event is category=Videos, action=playing, label=certain-video-name), I would see 633 total events and 158 unique events in that row?

          Does that mean 158 unique users pressed play at least once on this particular video, and then — on average — each one of them hit pause/play (or track back and forth) a couple times, to give 633 “playing” events?

          Thanks for any thoughts!

          Daniel

          Thanks,

          Daniel

          • Dan Wilkerson

            Hi Daniel,

            I can’t answer with 100% specificity because the tracking your showing looks like it uses a different script then ours. That said, Unique Events is the total number of times a given combination of dimensions occurred at least once during a users session. Total events is the absolute count of times that event occurred, including if it occurred multiple times in a session. The totals will vary as you re-filter and re-organize your report; it is just for the particular combination of dimensions you’re viewing at that moment.

            For example:

          • http://www.simplediagrams.com Daniel McQuillen

            Hi Dan,

            Thanks for laying that out in such detail. That confirms my own mental model of how I thought events would be tracked (I still wish there was a ‘raw’ view that showed events like your top table!).

            With that understanding, it would seem 158 people clicked play to watch the video in my screenshot. So strange then that there are 633 total events for that same video. That’s a lot of “play” clicks for each average user interaction with that video.

            I checked another popular video and clicked through the GA Events section so that my breadcrumb read All : Event Category (Videos) > Event Label (some video title) > Event Action : playing.

            So now I should be seeing ‘playing’ events for this particular video alone. The numbers were even stranger! 186 total events but only 8 unique events (see screenshot below). Hmm…now that looks suspicious to me. I would have thought I’d see something like 16 total and 8 unique, assuming users clicked play and pause twice on average while viewing. Otherwise, if these numbers are correct, each user of eight total users is clicking play 23 times on average! I don’t know what data those events could have that would allow GA to collapse 186 events into 8.

            I feel like there are some subtleties I’m missing, which is why I wish I could see the raw events and get a better understanding of data before GA munges it.

            At any rate, thanks again for sharing your wisdom. You’ve converted me to a frequent Lunametrics blog reader!

            – Daniel

  • Bryan Myers

    Hello Dan,

    I have completed these steps several times and I am still not getting any data in Google Analytics.

    Example page: http://www.aati-us.com/tracking.html
    Most Recent GA and GTM code.

    In GTM added custom HTML tag with script.

    In GTM added both custom variables.

    In GTM created custom event trigger.

    In GTM created Google Analytics Event Tag.

    I have installed Google Tag Assistant and it is showing the events firing.

    Is there a certain amount of time that will need to pass before events appear in GA? I have not seen this question previously asked or answered.

    Thank you.

    • Dan Wilkerson

      Hi Bryan,

      It can take a while for the hits to show up in your reports, but it should be pretty quick (no more than 1-2 hours at the worst). Do you see the hits in the realtime reports? Are you using a view that would filter out your hits? Check your Unfiltered View for data.

      [EDIT:] The hits look fine at first glance when I visited your test page. Verify you’re using/checking the same UA number, just in case.

      Dan

      • Bryan Myers

        Great response time Dan.

        It has been 2 hours (worst possible time) since adding the code.

        I do see the events triggering in the GA -> Real-Time – Events section. Event Category = Videos and Event Action = Play.

        When I go to GA -> Behavior -> Events -> Overview (or top events) there are no registered events for the videos. My other custom GA events are there.

        I have triple verified the GA UA number. It is also showing in Real-Time reports, so… that seems to answer that.

        • Dan Wilkerson

          If you’re seeing the hits in realtime, that means they should be tabulating. It may just be that GA is taking longer than usual to show you them in the reports – does your account receive an very high number of hits on a daily basis? If so, your processing may be on a different schedule, which typically is 12 or 24 hour updates. If you see no new hits (at all) since 12:00, that might be what’s going on.

          Alternatively, verify that you don’t have a filter that would exclude these hits, for whatever reason, from your View.

          Dan

          • Bryan Myers

            I am still seeing Events triggered in the real time view. I will check again in the morning to either close this issue or further the investigation. Either way, I hope the information helps future users.

            Thanks again Dan.

          • Bryan Myers

            Just a heads up. I checked stats this morning and they were showing up in the main reports.

            Thank you for all your help.

          • Dan Wilkerson

            Awesome; Glad to hear it, Bryan! Feel free to pop in if anything else comes up.

            Dan

  • John Fluke

    this is good stuff. one question, will this work for playlists? For example:

    • Dan Wilkerson

      Hi John,

      Yep, agonized over getting it to work with playlists for quite a while. Last I checked it worked no issues, but let me know if you have a different experience.

      Dan

  • Olivier

    Hello, thanks for this work!

    I followed the tutorial but I’m not familiar with Google Tag Manager.
    How can I verify that it works? Is it possible to follow the events related to the video on my Google Analytics account?

    Thanks for your help!

  • Eldwin Eldwin

    Hi Dan,

    Thanks for great tutorial. I’ve been trying to setup this on GTM. This is my page http://siapa-yesus.com/ with auto play embed youtube video.

    There’s no event fired and no data in Google Analytics. Is there any specific requirement to setup embed youtube video?

    • Dan Wilkerson

      Hi Eldwin,

      I don’t see GTM or Google Analytics installed on the page – you’ll need one of those, too.

      http://www.lunametrics.com/blog/2014/12/12/google-tag-manager-snippet-placement/

      http://www.lunametrics.com/blog/2012/02/09/where-put-google-tracking-code/

      Dan

      • Eldwin

        Hi Dan,

        I put GTM code after body tag based on Google recommendation. The analytic is active already, but it can’t track the event from your youtube tracking plugin. 🙁

        • Dan Wilkerson

          Looks like it’s working to me (see attached). One more step – you’ve got to add a Google Analytics Event tag to fire a Google Analytics hit when the event is pushed to the dataLayer. See ‘Google Tag Manager Configuration’ above.

          Dan

          • Eldwin Eldwin

            Hi Dan,

            I really appreciated your response.

            I’ve added Google Analytics Event too, but it still doesn’t work.

            Is it because of 2 tags on GTM using same Google Analytics? One is based on Page View and another one is event.

            Here’s the screenshot:

  • Melinda Caughill

    HI Dan! Thank you for this!
    Just one quick question – and maybe it’s a dumb one… I’d like video plays with the 90% of Watch to End to be counted as conversions for PPC and Analytics.
    Do you have any notes/comment/general suggestions for this?
    After thinking for a bit – I’m guessing I’d create a goal using “Custom” as the GA Goal Setup, “Event” as Goal Description, and “Category” as “Videos”, Action “Play”, and then I’m stumped.
    What might the correct label be? Watch to end? And the value?
    Ugh
    Thanks and sorry for my ignorance.
    Melinda

    • Joost Thijsen

      Hi Melinda,

      I would suggest using the Custom goal based on events as you’ve mentioned. The category would be “Videos”, that is correct as well.

      However, I would put Action – regular expression – 90%|Watch to End in the event action field. This way, you combine both events into the same goal.

      If a user completes both events (most will watch to the end if they’ve passed the 90% mark), you won’t be counting the completion twice with this setup as goals tend to count unique hits during one session.

      Is this clear for you and is it what you were looking for?

      Kind regards,
      Joost

    • Dan Wilkerson

      Hi Melinda,

      I would agree with Joost’s comment below – you’ll use the action 90%.

      Dan

    • Melinda Caughill

      Just one more question – Do I have to assign a Label or Value?
      Thanks!
      Melinda

  • Joost Thijsen

    Hi Dan,

    I’m loving the plugin but can’t get it to work for one particular client. It’s a WordPress website using an Ebor Page Builder. I’ve injected the video (second, lowest video on home page) using a RAW HTML block but the youTubeTrack event is not being pushed to the dataLayer.

    I’ve installed the plugin through Google Tag Manager, using the import container function. Adjusted the UA-code as well.

    Any ideas on how to fix this issue?

    URL: http://www.zembro.com

    Kind regards,
    Joost

    • Dan Wilkerson

      Hi Joost,

      It looks like maybe the origin parameter is hard-coded but is using the wrong protocol? See attached from view-source (see attached) and there’s another chunk of code that is overwriting onYouTubeIframeAPIReady in one of the scripts that loads at the bottom of the page. The youtube listener script depends on being able to register to (note that it caches the existing function there and still calls that).

      You can experiment with changing the trigger and introducing a timeout to cause the YT script to fire after that other script, although that’s a bit hack-y (standard warnings apply).

      Dan

  • Anna Larsson

    Hi, thanks for a great site.
    Yesterday I imported your container and updated as above. Tags was fireing in Realtime mode and happily I took a break from my computer.
    BUT this morning it´s dead! GA – Event – YouTube Tracking wount fire on a WordPress site.
    Its not recorded yet in GA, I was working very late

    Same thing happend with another trackingcode from http://www.cardinalpath.com/youtube-video-tracking-with-google-tag-manager-v2-and-universal-analytics-a-step-by-step-guide/
    The tag firered once but never again. That onetime shot is recorded this morning i GA

    Whats the problem?
    Do I need to pase some information to the web agency?
    Is it somthing wrong with my Tag Manager settings?

    http://www.direktkonsult.se/aktuellt/sparbarhet-i-fiskebranchen/

    WP:

    • Dan Wilkerson

      Hi Anna,

      You’ve got other code which is probably causing a race condition/conflict (see attached) – I’d see if you could adjust when the YouTube tracking fires in order to get them to play nicely.

      Dan

      • Nick Guebhard

        Hi Dan

        I’ve got the same problem. We found that by removing the enablejsapi=1 query string parameter from the video link the tracking worked. However, obviously that string has a functional purpose. Can you advise when the YouTube tracking would need to fire to get them to play nicely? 🙂

        In our case I think the iframe API is being called so that it can be used to expand the video when someone clicks on the play button.

        Thanks
        Nick

      • Anna Larsson

        Hi, thanks for your answer.
        Unfortunaly Im not a developer but a marketer so I do not dig deeper into coding. Im not realy understand what to do. Should I talk to the web agency, as developing of the website is their responsibility.

        Me as a marketer use Tag Manager for analysing the content. Shuld I make som changes i a trigger ?

        Right before your answered I made a third try out. Used your code and implemented it according to Simo Ahava how to Track Dynamically Loaded YouTube. Could that cause any problem?
        http://www.simoahava.com/analytics/track-dynamically-loaded-youtube-videos-in-google-tag-manager/

        • Anna Larsson

          Hi,
          the probleme is solved.
          Uninstall the plug-in for Word Press and use the embedded code provided from Youtube.
          I tested Down Load File messuring — same problem. No data is sent to GA. I´ll bet it´s a plug-in again.

  • Julia Jul

    I use Google Analytics Counter Tracker. I very glad from this.

  • Patrik

    I would like recommend plugin Google Analytics Counter Tracker https://wordpress.org/plugins/analytics-counter/

  • Patrik Finch

    Thank you I think that you should use Google Analytics Counter Tracker. I tried and still used it. More information are https://wordpress.org/plugins/

  • Benjamin Knights Johnson

    Hey Dan,

    I have implemented the above through GTM Universal Analytics on this page: http://rejoindre.sondagescompares.fr (the video is on the last page), but the percentage played does not seem to be coming through to GA. I can see that the events are firing when previewing the tags, but do not see the actions in GA. The only event actions coming through are Play, Pause and Watch to End.

    Do I need to add something more than just “Play|Pause|Watch to End” to the regex for the Trigger? I am not sure how I have done this wrong?

    Thanks

    Benji

    • Dan Wilkerson

      Hi Benji,

      Remove that condition and all the percentage viewed events will come through – sorry, the post is a little out of date as percentage tracking was added on after publication.

      Dan

      • Benjamin Knights Johnson

        Thanks Dan, this worked perfectly.

        Also, quick question, when using autoplay, does this count as a play?

        Thanks

        Benji

  • http://avalancheaudiovideo.com Avalanche Audio Video

    Hey Dan – I importer the container via the recommended installation method, and the CU – YouTube Tracking Tag is firing, but the GA – Event – YouTube Tracking tag is not. It is saying the Event Action and Event Label are undefined. Any help you can provide would be appreciated!

    • Dan Wilkerson

      Can you share a link?

      Dan

  • Amy

    Hi Everyone–how come my YouTube videos now autoplay when I added this code?

    • Dan Wilkerson

      You probably had code that was preventing autoplay before that this short-circuits. The script doesn’t touch autoplay settings.

      Dan

  • Tracy

    Hi Dan,
    Thanks for the great script. I installed it on my site and it was working great until I added an SSL certificate to the site. After that none of the videos were tracked. Any idea on what could have happened?

    Thanks,
    Tracy

    • Dan Wilkerson

      Glad I could help 😉

      Dan

  • Kevin Wiles

    Hey,

    This has just solved a lot of trouble for a site I am working on but the ^ of what they have watched doesnt seem to have worked?

Contact Us.

LunaMetrics

24 S. 18th Street, Suite 100,
Pittsburgh, PA 15203

Follow Us

1.877.220.LUNA

1.412.381.5500

getinfo@lunametrics.com

Questions?
We'll get back to you
in ONE business day.