In the There’s More than One Way to Play Embedded YouTube Videos! article, I described several different ways to go about embedding YouTube videos in a web page. In that tutorial, I made a passing reference to the Flash player. Well, guess what; as of January 27, 2015, both the YouTube JavaScript and ActionScript 3.0 Player API (also known as the YouTube Flash API), were officially deprecated. That leaves the IFrame Player API as the goto approach for achieving a more granular control over a video’s playback and events. In the Respond to Embedded YouTube Video Events tutorial, we learned what events the API exposes. In today’s follow-up, well take a look at some of the ways in which developers commonly respond to various events.
The IFrame API vs. Flash and JavaScript
According to YouTube, the prevailing factor in their decision to go with the IFrame API was that,
…unlike the Flash and JavaScript player APIs, which both involve embedding a Flash object on your web page, the IFrame API posts content to an <iframe> tag on your page. This approach provides more flexibility than the previously available APIs since it allows YouTube to serve an HTML5 player rather than a Flash player for mobile devices that do not support Flash.
It’s easy to think that the JavaScript API is alive and well because the IFrame API also uses JavaScript! However, the two APIs do differ in syntax. For one thing, the presence of an SWFObject would be a dead give-away to the JavaScript API. Meanwhile, event names like “onYouTubeIframeAPIReady” help identify it as part of the IFrame API.
Replacing the Page Based on Video Selection
At the end of a video, the YouTube player displays related videos within the embed iFrame. Perhaps you’d like to change the page in which the video is embedded in order to display some pertinent information about the video. Here’s a way to do that. Declare a global variable to act as a flag. In JavaScript, omitting the “var” keyword will append it to the global window namespace. When a video starts playing, set your flag to true. Then, if and when the video enters the “unstarted” state, if the flag contains a value of true, you’ll know that it’s a new video that just started playing. In that case, obtain its video ID from the event.target object and set your window location accordingly:
started = false; var onYouTubeIframeAPIReady = function(id) { var player = new YT.Player('player', { videoId: id, events: { 'onStateChange': function (event) { if (event.data == 1) { // The video started playing started = true; } if (started && event.data == -1) { // Video had already started playing before and is now in // "unstarted" state so it must be a new video. var video_url = event.target.i.videoUrl; var video_id = video_url.replace('http://www.youtube.com/watch?v=', '').replace('&feature=player_embedded', ''); window.location = '#/view/' + video_id; } } } }); }
You can see the above code in action on the http://toogl.es site.
Sending Player Event Info to Google Analytics
Tracking YouTube player events is a great way to see what your visitors are actually watching. The following onStateChange handler will pass on information about the player’s state to Google analytics via the global analytics object:
function onPlayerStateChange(event) { switch(event.data) { case YT.PlayerState.PLAYING: analytics.track('Played Video', { video: player.getVideoData().title, id: player.getVideoData().video_id, duration: player.getDuration() }) break; case YT.PlayerState.PAUSED: analytics.track('Paused Video', { video: player.getVideoData().title, id: player.getVideoData().video_id, pausedAt: player.getCurrentTime() }) break; case YT.PlayerState.ENDED: analytics.track('Finished Video', { video: player.getVideoData().title, id: player.getVideoData().video_id, duration: player.getDuration() }) break; default: return; } }
Triggering an Action when Video Reaches a Specific Timestamp
Unfortunately, the Youtube IFrame API does not include a way to trigger a JavaScript action when a YouTube video reaches a certain timestamp. As a workaround, you can create a timer that fires at the time that you specify. To avoid unnecessary processing, you can wait for player to enter PLAYING state, then invoke the setTimeout() function with the remaining time until the timestamp. In case of buffering, anytime the player resumes PLAYING states, re-invoke the same handler (timestamp_callback() in the code below), which clears the previous setTimeout and sets the new one:
var done = false; var player; function onYouTubePlayerAPIReady() { player = new YT.Player('myVideo', { height: '390', width: '640', videoId: 'rg53rweTfVcTedf', events: { 'onStateChange': stateChange } }); } var timestamp = 40; var timer; function timestamp_reached() { console.log('timestamp reached'); //do something… } function timestamp_callback() { clearTimeout(timer); current_time = player.getCurrentTime(); remaining_time = timestamp - current_time; if (remaining_time > 0) { timer = setTimeout(timestamp_reached, remaining_time * 1000); } } function stateChange(evt) { if (evt.data == YT.PlayerState.PLAYING) { timestamp_callback(); } };
Conclusion
You can do a lot using the YouTube IFrame API’s JavaScript functions, from queueing videos for playback; playing, pausing, or stoping those videos; adjusting the player volume; to retrieving information about the video being played. In addition to responding to player events, such as a player state change, you can also handle events such as a video playback quality change. For more information about YouTube IFrame API, take a look at the reference docs.