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 395.
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 ){
thisVideo.previousState = 'playing';
if ( !thisVideo.started ){ //If this Youtube video has not yet been started
thisVideo.started = true;
let thisEvent = {
event_name: 'video_start',
event_category: 'Videos',
event_action: ( nebula.isInView(jQuery(thisVideo.element)) )? 'Play' : 'Play (Not In View)',
event_label: thisVideo.title + ' (Youtube Video)',
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 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)',
event_label: thisVideo.title + ' (Youtube Video)',
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 ){
thisVideo.previousState = '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)',
event_label: thisVideo.title + ' (Youtube Video)',
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,
non_interaction: true
});
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.playerInfo.playerState == 2 && thisVideo.previousState == 'playing' ){ //The getPlayerState() function no longer works. Using e.target since e.data is not actually "current" inside of this setTimeout(). Paused = 2
thisVideo.previousState = 'paused';
jQuery(thisVideo.element).removeClass('playing');
if ( window.youtubePlayProgress ){
clearInterval(window.youtubePlayProgress);
}
let thisEvent = {
event_name: 'video_pause',
event_category: 'Videos',
event_action: 'Paused',
event_label: thisVideo.title + ' (Youtube Video)',
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,
non_interaction: true
});
nebula.crm('event', 'Video Paused: ' + thisEvent.title);
nebula.dom.document.trigger('nebula_paused_video', thisVideo);
}
} 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.
}
}
});