Usage
This function runs automatically, so it is not called manually. Is this incorrect?
Additional Notes
This function checks for the video to play, pause, or end.
When played, nebula_playing_video is triggered.
When paused, nebula_paused_video is triggered.
When ended, nebula_finished_video is triggered.
This function also triggers nebula_engaged_video when the user has watched enough of the video to be considered engaged.
Source File
Located in /assets/js/modules/video.js on line 378.
No Hooks
This function does not have any filters or actions available. Request one?Note: This function contains 1 to-do comment.
nebula.youtubeStateChange = function(e){ let thisVideo = nebula.videos[nebula.getYoutubeID(e.target)]; if ( !thisVideo ){ return false; } thisVideo.title = nebula.getYoutubeTitle(e.target) ?? 'Unknown'; //Playing if ( e.data === YT.PlayerState.PLAYING ){ let thisEvent = { event_name: 'video_start', event_category: 'Videos', event_action: ( nebula.isInView(jQuery(thisVideo.element)) )? 'Play' : 'Play (Not In View)', video_title: thisVideo.title, video_provider: 'youtube', autoplay: thisVideo.autoplay }; if ( thisVideo.autoplay ){ thisEvent.event_action += ' (Autoplay)'; } else { jQuery(thisVideo.element).addClass('playing'); } nebula.dom.document.trigger('nebula_event', thisEvent); gtag('event', thisEvent.event_name, nebula.gaEventObject(thisEvent)); nebula.crm('event', 'Video Play Began: ' + thisEvent.title); nebula.dom.document.trigger('nebula_playing_video', thisVideo); let pauseFlag = true; let updateInterval = 500; try { thisVideo.current = e.target.getCurrentTime(); thisVideo.percent = thisVideo.current/thisVideo.duration; window.youtubePlayProgress = setInterval(function(){ thisVideo.current = e.target.getCurrentTime(); thisVideo.percent = thisVideo.current/thisVideo.duration; thisVideo.watched += updateInterval/1000; //Add to the watched duration thisVideo.watchedPercent = (thisVideo.watched)/thisVideo.duration; if ( !thisVideo.autoplay && thisVideo.watchedPercent > 0.25 && !thisVideo.engaged ){ if ( nebula.isInView(jQuery(thisVideo.element)) ){ let thisEvent = { event_name: 'video_engagement', event_category: 'Videos', event_action: ( thisVideo.autoplay )? 'Engaged' : 'Engaged (Autoplay)', video_title: thisVideo.title, video_provider: 'youtube', autoplay: thisVideo.autoplay, non_interaction: true }; nebula.dom.document.trigger('nebula_event', thisEvent); //@todo "Nebula" 0: This needs the new nebula_event trigger with thisEvent object gtag('event', thisEvent.event_name, nebula.gaEventObject(thisEvent)); nebula.crm('event', 'Video Engaged: ' + thisEvent.title); thisVideo.engaged = true; nebula.dom.document.trigger('nebula_engaged_video', thisVideo); } } }, updateInterval); } catch { //Ignore errors } } //Ended if ( e.data === YT.PlayerState.ENDED ){ jQuery(thisVideo.element).removeClass('playing'); if ( window.youtubePlayProgress ){ clearInterval(window.youtubePlayProgress); } let thisEvent = { event_name: 'video_complete', event_category: 'Videos', event_action: ( nebula.isInView(jQuery(thisVideo.element)) )? 'Ended' : 'Ended (Not In View)', video_title: thisVideo.title, video_provider: 'youtube', play_time: Math.round(thisVideo.watched/1000), progress: thisVideo.current*1000, autoplay: thisVideo.autoplay, non_interaction: true }; if ( thisVideo.autoplay ){ thisEvent.event_action += ' (Autoplay)'; } nebula.dom.document.trigger('nebula_event', thisEvent); gtag('event', thisEvent.event_name, nebula.gaEventObject(thisEvent)); gtag('event', 'timing_complete', { name: thisEvent.event_action, value: thisEvent.progress, event_category: thisEvent.event_category, event_label: thisEvent.title, }); nebula.crm('event', 'Video Ended: ' + thisEvent.title); nebula.dom.document.trigger('nebula_ended_video', thisVideo); //Paused } else { setTimeout(function(){ //Wait 1 second because seeking will always pause and automatically resume, so check if it is still playing a second from now try { if ( e.target.getPlayerState() == 2 && pauseFlag ){ //This must use getPlayerState() since e.data is not actually "current" inside of this setTimeout(). Paused = 2 jQuery(thisVideo.element).removeClass('playing'); if ( window.youtubePlayProgress ){ clearInterval(window.youtubePlayProgress); } let thisEvent = { event_name: 'video_pause', event_category: 'Videos', event_action: 'Paused', first_pause: !thisVideo.pausedYet, play_time: Math.round(thisVideo.watched), video_percent: Math.round(thisVideo.percent*100), progress: thisVideo.current*1000, video_title: thisVideo.title, video_provider: 'youtube', autoplay: thisVideo.autoplay }; if ( !thisVideo.pausedYet ){ thisVideo.pausedYet = true; } nebula.dom.document.trigger('nebula_event', thisEvent); gtag('event', thisEvent.event_name, nebula.gaEventObject(thisEvent)); gtag('event', 'timing_complete', { name: thisEvent.event_action, value: thisEvent.progress, event_category: thisEvent.event_category, event_label: thisEvent.title, }); nebula.crm('event', 'Video Paused: ' + thisEvent.title); nebula.dom.document.trigger('nebula_paused_video', thisVideo); pauseFlag = false; } } catch { //Ignore errors } }, 1000); } };
Override
To override or disable this JavaScript function, simply redeclare it with the exact same function name. Remember: Some functionality is conditionally loaded via dynamic imports, so if your function is not overriding properly, try listening for a DOM event (described below).
For non-module import functions:
nebula.youtubeStateChange = function(){ //Write your own code here, leave it blank, or return false. }
For dynamically imported module function overrides:
jQuery(window).on('load', function(){ nebula.youtubeStateChange = function(){ //Write your own code here, leave it blank, or return false. } });
Custom Nebula DOM events do also exist, so you could also try the following if the Window Load listener does not work:
jQuery(document).on('nebula_module_loaded', function(module){ //Note that the module variable is also available to know which module specifically was imported if ( typeof nebula.youtubeStateChange === 'function' ){ nebula.youtubeStateChange = function(){ //Write your own code here, leave it blank, or return false. } } });