YouTube Player Tracking Plugin v0.2 - Omniture SiteCatalyst
Ever wanted Omniture SiteCatalyst to track your embedded YouTube videos on your site? Not a bad idea and not too difficult to solve...
Update: This v0.2 is now multiplayer compatible.
Important note to v15 Users: This plugin currently only works with SC v14 media tracking. Once v15 media tracking is out of beta and I have final documentation, there might be an update.
Automatic Tracking - using the plugin:
The steps you need to do:
- Add the Omniture Media tracking module to your s_code.js (or similar). You need to have code version of H.15.1 or newer. You'll get this Media module from your Account Manager, Implementation Consultant or ClientCare.
A sample configuration could be:
s.loadModule("Media");
s.Media.autoTrack=false;
s.Media.trackWhilePlaying=true;
s.Media.trackSeconds=30;
s.Media.trackVars="None";
s.Media.trackEvents="None";
which would send the tracking information every 30s to Omniture, not track any custom props/eVars and not track any other players like Windows Media Player, QuickTime Player or RealPlayer. Check the Omniture implementation manual for your desired configuration.
- make sure you embed the video with the API turned on e.g. http://www.youtube.com/v/8pB5sRsX5OU?fs=1&rel=0&enablejsapi=1&playerapiid=myytplayer
If you use SWFObject (which I strongly suggest):
<div id="ytcontainer"></div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<script type="text/javascript">
swfobject.embedSWF("http://www.youtube.com/v/8pB5sRsX5OU?fs=1&rel=0&enablejsapi=1&playerapiid=myytplayer",
"ytcontainer", "425", "356", "8", null, null,
{allowscriptaccess:"always",allowfullscreen:"true"}, {id:"myytplayer"});
</script>
where ytcontainer is your <div>-tag you want to have the player in. You can/should host the swfobject.js on your server, so change the code above appropriately.
- put the following plugin into your s_code.js (or similar). Should be placed somewhere after your config section and before the "DO NOT ALTER ANYTHING BELOW THIS LINE !" warning.
/*
* Plugin: YouTube Tracking v0.2 - track embedded YouTube Player
* Author: Andreas Dierl - http://adlytics.de/adytt
*/
var adytt={pl:[]};adytt.p=function(){var k=function(a,b){var c=a.indexOf('?');var d=a.indexOf('#');
if(c<0){return""}var e=a.substr(c+1);if(d>0){e=a.substring(c+1,d)}var f=e.split('&');var i;
for(i=0;i<f.length;i++){var g=f[i].split('=');g[0]=unescape(g[0]);if(g[0]===b){g[1]=unescape(g[1]);
if(g[1].indexOf('"')>-1){var h=/"/g;g[1]=g[1].replace(h,'\\"')}if(g[1].indexOf('+')>-1){var j=/\+/g;
g[1]=g[1].replace(j,' ')}return g[1]}}return""};var l=function(a,b,c){if(typeof a==='object'&&a!==null)
{if(a.attachEvent){a['e'+b+c]=c;a[b+c]=function(){a['e'+b+c](window.event)};a.attachEvent('on'+b,a[b+c])}
else{a.addEventListener(b,c,false)}}};this.p=null;this.id="";this.op=false;this.pl=false;this.po=0;
this.du=0;this.bl=0;this.tp=false;this.i=function(a){var b=0;if(typeof s!=="object"){b=3}if(!b)
{this.p=document.getElementById(a);if(this.p){this.p.addEventListener("onStateChange","adytt.pl['"+a+"'].st");
var c=this;l(window,"unload",function(e){if(c.op){if(typeof c.sc==='function'){c.sc(c.po,true)}}})}}
else{}};this.sc=function(a,b){if(this.pl){s.Media.stop(this.id,a);this.pl=false;this.tp=false}
if(b&&this.op){s.Media.close(this.id);this.op=false;clearInterval(this.tf)}};this.st=function(a)
{this.tp=false;switch(a){case 0:this.sc(this.du,true);break;case 1:this.du=Math.floor(this.p.getDuration());
if(!this.op){var b=this.p.getVideoUrl();this.id="YT|"+k(b,'v');if(typeof adytt.getID==='function')
{this.id=adytt.getID({url:b})}s.Media.open(this.id,this.du,"YouTube Embedded Player",{id:this.id});
var c=this;this.tf=setInterval(function(){c.ti()},500);this.op=true}this.tp=true;break;
case 2:this.sc(Math.floor(this.po),false);break;case 3:this.bl=this.p.getVideoBytesLoaded();
this.po=this.p.getCurrentTime();if(this.bl===-1){this.sc(Math.floor(this.po),true)}
else{this.sc(Math.floor(this.po),false)}break;case-1:break;case 5:this.sc(Math.floor(this.po),false);break}};
this.ti=function(){if(!document.getElementById(this.p.id)){this.sc(this.po,true)}
else if(this.p&&(this.p.getPlayerState()===1||this.tp)){this.po=this.p.getCurrentTime();
this.bl=this.p.getVideoBytesLoaded();if(this.tp&&this.bl>0&&!this.pl){this.pl=true;this.tp=false;
s.Media.play(this.id,Math.floor(this.po))}}}};function onYouTubePlayerReady(a){a=decodeURIComponent(a);
if(adytt.pl[a]){adytt.pl[a].sc(Math.floor(adytt.pl[a].po),true);delete adytt.pl[a]}
adytt.pl[a]=new adytt.p();adytt.pl[a].i(a)}
//adytt.getID = function(o) { return o.url; };
Demo Page:
To see this plugin with out of the box s_code and media plugin from Omniture check the demo page
Notes:
- when using traditional object tag, make sure you don't have two tags with the same ID, but make sure the tag has an ID that matches the playerapiid parameter.
- default naming is YT|VideoID, e.g. "YT|8pB5sRsX5OU". Unfortunately YouTube does not make the video name available via API. So you need to classifiy the videos later in SiteCatalyst. (Update: help is coming)
- if you want to change the default naming, simply uncomment the adytt.getID function (last line of the plugin), change the code and return the name you want.
- The code is not multi-player compatible. So if you have more than one player on a page and both playing at the same time, it will mess up the data. As a workaround you can easily load the YouTube player in a layer (LightBox, ...) to only have one player playing at a time.
With version v0.2 this plugin is multiplayer compatible. Just make sure the id's don't overlap. So each player must have an unique playerapiid and id= in the embed/object tag.
Old version v0.1c can still be accessed here.
- The plugin adds an events handler to the window.onunload event to catch users that just leave the page. It tries to close the video and send the call to Omniture before leaving the page.
- Use the code above at your own risk. Always test before putting to production environments.
If you really don't want to follow my recommendation to use SWFObject, this way to implement the video manually seems to be the most-browser compatible. Make sure the plugin is loaded before the YouTube Player initializes!
<object id="myytplayer" width="425" height="344" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">
<param name="movie" value="http://www.youtube.com/v/8pB5sRsX5OU?fs=1&rel=0&enablejsapi=1&playerapiid=myytplayer"></param>
<param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always"></param>
<embed id="myytplayer2" src="http://www.youtube.com/v/8pB5sRsX5OU?fs=1&rel=0&enablejsapi=1&playerapiid=myytplayer2" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed>
</object>
-OR- Manual Tracking - writing your own code:
On the YouTube JavaScript Player API Reference page you can find the neccesary information to get the player talk to you.
The steps you need to do:
- Follow Step 1 & 2 from Automatic Tracking to have the player ready and have the Media Plugin in your s_code.js file (or similar).
- have a call back for the YouTube API:
function onYouTubePlayerReady(playerId) {
...
}
The playerId will give you the ID to reference the player.
- Get the player:
ytplayer = document.getElementById(playerId);
- and have a function to listen to the state changes:
ytplayer.addEventListener("onStateChange", "ytStateChange");
...
function ytStateChange(newState) {
...
}
- In the ytStateChange function you have to place your Omniture calls for s.Media.open(), s.Media.play(), s.Media.stop() and s.Media.close
Would be nice if you'd drop me a line if this works for you.
This plugin is published under the license of postcardware as long as you don't remove the header.
Have fun with video measurement!
Andreas
Version History:
2010-01-23 - 0.1
initial postcardware version
2010-06-10 - 0.1b
added decodeURIComponent for init
2010-10-05 - 0.1c
rewritten play/pause/.. handling, since API meant to say state=playing but bytesloaded=-1
2011-02-09 - 0.2
multiplayer version