Easily Track YouTube Videos with Google Analytics
THE PROBLEM!
I WANT TO TRACK ALL MY YOUTUBE VIDEOS EMBEDDED ON MY PAGE WITHOUT HAVING TO WRITE NEW JAVASCRIPT EVERY TIME I EMBED A VIDEO!
Recently I was tasked with tracking YouTube videos on a website using Events in Google Analytics, and I was not particularly thrilled with the options. Either old blog posts from even our site, or posts that didn’t lay out any specifics on how to do it, or posts that listed basically how the YouTube player API instructs people to track videos. Most from a year or even two ago. Which was all well and good, until I realized that I was dealing with possibly hundreds of pages, with a variable amount of videos on them.
The basic YouTube IFrame Player API shows an example of one video. And if you add a second? Well you need to add more javascript, as well as modify your HTML. If you had 10 videos on a page you would have to modify the javascript for the page to create 10 different objects, and you’d need to replace or edit the embed code to div tags. Not exactly easy, particularly for someone to go back to a site already in existence.
What I wanted was basically, maybe, a javascript file you could include on your page and then just BAM presto chango, all the basic embeded YouTube videos would be tracked, no muss no fuss, no additional JavaScript. Write a new blog post, add a new YouTube video, and have the tracking just automatically happen. I couldn’t find that.
So I wrote it.
See that video? I embedded it with standard Youtube embed code. Copy and Paste into the blog. No additional javascript. Go ahead and view the source. I’m tracking when it buffers, plays, cues, pauses, or if someone watches it to the end. All I did was copy and paste the embed code straight from YouTube on the page.

This one too. Copy. Paste. Tracked with Events in Google Analytics. Easy as pie. A monkey could do it. Well… a trained monkey.
And this one too…Don’t believe me? Use your favorite tool, and check out the source. Just iframes. Check out the Network and see the UTM gif’s flying with Event’s being Tracked for being Rick Rolled straight to our Google Analytics account.
It’s ok. You can go ahead and slow clap.
THE SOLUTION!
INCLUDE OUR SCRIPT. THE END!
Here’s what you do. No complicated coding. Just download this file and include it in the head of your html. You’ll also need Jquery so be sure to include that before the script. So you’ll have something like this…
<script src=”//code.jquery.com/jquery-1.7.2.js”></script>
<script type=”text/javascript” src=”http://www.lunametrics.com/js/lunametrics-youtube.js”></script>
And then… That’s it. The script will use jquery to scan through your page and look for iframes. Any iframe that has a standard youtube value in it’s source parameter like http://www.youtube.com/embed/ or https://www.youtube.com/embed/ will get acknowledged as a YouTube video. (if it has the -nocookie listing that is an option in Youtube we don’t track it, as it wouldn’t track anyway). Then we dynamically create the objects based on the YouTube ID’s based on their IFrame Player API and voila. All the iframes embedded on the page with the standard default YouTube embed code, as well as their https secure version, get tracked with Events in Google Analytics.

NOTES!
JUST BECAUSE IT’S NOT PERFECT!
1) It requires jquery. If you don’t have jquery on the page as well as our youtube code, it won’t work.
2) It assumes that the video is embedded only once on the page. You can have 100 videos on the page and it’ll track them all, but if you embed the same video twice it’ll actually error out because I’m using the YouTube video ID as the id for the player itself, so it’ll just overwrite itself, and the second video with the same YouTube video ID won’t get tracked.
3) I mentioned it before, but if you choose the option for “enhanced privacy mode” which sets a no cookie field in the URL, we don’t track those.
4) We track Play, Pause, Cue, Buffer, and Watch till End, but you’re free to add additional stuff to our code for your own use.
5) We strip the YouTube ID out from the URL and that’s what gets placed into the Event for identification, not the full URL.
6) This works with the embed code YouTube provides. If you copy the URL and gum up the url in the iframe with all sorts of other parameters that aren’t standard, it probably won’t work either. It’ll work with URL’s like http://www.youtube.com/embed/e90s3v_G4PU?rel=0 or http://www.youtube.com/embed/e90s3v_G4PU or https://www.youtube.com/embed/e90s3v_G4PU?rel=0 or http://www.youtube.com/embed/e90s3v_G4PU which are the basic forms that YouTube provides as the SRC value in the iframe.
7) This does NOT work with the old object code embeds, only the iFrame embeds.
8) If you don’t have Google Analytics and the Tracking Code already on your site, this won’t work without it. It works WITH jquery and the GATC, but doesn’t include either.
9) We’re not currently tracking how long the video played. We had some errors with the API and wanted to make the value of the event the duration of watching the video on both the pause, and watched till end, but have left them off for now.
DRAMATIC CONCLUSION!
Hopefully this makes some people’s lives easier. Tracking videos embedded on your site from YouTube is now a fire and forget solution. I know I was excited to get this to work, so I have to assume there are other people out there that will find this just as easy and useful.
Questions or comments? Post em below! If someone finds a problem with the code, let me know and you can help perfect it!
About Sayf Sharif
Sayf Sharif is a Web Analyst, and expert in Usability and UX, who has worked with businesses large and small to maximize their online presence since the beginning of the Web, winning numerous awards along the way. Sayf has studied human tool use from the stone age (he went to graduate school for Archaeology) to the information age (he started programing on his father’s TRS-80), and is always interested in what goals people wish to accomplish using their tools, and how successful that experience was.






