SOLVED

Tracking how long an embedded video was watched

Go to solution
Jimmy_Forde
Level 2

Tracking how long an embedded video was watched

Hello-

I am trying to edit some video tracking mechanisms into landing page templates using munchkin. I was able to implement the below code without issue and am able to track video starts and finishes. However, I want to be able to parse out how much of the video they watched into percentages ( like 25%, 50%, 75%). I have tried implementing code shown here: https://nation.marketo.com/groups/dallas-user-group/blog/2016/08/25/track-youtube-videos-in-marketo  but the video wont embed on the page whenever i try.

Is there a way to edit my current code ( below) to capture the percentages?

<div id="player"></div>  
<script>
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
document.getElementsByTagName('head')[0].appendChild(tag);

//Change 'iiqxcjxJ5Us' to video needed
var player, videoId = '{{my.Links_YoutubeID}}';
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: videoId,
events: {
'onStateChange': onPlayerStateChange
}
});
}

function onPlayerStateChange(event) {
switch( event.data ) {
//Send video started event to Marketo
case YT.PlayerState.PLAYING: Munchkin.munchkinFunction('visitWebPage', {
url: '/video/'+videoId
, params: 'video=started'
}
);
break;
//Send video finished event to Marketo
case YT.PlayerState.ENDED: Munchkin.munchkinFunction('visitWebPage', {
url: '/video/'+videoId
, params: 'video=finished'
}
);
break;
}

}
</script>
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
1 ACCEPTED SOLUTION

Accepted Solutions
SanfordWhiteman
Level 10 - Community Moderator

Re: Tracking how long an embedded video was watched

The code at

   MktoMunchkin :: YouTube Players x3 plus Percent, Gross Time

has 3 independent YouTube players, each tracking elapsed time (in seconds) and elapsed percent (time / duration).

View solution in original post

13 REPLIES 13
SanfordWhiteman
Level 10 - Community Moderator

Re: Tracking how long an embedded video was watched

Can you highlight your code (as JS) using the Advanced Editor's syntax editor? I can't read it otherwise.

Jimmy_Forde
Level 2

Re: Tracking how long an embedded video was watched

Sure, I put it here: Youtube Embed - JSFiddle 

I tested this and it works great to see if a video has been watched ( started and finished), just want to get a bit more granular if possible. I created a token for the youtube ID so the this can live in design studio and the program its used with can define what Youtube ID to track. Thanks so much for your quick reply and help!

SanfordWhiteman
Level 10 - Community Moderator

Re: Tracking how long an embedded video was watched

I mean highlighted here on the Community.

SanfordWhiteman
Level 10 - Community Moderator

Re: Tracking how long an embedded video was watched

The code at

   MktoMunchkin :: YouTube Players x3 plus Percent, Gross Time

has 3 independent YouTube players, each tracking elapsed time (in seconds) and elapsed percent (time / duration).

Jimmy_Forde
Level 2

Re: Tracking how long an embedded video was watched

Thanks! Just tried to make a test page with this, and the video wont embed on to the page. I know I must be doing something wrong, but not sure what. The code of the page below has the code above the </body> but the page is blank?

Page: https://build.amazonalexadev.com/Youtube-Integration_YoutubeHTML.html 

SanfordWhiteman
Level 10 - Community Moderator

Re: Tracking how long an embedded video was watched

I don't see the code from the JS pane of the Pen on that page.

I do see an extra Munchkin.init() though. You don't want that!

Jimmy_Forde
Level 2

Re: Tracking how long an embedded video was watched

I edited that page and I see the JS now showing. The munchkin.init is being added after the template is approved but I only see one so hopefully that inst an issue?

Do I embed the video in a normal Iframe now and this code will catch it?

Thanks!

SanfordWhiteman
Level 10 - Community Moderator

Re: Tracking how long an embedded video was watched

I only see the one Munchkin.init (the automatically added one) which is good.

To add videos, use the same structure as in the CodePen HTML pane.  Don't use Marketo's named video elements.

<div id="player" class="youtube-wrapper" data-video-id="M7lc1UVf-VE" data-video-width="640" data-video-height="340"></div>
<div id="player2" class="youtube-wrapper" data-video-id="tuSvnhcATUE" data-video-width="320" data-video-height="170"></div>
<div id="player3" class="youtube-wrapper" data-video-id="4PgW_X-7QNg" data-video-width="320" data-video-height="170"></div>
Jimmy_Forde
Level 2

Re: Tracking how long an embedded video was watched

Thanks! Confirming this works. However i'm noticing that doing it that way makes it extremely hard to scalably track how long people are watching because it seems to only record the percentage if they click or pause the video. So I wouldn't be able to pull a list of people who reached at least 25%, i could only pull people that clicked or paused a video at the 25% mark.

Alternatively, I used the below code that I tested out and it works. This watches and waits for a user to hit a certain percentage milestone ( 25%, 50%,75%) or whatever other percentage i define in the "playbackmilestones", as well as the actual time watched. That way I can pull a smart list and find every person who has watched atleast 25% of the video!

Putting the code here so other users can see and use as well.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div id="digitalpi-yt-player" data-youtube-id="YGdk0IMKzTo" data-video-width="640" data-video-height="340"></div>
<script>// Set options
var
playerEl= "digitalpi-yt-player", // id attribute of html element to be replaced with iframed video player
playbackMilestones= [ 25 , 50 , 75, 100 ], // playback percentages, log action when reached
showRelatedVideos= 0, // set to 1 to show suggested videos when the video finishes
showControls= 0, // set to 1 to show player controls
showInfo= 0, // set to 1 to show video title and player actions
autoplay= 0, // set to 1 to begin playing video immediately
playerRelHeight= .5625 // player height relative to width; .5625 for 16:9 aspect ratio; .75 for 4:3
; // close statement


/*********************** DO NOT EDIT BELOW THIS LINE **********************/


// Accepts id (with hashtag) of iframe containing YT player
// Set the height of the YouTube player proportionately to width
function setPlayerHeight( playerEl ) {
var width = jQuery(playerEl).parent().width();
jQuery(playerEl).height( Math.round(width * playerRelHeight) + "px" );
}

// Returns current time code (minutes:seconds) of video
function getTimeCode() {
var minutes = Math.floor( player.getCurrentTime() / 60);
var seconds = Math.round( player.getCurrentTime() % 60);
if(minutes < 10) minutes = "0" + minutes;
if(seconds < 10) seconds = "0" + seconds;
return minutes + ":" + seconds;
}

// Returns current percentage of video that has been played
function getPlaybackPercentage() {
return Math.round( 100 * ( player.getCurrentTime() / player.getDuration() ) );
}

// Returns unique YouTube video ID
function getVideoId() {
return player.getVideoData()['video_id'];
}

// Log video playback milestones
function logPlaybackMilestones() {
// if video is playing...
if( player.getPlayerState() == 1 ) {
// then check to see whether we're at a playback milestone
for(i=0;i<playbackMilestones.length;i++) {
// if we are...
if( !pmAchieved[i] && playbackMilestones[i] == getPlaybackPercentage() ) {
// ...make a note of that...
pmAchieved[i] = true;
// ...and tell Marketo
Munchkin.munchkinFunction('clickLink', {
href: '/munchkinVideoTracker/?video='
+ getVideoId()
+ '&movie-action=achieved-milestone&percent='
+ getPlaybackPercentage()
+ '&time='
+ getTimeCode()
});
}
}
// then check again in 1 second
setTimeout(logPlaybackMilestones,1000);
}
}


// Retrieves the data-youtube-id attribute value
youtubeVideoId = jQuery( '#'+playerEl ).data("youtube-id");

// Requires a valid youtubeVideoId to run
if( youtubeVideoId && youtubeVideoId != "false" ) {

// Track which playback milestones have been achieved
var pmAchieved = [];
for(i=0;i<playbackMilestones.length;i++) {
pmAchieved.push(false);
}

// Load YouTube iframe API
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// When the API is ready...
function onYouTubeIframeAPIReady() {

// ...create YT Player object
player = new YT.Player(playerEl, {
width: "100%",
videoId: youtubeVideoId,
events: {
'onStateChange': onPlayerStateChange
}
});

// Apply options above (by changing iframe src attribute)
jQuery("#"+playerEl).attr( "src" ,
jQuery("#"+playerEl).attr( "src" )
+ "&rel=" + showRelatedVideos
+ "&controls=" + showControls
+ "&showinfo=" + showInfo
+ "&autoplay=" + autoplay);

// Initialize player height
setPlayerHeight( "#"+playerEl );

// Reset player height whenever browser size changes
jQuery(window).on('resize orientationChange', function(event) {
setPlayerHeight( "#"+playerEl );
});

}

// When user interacts with video, tell Marketo (via Munchkin API)
function onPlayerStateChange( event ) {
switch( event.data ) {

// User played video
case YT.PlayerState.PLAYING:
Munchkin.munchkinFunction('clickLink', {
href: '/munchkinVideoTracker/?video='
+ getVideoId()
+ '&movie-action=pressed-play&percent='
+ getPlaybackPercentage()
+ '&time='
+ getTimeCode()
});
logPlaybackMilestones();
break;

// User paused video
case YT.PlayerState.PAUSED:
Munchkin.munchkinFunction('clickLink', {
href: '/munchkinVideoTracker/?video='
+ getVideoId()
+ '&movie-action=paused&percent='
+ getPlaybackPercentage()
+ '&time='
+ getTimeCode()
});
break;

// User watched video to end
case YT.PlayerState.ENDED:
Munchkin.munchkinFunction('clickLink', {
href: '/munchkinVideoTracker/?video='
+ getVideoId()
+ '&movie-action=played-to-end&percent='
+ getPlaybackPercentage()
+ '&time='
+ getTimeCode()
});
break;

}
}

}
</script>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