Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

YouTube API - iframe onStateChange events

I'm using the iframe YouTube API and I want to track events, for example, sending data to google analytics, when user start and stop video.

<iframe src="https://www.youtube.com/embed/DjB1OvEYMhY"></iframe>

I looked https://developers.google.com/youtube/iframe_api_reference?csw=1 and did not find an example how to do that. The example creates iframe and defines onReady and onStateChange as well. How would I do same when I've only iframe on page?

like image 723
Dmytro Pastovenskyi Avatar asked Jul 07 '14 23:07

Dmytro Pastovenskyi


2 Answers

Here is a version that doesn't use Youtubes iframe API script. The only drawback is that the iframe API might change.

<iframe id="player" src="https://www.youtube.com/embed/dQw4w9WgXcQ?enablejsapi=1"></iframe>
var addYoutubeEventListener = (function() {

    var callbacks = [];
    var iframeId = 0;

    return function (iframe, callback) {

        // init message listener that will receive messages from youtube iframes
        if(iframeId === 0) {
            window.addEventListener("message", function (e) {

                if(e.origin !== "https://www.youtube.com" || e.data === undefined) return;
                try {
                    var data = JSON.parse(e.data);
                    if(data.event !== 'onStateChange') return;

                    var callback = callbacks[data.id];
                    callback(data);
                }
                catch(e) {}
            });
        }

        // store callback
        iframeId++;
        callbacks[iframeId] = callback;
        var currentFrameId = iframeId;

        // sendMessage to frame to start receiving messages
        iframe.addEventListener("load", function () {
            var message = JSON.stringify({
                event: 'listening',
                id: currentFrameId,
                channel: 'widget'
            });
            iframe.contentWindow.postMessage(message, 'https://www.youtube.com');

            message = JSON.stringify({
                event: "command",
                func: "addEventListener",
                args: ["onStateChange"],
                id: currentFrameId,
                channel: "widget"
            });
            iframe.contentWindow.postMessage(message, 'https://www.youtube.com');
        });
    }
})();
addYoutubeEventListener(document.getElementById("player"), function(e) {

    switch(e.info) {
        case 1:
            // playing
            break;
        case 0:
            // ended
            break;
    }
});
like image 196
Martins Balodis Avatar answered Oct 16 '22 17:10

Martins Balodis


This example listens to every play/pause action the user makes, using onPlayerStateChange with its different states, and prints (records) them.

However, you need to create your own record function to do whatever you want with this data.

You also need an ID on your iframe (#player in this case) and to add ?enablejsapi=1 at the end of its URL. And of course, make sure to include the Youtube iframe API.

Note

It's important to declare the API after your code, because it calls onYouTubeIframeAPIReady when it's ready.

<!DOCTYPE html>
<html>
<body>
    <iframe id="player" src="https://www.youtube.com/embed/DjB1OvEYMhY?enablejsapi=1"></iframe>
    <h5>Record of user actions:</h5>
    <script>
      var player;
      function onYouTubeIframeAPIReady() {
        player = new YT.Player( 'player', {
          events: { 'onStateChange': onPlayerStateChange }
        });
      }
      function onPlayerStateChange(event) {
        switch(event.data) {
          case 0:
            record('video ended');
            break;
          case 1:
            record('video playing from '+player.getCurrentTime());
            break;
          case 2:
            record('video paused at '+player.getCurrentTime());
        }
      }
      function record(str){
        var p = document.createElement("p");
        p.appendChild(document.createTextNode(str));
        document.body.appendChild(p);
      }
    </script>
    <script src="https://www.youtube.com/iframe_api"></script>
</body>
</html>

JS Fiddle Demo

like image 41
blex Avatar answered Oct 16 '22 15:10

blex