That was the most entertaining script I’ve read…I guess ever.
I’ll admit I was commenting it on Saturday from my couch and taking way too much pleasure in doing so. Glad you enjoyed it.
Due to various backend issue we chose to implement all our event tracking in a similar way; including recognising and categoriesing different groups of links on given pages. There are issues as you mention, but it’s worth considering as a viable option.
Absolutely Nick. Adding in abilities so recognize groups and categories is a great addition to this type of code.
My main concern writing this was essentially thinking of a generic site with a generic blog, one where there were a myraid of videos embedded throughout the static pages, and then regular embedded videos posted on the blog, and how much a nightmare it would be to track them, particularly if the organization had a very tight IT funnel.
with code like this you could essentially add it through Google Tag Manager, if you had that working, and then without even bothering your IT department be suddenly and effectively tracking all your standard YouTube video embeds, with no other effort.
Sayf, nice code! This will save me so much time! I like the midieval-ish comments, too.
The way that the code captures the youtube id possibly needs to be broader that an exact string ?rel=0. See the available YT parameters https://developers.google.com/youtube/player_parameters#relstring .
What could be done is to use a regex in the js that pattern matches all characters after embed up until it finds a question mark. Something like: [^\?]+ would do the trick.
String matching is significantly more efficient than regex, but also more limited in use. So broadening from an exact strong match to a regex pattern would cause a small performance hit on the efficiency of your js. Something to consider to make this more awesome.
It’s interesting you bring up the Regex because that’s what I first did to match the strings to grab the ID. I agree what I have is definitely limiting, and I think probably needs to be expanded in that direction, but when i first did the regex I was a little concerned that I was leaving things off, or getting an incorrect result. I don’t recall what it was, but I decided to just go explicit for the moment. Definitely a 2.0 version of this code I think should use a decent pattern match to grab more id’s.
I think I was worried about the order of the paramters in some cases? I think I need a bigger list of possible sources for the iframe with various parameters to make sure that we don’t lose anything.
But I think you’re absolutely right, adding the regex is a definite next step to take this a notch up.
Thanks for sharing that Sayif.
The code is quite entertaining. I have written the same thing in the past. You may want to take a look at mine, even though it’s not so well commented.
https://github.com/CardinalPath/gas/blob/master/src/plugins/youtube.js
I’m quite intrigued how you don’t need to use the enablejsapi=1 query parameter in the video url. The docs say it’s required. And in my previous tests it wouldn’t work otherwise. Maybe I need to re-run some tests as I have written this plugin quite a while back and had to rewrite some parts a couple months ago when the youtube api left beta status and did some breaking changes.
It probably needs some cleanup anyway.
Eduardo, I originally didn’t add it and it worked. It looks like it throws a few security warnings in the Chrome console, but no errors, and it works, so I didn’t add it in.
I was curious as well that it was working, but if I could get it to work in my browsers without forcing a user to do anything but copy and paste their iframe embed code into their blog, I decided to try and get away with it. I’d be curious to hear how your tests go and whether it works with your code now as well.
Just tried it out and it works even without the enablejsapi=1. The errors in the console you mention happen regardless if you use it or not.
With enablejsapi: http://jsbin.com/ilutut/1/quiet
Without enablejsapi: http://jsbin.com/ilutut/2/quiet
You should take a look at mine because even though I use the enablejsapi I don’t require the user to add that. I change the iframe href on the fly. It seems hackish at first but it actually works very reliably. I even change object/embeds to iframes in order to track them with the api. So the user also doesn’t need to do anything special besides triggering my code at some point.
Thanks for sharing.
Recently I was working on some projects which also required tracking YouTube and Vimeo player events with Google Analytics. Because I couldn’t find any scripts or examples that met my requirements I wrote some scripts myself. You can find both scripts and documentation on GitHub:
https://github.com/sanderheilbron/google-analytics-youtube-video-tracking
https://github.com/sanderheilbron/google-analytics-vimeo-video-tracking
Thanks for sharing your code Sander,
The main difference is that it looks like your code still requires some Javascript work, entering in YouTube ID’s manually, unless I’m reading it wrong. That seemed pretty standard across most of the code I found that worked. My issue was that I wanted to be able to instantly apply the code I had to the head of a website so that I could immediately start tracking possibly thousands of videos across thousands of pages with an upload of 2 lines of code rather than having to go page by page by page editing page specific scripts. (as long as the videos were embedded with the standard youtube iframe).
I was thinking of say someone who had a WordPress blog and wanted to be able to just embed a video on their blog (like our LunaTV’s!) where a Social Media person, or Marketing person with no knowledge and skill with javascript could just embed the copy/paste code on their site, and have it automatically tracked.
This is great! I’m going to use this on our site and all of our clients’ sites! More writing from Sayf would be great. I love that his writing style is the perfect mix of entertaining, intelligent, professional, and accessible.
Awesomeness!
Very useful script! Just gave it a testdrive and found two issues:
1. When using the scrollbar to skip parts of the video, it triggers many events for YT.PlayerState.PAUSED;
2. When videos are set to loop, the script will not trigger the event YT.PlayerState.ENDED, event when the video is watch till the end.
Hopefully this feedback can be incorpated into the current code.
Martijn thanks for the feedback! I’ll look into both of those.
Nice script! Is there any way the title of the video could be used for the GA Event tracking label, instead of the video ID?
Well unless I read the API wrong you can’t grab the title from YouTube.
https://developers.google.com/youtube/js_api_reference#Retrieving_video_information
You can get the URL, the embed code, and the duration. It’s not optimal. We talked about it internally here at LunaMetrics about what would be preferable. Just the YouTube ID? The URL stripped of parameter garbage? Ultimately we are using different things and modifying the code for different clients. One thing you find is that with all the parameters you can have the same video track as different ones, so you want to combine those as much as possible.
Optimally we could capture both the link as well as the title, I agree, but the only way we could see to easily get the title, was to have the user enter the title manually in the iframe included on the page, or in a separate html element named and included near it. That was not my intention for this, in that I wanted something people could track their videos on a fire and forget basis by simply embedding a youtube video on their blog and have it immediately be tracked.
But if we can come up with a better and easier way to grab that title and stick it into the event, I’m all ears!
im trying to use the libs for my web but i get always a js error, at line 57 of lunametric-youtube.js: “Uncaught TypeError: Cannot call method ‘substr’ of undefined” any ideas?” it´s tracking anything T_T
Yarvit, I’m seeing that actually here on the LunaMetrics website, but I’m NOT seeing it on my test server where i’m running a stripped down HTML page. I’m wondering if it’s some sort of conflict with other code on the page? I’m looking into it.
im debuging and at line 50 of the libs:
var src = video.attr(‘src’);
it returns src as undefined;
Yeah, i’ve tried changing how the jQuery is loaded, no conflicts, jQuery(‘iframe’) rather than $. Changed the variable to vidSrc rather than src. Added a basic check to only run those substrings if vidSrc has a value…
Still comes up as an Uncaught TypeError: Cannot call method ‘substr’ of undefined.
It does bother me that i can’t reproduce the error on my test page though, there has to be some sort of conflict.
Am just checking out the script, but in the course of looking at this page’s source I noticed an error indo9cating your caching plugin isn’t working correctly:
Just wanted to let ya know in case you hadn’t spotted it yet.
Paul
Thanks Paul, but the weirdness there is that we don’t use WP Super Cache, it must be a relic comment from somewhere.
i couldnt solve it, anyone have the same prob?
Hi!
Thanks for your script, we have adopted it and made some modifications to report as we do with another script.
One note, it would be nice that you checked that vidSrc exists in your script, considering the page can have some other iframes in it that do not have a src attribute (like in our case).
Like this:
if(vidSrc && vidSrc.length>29){
Thanks again!
I have fix it
if (video[i] == undefined) {
var src = video.attr(‘src’);
} else {
var src = video[i].src;
}
its temporal, i think maybe its a problem with other iframes of the page (facebook and twitter logins)
Thanks for this post – it came at exactly the right time when I needed it. Like some others, I made a few modifications which may or may not be helpful to others. To prevent conflict with other videos on a page (which may be tracked in a different way), I added a unique id attribute to each I wanted tracked – i.e. “track123456″ – and checked that “track” was there. Like others here, I wanted a bit friendlier title passed in the label parameter of the tracking so that it would be easier to recognize the video on the GA side. So, I added functionality which takes the title from the iframe and passes it as the label. (Less hands off than your approach, but most videos on my site are added to content dynamically based on a content structure with this metadata, so it works for me. And if it’s not, then this approach is friendly enough for content editors to be trained to do.) I also changed the URL matching to this regex, which works well (though I’m sure there are regex experts who could tell me a whole bunch of things wrong with it), saves some code duplication, and doesn’t care which URL parameters exist.
var regex = /https?\:\/\/www\.youtube\.com\/embed\/([\w-]{11})(?:\?.*)?/;
var matches = vidSrc.match(regex);
If it’s a proper YouTube embed URL, then matches[1] should hold the youtubeid.
I’m going to apply these fixes and upload new code when i’ve tested it.
Does anyone have any thoughts on how best to solve the issue of it firing a slew of pause events when someone drags the player time scroll bar?
I’m testing this on a wordpress site using the slidedeck plugin, and some of my slides are not showing after adding this script (Only ‘smart’ slidedecks are affected).
The strange thing is that the slides are defined using definition lists, no iframes anywhere.. I had a quick look and the source doesn’t seem to be any different… I can’t see anything in the script that could cause this, but my Javascript skills is rather rusty. I’ll do some more testing and see if I can figure out what’s happening.
I’m using Viewbix to embed YouTube videos (works with Vimeo too) and the stats are great. I can also add an optin form for my email list. The videos get way more attention then the “vanilla” YouTube embeds.
I haven’t seen any specific data on levels of engagement with Viewbix videos, but there are other free ways to add interactive links to videos. In general though I’m not a fan of splitting analytics. I want to see in one spot, in this case Google Analytics, what is happening on the site, and how that relates to conversions. Do video viewers convert more on my site? I want to see that inside Google Analytics, etc.
Riann, I’ve seen general problems with smart slidedecks and youtube videos in general. Which slidedeck are you using? My immediate though is that the jquery is messing things up with how the jquery for the slidedeck is setup, and how the code in this is.
I’m using one called slidedeck (slidedeck.com). You can see the site on coretalk.co. For now, I’ve disabled your script, but the problem is with the slides in the sidebar (Yeah, I know – Slides in a sidebar!? – Shareholders will be shareholders though)
Yeah, obviously slidedeck uses jquery and some complicated javascript to function, and it doesn’t like something in this one. My money is still on some sort of jquery conflict.
For the paused event… Wouldn’t this work?
For your review…
var _pauseFlag = false;
….
function onPlayerStateChange(event) {
//it tries to trick us with a number one greater than
//that of our arrays. But we outsmart it.
//with math.
videoarraynum = event.target.id – 1;
//Should the video rear it’s head
if (event.data ==YT.PlayerState.PLAYING){
_gaq.push(['_trackEvent', 'Videos', 'Play', videoArray[videoarraynum] ]);
_pauseFlag = false;
}
//should the video tire out and cease
if (event.data ==YT.PlayerState.ENDED){
_gaq.push(['_trackEvent', 'Videos', 'Watch to End', videoArray[videoarraynum] ]);
}
//and should we tell it to halt, cease, heal.
if (event.data ==YT.PlayerState.PAUSED && _pauseFlag == false;){
_gaq.push(['_trackEvent', 'Videos', 'Pause', videoArray[videoarraynum] ]);
_pauseFlag = true;
}
//and should the monster think, before it doth play
//after we command it to move
if (event.data ==YT.PlayerState.BUFFERING){
_gaq.push(['_trackEvent', 'Videos', 'Buffering', videoArray[videoarraynum] ]);
}
//and should it cue
//for why not track this as well.
if (event.data ==YT.PlayerState.CUED){
_gaq.push(['_trackEvent', 'Videos', 'Cueing', videoArray[videoarraynum] ]);
}
}
This is exactly what I’ve been looking for but it’s not working. No errors, just doesn’t work.
I’m not sure but it’s possible YouTube changed something on their end. The onYouTubeIframeAPIReady function is fired before your trackYouTube function, causing the videoArray.length to be 0, therefore nothing happens.
This is definitely not working, and I’ve spent hours checking and double-checking my process. Definitely a bummer, I should have read the last two comments before devoting so much time to troubleshooting!
Google Analytics reads “4 of your visits sent events” but there is zero information regarding those events.
Ken and Trevor,
I’m not sure exactly which issues you’re having. The code as described above is working on this very site, and on our test site. Are there no other errors getting kicked up? Are the embedded videos flagged as secure or to not be tracked? Were the embedded straight from the YoutTube site? If you read this, can you email me at sharif@lunametrics.com with an example page that doesn’t work for you, including the code implementation, and the embedded iframe? I’d like to take a look to see if i can reproduce and fix the problem.
I had a little issue that some others may run into, and the fix is easy. I was getting an undefined error related to mySrc, and tracked it down to the fact that Olark generates an iframe without a src attribute which kills the rest of the loop, apparently.
I fixed it by changing this:
if(vidSrc.length>29){
to this:
if(vidSrc && vidSrc.length>29){
So basically now it checks to make sure vidSrc actually exists and then looks at the length. The length check wasn’t enough because it would throw the undefined error on the length check if vidSrc was undefined.
Hi Sayf,
Great giveaway, it solves a big problem for a lot of people.
I have a question, does this code work only with asynchronous GA tracking code or it also works with the traditional GA code?
Awesome. We always ran into issues getting accurate tracking of embedded videos on client sites. Uploaded your JS and bam! instantly tracking correctly.
Thanks
AJ,
My guess is that it might not work with the traditional code, but I haven’t tested it.
Hi Sayf,
This is a recommended approach for evaluating youtube urls and the youtube video id with regex:
URL MATCHING:
if(url.match(‘http://(www.)?youtube|youtu\.be’)) { do.something() }
GET THE ID:
var youtubeId = url.split(/v\/|v=|youtu\.be\//)[1].split(/[?&]/)[0];
Thanks for the code! It is very useful for embedded video tracking. The install takes only 2 minutes and it works!
Awesome idea!
Thanks Sayf, too bad it doesn’t work with the traditional code. I have to do the OLD School setup again for a site, how come there is no simpler way for Traditional code.
FYI, I think you need to add the http: before the link in your code above:
Great script but do you know why it doesn’t seem to work in IE? I am seeing almost no plays, pauses etc from IE users despite them making up around 30% of visits. Also I am testing a bit in IE8 and can only get events to fire intermittently. Anyone else having problems in IE?
Hi Sayf!
It seems a pretty simple tutorial. However, I didn’t manage to track the events in GA. I have added the scripts as you said. Also I have added the Youtube video with the recommended iframe code.
I got nothing. I use Asynchronous code for GA tracking. Does anyone encounter this problem with the code above?
Thanks
@Mihnea
I have the same issue. I insert the code right after my GATC and before the , with no results.
I’m a marketer by trade, know very little about coding and don’t have budget to hire anyone. That said, any suggestions for getting this tracking code to work via my Tumblr blog would be greatly appreciated
This code did not work for me either. Nothing appears in GA.
I’ve updated the code to version 2, with some of the above suggestions. It now uses regex to match the iframes, so should match more odd youtube iframe embeds better. In addition I added the pause script suggestion to prevent the rapid fire pause events that would occur on dragging the slide bar. I’ve tested the code and it’s working.
If you are having problems getting the code to fire, confirm that your jquery and youtube code is placed on the page after the main Google Analytics Tracking Code script, and that you’re linking to them correctly. Download the javascript, and host it on your own system, rather than linking to the code on lunametrics.
However the script does seem to have some Internet Explorer cross browser compatibility issues, and does not fire consistently on IE. Will look at that for the next version of the code.
Awesome! Although I didn’t use it as just an include, since I had to integrate it into a custom analytics tracking module. But I used all the ideas in it. Life saver! Thanks
Great script, except I can’t get it to work on my site. In the Chrome console an error is shown: Uncaught TypeError: Cannot call method ‘match’ of undefined. Any ideas, or anyone else having the same problem?
Tathiana,
Thanks! While it worked on my test site, I was able to reproduce your error. I added in some slightly better logic to catch that occurrance, and if you download the script again and use the new script included, there is additional logic on line 65 to catch that error, and it should now work.
Thanks for the script. We were having some issues with it not reporting on IE and I found a fix that seems to work.
I added two new booleans, documentReady and youtubeAPIReady which are set to true when those respective methods are called.
Then, I added a new method which is called by an interval:
function initialisePlayers() {
if (youtubeAPIReady && documentReady) {
clearInterval(initPlayersInterval);
trackYouTube();
constructPlayers();
}
}
I’m not sure how good of a practice this is, so any advice would be great & I hope this helps someone
Interesting, I’ll have to take a look at that.
Thanks for this! I am not familiar with javascript, so I am dependent upon great work such as this. I am, however, having some trouble. I am hoping someone can help me.
I am running a blogger site. Each post is a video. The main page shows the 5 most recent posts, and therefore contains 5 videos. Videos are placed on the page using the standard embed method.
In the header of the site template, I have added the following lines:
So here is what I get:
1. First video on the page does generate alerts.
2. Other videos on the page do not generate any alerts
3. Only two alerts are reporting: PLAY and PAUSE
What am I missing here? Thanks for the help!
Sorry… the comment engine must have stripped the script code. It’s essentially the two lines that are posted in the blog entry here after the words: ” So you’ll have something like this…”
I have one line for jquery and one line for lunametrics-youtube.js.
Ok I see it now on your site. This isn’t the first time I’ve seen this error with the code, but i can’t reproduce it on my test server, which makes me wonder exactly what is causing it.
It often seems to revolve around the matching aspect and your site is kicking up the error:
Uncaught TypeError: Cannot call method ‘match’ of undefined
Maybe that’s not being handled right in the code. I’ll see what I can do to change it, unless anyone else listening in on this thread has any suggestions.
Thanks! I did see your visit, and it looks like the first video on each of the two build pages registered the play/pause events.
I appreciate you looking into this. Your script was exactly what I needed. I’ve tried the former methods, and they don’t work with multiple videos on the same page. I was very excited to find this. Now if we can figure out what the deal is, maybe it will help others too.
For everyone else…My site is a Blogger site, so it may be unique to their formatting?? Not sure. I know only enough to get into trouble. : )
I’m way out of my comfort zone here, but I did try copy/paste the actual code into the page, rather than using your externally host js. It didn’t work either, but maybe there is some intel that will make sense to you. When I tried to use the code direct, It wouldn’t accept some of the formatting.
I had to change && references to &:& and I had to change < to $lt;
This could just be a product of the Blogger html editor (since it checks for malformed tags or code issues before letting me save) and may not really have any impact to the actual code processing in real-time, but I figured I would bring it up in case it was of some value to you as you try and troubleshoot.
Sorry….It should read:
I had to change && references to && and I had to change < to <
(I can't edit the comment)
One thing that you could do would be to try hard coding the video. It goes against my goal of this code which was to just have a script to have on all your pages to automatically track all videos across a site without hand coding anything….
However this has worked in the past when for whatever reason the client server has a problem with the match method. To change the trackYouTube function in the above code to the following, and then just have if/else statements to match the actual src value for each video on the page, and bypass a regular expression match entirely. It’s definitely a kludge, but if you only have a few videos, it could work and solve the problem.
Look at the iframe on the page, and then take the value of the src which would be something like “http://www.youtube.com/embed/YOUTUBEIDHERE” where YOUTUBEIDHERE is the YouTubeId like.. PtHET657o and copy that whole value into the line below with it, and then just the youtube id into the two spots for it there. Then even just copy and paste that entire if statement again and do it for a second video.
Essentially you’d be manually building the array of videos on the site rather than comparing them via a regex match. This wouldn’t even really be the best way to do this staticlly, because you could do it without even running through every iframe on the page to check, you could just set them, but this seemed like it might be easier to understand for a non developer.
let’s hope my code pastes below…
function trackYouTube()
{
var i = 0;
$(‘iframe’).each(function() {
var video = $(this);
var vidSrc = “”;
vidSrc = video.attr(‘src’);
if (vidSrc == “http://www.youtube.com/embed/YOUTUBEIDHERE”){
videoArray[i] = “YOUTUBEIDHERE”;
$(this).attr(‘id’, “YOUTUBEIDHERE”);
i++;
}
});
}
I appreciate the time Sayf. This option does not work in my situation, since I cannot predict which videos will be displayed at any given time They are dynamically presented based on recency, search results, etc.
Would it be possible to remove the trackYouTube function all together and just hard code adding the video ID into the array down in the page where the video actually is? I don’t know if this is possible, but I was thinking of something like this (pseudocode):
Add the code that can be loaded up front that doesn’t require the array to be in place yet.
Have the various videos iframes and an associated javascript code that simply adds the video ID to the array. No regex, no if/then, just a statement that loads with the video pages.
At the very end, after all of the array statements have been made, can I then load up the rest of the script that is dependent upon the array being complete. I imagine this is the meat of the code, loading at the end rather than up front. I realize their is some risk of activity before the script fully loads, but I see it as minimal.
Does any of this make sense, and is it possible to reconfigure in that fashion? I realize it takes away from the fire-and-forget intention of the script, but it doesn’t seem like that is going to work in my situation. I’d rather not go manually add javascript code to my 50ish videos, but will do it if that’s the way to get it to work. Future videos are not a problem, since I can just make it a part of the template for new posts.
Thanks!
Dang…looks like my “free support” expired. : ) LOL. Just kidding. I may have to look at plan B…I just can’t get this to work. Unfortunately, all of the articles and blogs that start to address the situation eventually point to this blog. Kudos for solving most everyone’s needs! Stinks, tho, that there are a few of us that this doesn’t work for. I even tried looking for conflicting javascript, but didn’t find it. I’ll continue to check back from time to time, just to see if anyone comes up with anything. Thanks!
Chris, et al,
i’ve just updated it to 2.1. I’ve added the following code.
if(video.attr(‘src’)===undefined){
var vidSrc = “”;
}else{
var vidSrc = video.attr(‘src’);
}
Before I wasn’t checking for something being undefined and it would error out on the match portion later, but only on some servers. I don’t know WHY it only happened on some servers and not others, but there it is. This check though seems to fix that Type match problem, and might solve some of the problems for people where the code would not fire.
Sayf,
Thank you, thank you, thank you!
This seems to be working great now on my site. I really appreciate it, and glad you were able to figure out the issue. I am glad I decided to check back today!
Chris, Glad that fix worked for you!
Thanks for posting this, Sayf! I was about to code the same thing, so you saved me the time. Much appreciated! I wanted to include the video time at the time of the events, so I’m glad you mentioned getting some errors in the API.
The comments in the code are amusing. =) Do you have a clean, minified version of the code available for download?
I don’t have a clean version available (though I’ve made one in the past by just hand deleting the comments). I should really just get my act together and put a version in github or something to make it easier for people to play with.
good idea for the video time in the events. I just did that with my jplayer tracker, and it’s really useful for analysis.
This just doesn’t work for me and I don’t understand why. On the JavaScript console on Google Chrome, I get this:
——-
Uncaught SyntaxError: Unexpected end of input js_lunametrics_youtube2:184
Unsafe JavaScript attempt to access frame with URL http://www.mysite.com/ from frame with URL http://www.youtube.com/embed/___________. Domains, protocols and ports must match.
Luca, the unsafe javascript attempt is normal, that’s not the problem. The Uncaught SyntaxError is. I’m not sure what’s cuasing that, it looks like maybe you renamed the file? Or edited it? It’s hard to say without looking directly at the page with the error. Something looks like it wasn’t properly implemented though.
Hi there,
Just wanted to mention a product that already does embed analytic measurement with depth tracking:
vidanalytic.com/
We also do Dailymotion and Vimeo for multi-source curators.
(P.S. I work for vidanalytic – so this is a shameless plug
)
James, I’ll allow the plug.
However, I have to say that while your service appears to give good information on video usage, it is completely disconnected from the remainder of your site tracking.
My goal with the various video tracking scripts I’ve posted is to bring in that video data to Google Analytics, where you can see where a user came from (say a campaign tagged email marketing blast) and what they did on the site (like watched a couple of videos, viewed a few product pages), and then ultimately whether they converted on your KPI (they purchased a product, they filled out a contact form, etc).
Bringing that data into Google Analytics let’s us compare how the videos perform in relation to where the visitors came from, what they also looked at on the site, and how they ultimately converted. If there are 20 videos on a website, just knowing that all 20 were viewed 10 times each doesn’t help increase our conversion by itself. Knowing however that viewing Video A led to 50% of the viewers to purchase a product, versus Video B which led to 0 purchases can let the company say “hey maybe we should use more of Video A” etc.
Sayf, that feature is definitely on our roadmap (and accelerated based on your feedback!) – we’ve seen some adoption over the past few months from folks hosting A/B test pages – and something like that will definitely take it to another level.
Hello Sayf,
I love your script! Yesterday I succeded in getting it working, I left the office got back and it wasn’t working anymore! that sound weird I know.
Looking at the console I get:
chrome.windows is not available: You do not have permission to access this API. Ensure that the required permission or manifest property is included in your manifest.json. binding:202
Uncaught TypeError: Cannot call method ‘getCurrent’ of undefined popup.js:17
Not sure this could cause it.
here you find my attempt:
I even tried to create a new blank page (which is correctly tracked by realtime on Analytics) with your code I found on the source of this page and this video:
NOthing: I see someone is browsing that page but no events is showing in realtime–>events
The weird thing is that it was working yesterday evening!
Hello,
I can’t seem to get your script to work if the videos have been embedded using the javascript method (where the iframe is created dynamically), instead of writing iframe tags into the actual html source.
That is, using this method: https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player
I can successfully attach events for onReady and onStateChange like in the example, but I would like to use your script (or a similar one) in order to not have to specify events manually for each video I embed.
When I include your script as-is, it stops the video frame from loading completely. I suspect it could be due to it creating new YT.player objects that replace the original one.
Sayf,
For the most part this seems great, and I’m really excited about this, but it seems that there is a strange anomaly happening with the reporting. The code has been running for two days, and over the past two days google Analytics is reporting that 18 of our 99 videos that have been viewed thus far have 1 transaction associated with them, with the Revenue being $277.83 exactly. I looked into our order management system and there has only been one order equaling $277.83. So could there be an issue here, or is it possible that an individual watched 18 different videos before making a purchase and each video is being tied to that purchase?
Thanks,
Chris
Hey, I tried your method & downloaded the file & followed the direction.
But still not firing off. My website is a wordpress, I get this message when I was debugging it via chrome.
Blocked a frame with origin “http://www.youtube.com” from accessing a frame with origin “http://mywebsite.com”. Protocols, domains, and ports must match.
Have you seen this before?
Leone, I’m not sure. Maybe the latest version of jQuery has an issue with something? i just checked here on LunaMetrics and it’s still working. Try putting an id on each iframe, and also moving the code up higher on the page above the GATC and see if that fixes it.
Viktor, yes this isn’t compatible with dynamically generating them. You’d have to modify the script so that our video script wouldn’t actually run until after the videos are all loaded onto the page, and then it probably would work.
Chris you should be able to tell how many people watched the videos. One way you might want to look at is to segment video viewing sessions from sessions that didn’t view videos. Create an Advanced Segment which includes video event category, and another segment which excludes them. Then you can compare visits where people viewed videos and those that didn’t.
however if you’re seeing 18 videos viewed, and they all have that same transaction amount, and no other videos do, my feeling is that it’s one person who watched them all and purchased.
Also keep in mind, I think it says this somewhere, that this still is iffy or doesn’t work at all on IE, so if you have a large volume of IE traffic, it’s not going to capture everything.
Jo that error message is normal with the script, and shouldn’t stop it from working. There must be some other problem with how you implemented the code. If you want, you could create a test page and put the URL in here as the website URL on your comment and I’ll take a quick look.
Thanks Sayf!
here’s the test page that you can look at.
http://westernshootingjournal.com/about/test/
Jo,
Not sure if that’s the right page. There was no youtube video on that page, and the youtube script itself looks like it wasn’t loaded/pointed to on the page properly.
I had to take it down for the wkend.
please look it the page now.
Is this the script to include our code?
<script type=”text/javascript” src=”http://westernshootingjournal.com/wp-content/themes/atahualpa/js/utube.js”>
If so, then the quotes are ‘curly quotes’ and need to be changed to regular quotes like “. In addition that file doesn’t appear to exist on the server. It looks like the filename was cut off. so it’s definitely not loading our script correctly that I can see.
yes that is the script.
double checking the file it does show up on my browser, I did rename the file to utube.js
It’s definitely not loading for me in Chrome. Watching the Console while the page loads I get this error:
Failed to load resource: the server responded with a status of 404 (Not Found) http://westernshootingjournal.com/about/test/%E2%80%9Dhttp:/westernshootingjournal.com/wp-content/themes/atahualpa/js/utube.js%E2%80%9D
Yes, when I run the debug in chrome, I do see this. I double checked the server, and the file is there. so I’m confuse at the moment.
I am getting a console error when any event is trying be fired, such as pressing play:
“Uncaught ReferenceError: _gaq is not defined”
If it makes any difference, the tracking code GA gave me today doesnt look like the codes I’ve used in the past (details hidden):
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,’script’,'//www.google-analytics.com/analytics.js’,'ga’);
ga(‘create’, ‘UA-########-1′, ‘domain.co.uk’);
ga(‘send’, ‘pageview’);
Mark,
Like it says in the notes, you need to be using the older ga.js code for this to work, you can find it here:
https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingOverview