How To Fix HTML5 Video Javascript Tracking Code That Does Not Work Correctly

I have JavaScript code that I found online that provides statistics for Google Analytics for my HTML5 video. However, the code only CORRECTLY displays statistics for “video playback” and “video paused,” but the rest of the information will not be displayed or even calculated. Other information:

"25% watched the video," "50% watched the video," "75% watched the video," "100% watched the video."

How can I get the code below to work correctly? Also, is Google Analytics the only way to track these characteristics, or is there another way?

<script type="text/javascript"> document.addEventListener('DOMContentLoaded', init, false) var videoId = document.getElementById('bigvid3') var videoTitle = videoId.getAttribute('data-description') var videoTitle = 'bigvid3' function init () { videoId.addEventListener('play', videoPlay, false) videoId.addEventListener('pause', videoPause, false) videoId.addEventListener('ended', videoEnd, false) videoId.addEventListener('timeupdate', videoTimeUpdate, false) } function setKeyFrames (duration) { var quarter = (duration / 4).toFixed(1) sessionStorage.setItem('one', quarter) sessionStorage.setItem('two', (quarter * 2).toFixed(1)) sessionStorage.setItem('three', (quarter * 3).toFixed(1)) } function videoTimeUpdate () { var curTime = videoId.currentTime.toFixed(1) switch (curTime) { case sessionStorage.getItem('one'): ga('send', 'event', 'video', '25% video played', videoTitle) sessionStorage.setItem('one', null) case sessionStorage.getItem('two'): ga('send', 'event', 'video', '50% video played', videoTitle) sessionStorage.setItem('two', null) case sessionStorage.getItem('three'): ga('send', 'event', 'video', '75% video played', videoTitle) sessionStorage.setItem('three', null) } } function videoPlay () { ga('send', 'event', 'video', 'video played', videoTitle) setKeyFrames(this.duration) } function videoPause () { ga('send', 'event', 'video', 'video paused', videoTitle) } function videoTimeUpdate () { ga('send', 'event', 'video', '25% video played', '50% video played', '75% video played', videoTitle) } function videoTimeUpdate () { ga('send', 'event', 'video', '25% video played', videoTitle) } function videoTimeUpdate () { ga('send', 'event', 'video', '50% video played', videoTitle) } function videoTimeUpdate () { ga('send', 'event', 'video', '75% video played', videoTitle) } function videoEnd () { ga('send', 'event', 'video', '100% video played', videoTitle) } </script> 
+5
source share
2 answers

Just to let you know, this one code even fixed will not work. There is a really good online tutorial for this, but you seem to have found the wrong one. I will do my best to simplify the process for you.

First correct the code in the original question:

 <script type="text/javascript"> document.addEventListener('DOMContentLoaded', init, false) var videoId = document.getElementById('bigvid3') //var videoTitle = videoId.getAttribute('data-description') var videoTitle = 'bigvid3' function init () { videoId.addEventListener('ended', videoEnd, false) videoId.addEventListener('timeupdate', videoTimeUpdate, false) videoId.addEventListener('play', videoPlay, false) videoId.addEventListener('pause', videoPause, false) } function setKeyFrames (duration) { var quarter = (duration / 4); sessionStorage.setItem('one', quarter); sessionStorage.setItem('two', (quarter * 2)); sessionStorage.setItem('three', (quarter * 3)); } function videoTimeUpdate () { var curTime = videoId.currentTime.toFixed(1) if (curTime > sessionStorage.getItem('one') && sessionStorage.getItem('one') != null) { ga('send', 'event', 'video', '25% video played', videoTitle) sessionStorage.setItem('one', null) } else if (curTime > sessionStorage.getItem('two') && sessionStorage.getItem('two') != null) { ga('send', 'event', 'video', '50% video played', videoTitle) sessionStorage.setItem('two', null) } else if (curTime > sessionStorage.getItem('three') && sessionStorage.getItem('three') != null) { ga('send', 'event', 'video', '75% video played', videoTitle) sessionStorage.setItem('three', null) } function videoEnd () { ga('send', 'event', videoCategory, '100% video played', videoTitle); } function videoPlay () { ga('send', 'event', videoCategory, 'video played', videoTitle); setKeyFrames(this.duration); } function videoPause (video) { var pauseCurTime = videoId.currentTime, pauseDuration = videoId.duration; ga('send', 'event', videoCategory, 'video paused', videoTitle); } </script> 

The next step is to add the markup of the google tag manager after the tag tag to open the page on which the video is located:

 <!-- Google Tag Manager --> <noscript><iframe src="//www.googletagmanager.com/ns.html?id=emblem" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','emblem');</script> <!-- End Google Tag Manager --> 

Once you have correctly configured the google tag manager to trigger / trigger events, be sure to replace the world logo with the actual google tag manager logo located in the upper left corner of the page.

Finally, add this markup to get the necessary functionality:

 <script> // Let wrap everything inside a function so variables are not defined as globals (function(){ // This is gonna our percent buckets ( 25%-75% ) //Change the variable "divisor" to create different multiples to track smaller % like 10% etc. var divisor = 25; // We're going to save our players status on this object. var videos_status = {}; // This is the funcion that is gonna handle the event sent by the player listeners function eventHandler(e){ switch(e.type) { // This event type is sent everytime the player updated it current time, // We're using for the % of the video played. case 'timeupdate': // Let set the save the current player video time in our status object videos_status[e.target.id].current = Math.round(e.target.currentTime); // We just want to send the percent events once var pct = Math.floor(100 * videos_status[e.target.id].current / e.target.duration); for (var j in videos_status[e.target.id]._progress_markers) { if (pct >= j && j > videos_status[e.target.id].greatest_marker) { videos_status[e.target.id].greatest_marker = j; } } // current bucket hasn't been already sent to GA?, let push it to GTM if (videos_status[e.target.id].greatest_marker && !videos_status[e.target.id]._progress_markers[videos_status[e.target.id].greatest_marker]) { videos_status[e.target.id]._progress_markers[videos_status[e.target.id].greatest_marker] = true; dataLayer.push({ 'event': 'gaEvent', 'gaEventCategory': 'HTML5 Video', 'gaEventAction': 'Progress_' + videos_status[e.target.id].greatest_marker + '%', // We are using sanitizing the current video src string, and getting just the video name part 'gaEventLabel': decodeURIComponent(e.target.currentSrc.split('/')[e.target.currentSrc.split('/').length - 1]) }); } break; // This event is fired when user click on the play button case 'play': dataLayer.push({ 'event': 'gaEvent', 'gaEventCategory': 'HTML5 Video', 'gaEventAction': 'Play', 'gaEventLabel': decodeURIComponent(e.target.currentSrc.split('/')[e.target.currentSrc.split('/').length - 1]) }); break; // This event is fied when user click on the pause button case 'pause': dataLayer.push({ 'event': 'gaEvent', 'gaEventCategory': 'HTML5 Video', 'gaEventAction': 'Pause', 'gaEventLabel': decodeURIComponent(e.target.currentSrc.split('/')[e.target.currentSrc.split('/').length - 1]), 'gaEventValue': videos_status[e.target.id].current }); break; // If the user ends playing the video, an Finish video will be pushed ( This equals to % played = 100 ) case 'ended': dataLayer.push({ 'event': 'gaEvent', 'gaEventCategory': 'HTML5 Video', 'gaEventAction': 'Finished', 'gaEventLabel': decodeURIComponent(e.target.currentSrc.split('/')[e.target.currentSrc.split('/').length - 1]) }); break; default: break; } } // We need to configure the listeners // Let grab all the the "video" objects on the current page var videos = document.getElementsByTagName('video'); for (var i = 0; i < videos.length; i++) { // In order to have some id to reference in our status object, we are adding an id to the video objects // that don't have an id attribute. var videoTagId; if (!videos[i].getAttribute('id')) { // Generate a random alphanumeric string to use is as the id videoTagId = 'html5_video_' + Math.random().toString(36).slice(2); videos[i].setAttribute('id', videoTagId); } // Current video has alredy a id attribute, then let use it :) else { videoTagId = videos[i].getAttribute('id'); } // Video Status Object declaration videos_status[videoTagId] = {}; // We'll save the highest percent mark played by the user in the current video. videos_status[videoTagId].greatest_marker = 0; // Let set the progress markers, so we can know afterwards which ones have been already sent. videos_status[videoTagId]._progress_markers = {}; for (j = 0; j < 100; j++) { videos_status[videoTagId].progress_point = divisor * Math.floor(j / divisor); videos_status[videoTagId]._progress_markers[videos_status[videoTagId].progress_point] = false; } // On page DOM, all players currentTime is 0 videos_status[videoTagId].current = 0; // Now we're setting the event listeners. videos[i].addEventListener("play", eventHandler, false); videos[i].addEventListener("pause", eventHandler, false); videos[i].addEventListener("ended", eventHandler, false); videos[i].addEventListener("timeupdate", eventHandler, false); videos[i].addEventListener("ended", eventHandler, false); } })(); </script> 

You will need to add this markup to the google tag manager, and not to the page where the video will be found and set the parameters.

This is a simplified version of this guide . If you do everything right, you will get what you need.

Last thing. I see absolutely nothing wrong with videoEnd. It should work. Make sure your video is not set to LOOP, otherwise it will never end and it will not be registered. Other than this, I do not see any other possibility that it would not be registered.

+1
source

the problem is that the curTime you get will probably not exactly match the value you set in your session variables. what you want to do (before you clear them) will see if the value is greater than what you check ... something like:

 function videoTimeUpdate () { var curTime = videoId.currentTime.toFixed(1) if (curTime > sessionStorage.getItem('one') && sessionStorage.getItem('one') != null) { ga('send', 'event', 'video', '25% video played', videoTitle) sessionStorage.setItem('one', null) } else if (curTime > sessionStorage.getItem('two') && sessionStorage.getItem('two') != null) { ga('send', 'event', 'video', '50% video played', videoTitle) sessionStorage.setItem('two', null) } else if (curTime > sessionStorage.getItem('three') && sessionStorage.getItem('three') != null) { ga('send', 'event', 'video', '75% video played', videoTitle) sessionStorage.setItem('three', null) } } 
+1
source

All Articles