YouTube API - iframe onStateChange events



我正在使用iframe YouTube API,我想跟踪事件,例如,发送数据到谷歌分析,当用户开始和停止视频。

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

我看了https://developers.google.com/youtube/iframe_api_reference?csw=1,没有找到一个例子如何做到这一点。这个例子创建了iframe并定义了onReady和onStateChange。当页面上只有iframe时,我该如何做呢?

这个例子监听每个播放/暂停动作的用户,使用onPlayerStateChange与它的不同的状态,并打印(记录)他们。

但是,您需要创建自己的record函数来处理这些数据。

你还需要一个ID在你的iframe (#player在这种情况下),并添加?enablejsapi=1在URL的末尾。当然,要确保包含Youtube iframe API。

注意

在你的代码之后声明API是很重要的,因为它会在准备好时调用onYouTubeIframeAPIReady

<!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

这是一个不使用youtube iframe API脚本的版本。唯一的缺点是iframe API可能会改变。

<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;
    }
});

有时事件加载不足以确保iframe内的文档准备就绪。如果iframe在不同的域中,则不可能订阅以查看它何时准备就绪。

一个可能的解决方法是记录何时从iframe接收到事件,如果订阅后没有收到事件再试一次:

var addYoutubeEventListener = (function() {
   var callbacks = [];
   var iframeId = 0;
   var subscribed = [];
   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);
                   subscribed[data.id] = true;
                   if(data.event !== 'onStateChange') return;
                   var callback = callbacks[data.id];
                   callback(data);
               }
               catch(e) {}
           }, true);
       }
       // store callback
       iframeId++;
       callbacks[iframeId] = callback;
       subscribed[iframeId] = false;
       var currentFrameId = iframeId;
       //console.log("adding event listener to iframe id " + iframeId);
       // sendMessage to frame to start receiving messages
       iframe.addEventListener("load", function () {
           var tries = 0;
           var checkSubscribed = function()
           {
               if (subscribed[currentFrameId]) {
                   //console.log("subscribed succesfully " + currentFrameId)
               }
               else
               {
                   tries++;
                   //console.log("Try again " + currentFrameId + " (" + tries + ")");
                   if (tries < 100) {
                       doSubscribe();
                   }
                   else
                   {
                       console.log("Unable to subscribe" + currentFrameId );
                   }
               }
           }
           var doSubscribe = 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');
                setTimeout(checkSubscribed, 100);
            };
            doSubscribe();
       }, true);
   }
})();

最新更新