Google AnalyticsでYoutubeの動画がどれだけ再生されたかを分析する

#はじめに
Google Analytics Advent Calender 2日目の記事です

この記事は、以下の様な方々に捧げます。

* Webサイトに動画を埋め込んだけど、実際にそれがサイトで再生されているか動画のオーナーじゃないのでわからない。でもなんとかして再生数を知りたい。

* 動画のオーナーではあるけど、単純な再生回数ではなくて、Youtube.comで再生されたのか、自分のサイトに埋め込んだプレイヤーで再生されたのか、内訳を知りたい。
* えっ、Google Analyticsで動画計測できるの？ とりあえずやり方が知りたい
* GTM（Google Tag Manager）を使った何か便利なことをしてみたい

##前提
当記事は以下のサイトを参考に、筆者が内容を和訳・咀嚼・修正した記事です。
[YOUTUBE VIDEO TRACKING WITH GTM AND UA: A STEP BY STEP GUIDE](http://www.cardinalpath.com/youtube-video-tracking-with-gtm-and-ua-a-step-by-step-guide/)
※スクリプトの内容理解を深めるために、コードの部分等を意図的に改変しています。


##概要
Google Analytics（Universal Analytics）を使用して、
Youtubeの動画がどれだけ再生されたかを調べます。
仕込みにはGoogle Tag Managerを使用します。

##この手法を用いるメリット
そもそものYoutubeには再生数などを分析する機能が元からついています。
しかし、それを閲覧できるのは動画をアップロードしたユーザーのみです。
この手法を用いると、

* 自分のサイトに貼ったYoutube動画の再生数が計測できる
* Google Analyticsの計測と合わせることで、動画を見たユーザーの動線がわかる

などのメリットがあります。


#設定
マクロ、トリガー、タグについてそれぞれ設定していきます。


##マクロ
マクロで設定する項目は3つです

1. Youtubeの存在確認
1. dataLayerの項目追加（action）
1. dataLayerの項目追加（label）


###1.Youtubeの存在確認

|設定項目|値|
|---|---|
|名前|Youtube存在確認|
|カテゴリー|変数（Variable）|
|種類|カスタムJavascript|

以下のコードをテキストエリアに貼り付ける

```js:Youtube存在確認
/**
 * 少なくとも、最低1個あれば、trueが返る
 */
function () {
    var frames = document.getElementsByTagName('iframe');

    for (var i = 0; i < frames.length; i--){
        if (/youtube.com\/embed/.test(frames[i].src)){
            return true;
        }
    }
    return false;
}
```


###2.dataLayerの項目追加（action）

|設定項目|値|
|---|---|
|カテゴリー|変数（Variable）|
|名前|データレイヤー_action|
|種類|データレイヤーの変数|
|データレイヤーの変数名|action|
|バージョン|バージョン2|


###3.dataLayerの項目追加（label）

|設定項目|値|
|---|---|
|カテゴリー|変数（Variable）|
|名前|データレイヤー_label|
|種類|データレイヤーの変数|
|データレイヤーの変数名|label|
|バージョン|バージョン2|


--------


##トリガー
トリガーで設定するのは2つです

1. Youtubeの動画がページにあったら配信トリガー
1. Youtubeのイベントが何かしらあったら配信トリガー

###1.Youtubeの動画がページにあったら配信トリガー
|設定項目|値|
|---|---|
|カテゴリー|トリガー（Trigger）|
|名前|Youtubeトリガー|
|イベントを選択|カスタムイベント|
|配信するタイミング|{{Event}}　等しい　gtm.dom|
|配信するタイミング2|{{Youtube存在確認}}　等しい　true　|


###2.Youtubeのイベントが何かしらあったら配信トリガー
|設定項目|値|
|---|---|
|カテゴリー|トリガー（Trigger）|
|名前|Youtubeイベントトリガー|
|イベントを選択|カスタムイベント|
|配信するタイミング|{{Event}}　等しい　youtube|



---------

##タグ
タグで設定するのは2つです

* Youtubeリスナー
* Youtubeイベントタグ

###1.Youtubeリスナー

|設定項目|値|
|---|---|
|カテゴリー|タグ（Tag）|
|名前|Youtubeリスナー|
|プロダクトの選択|カスタムHTMLタグ|
|配信するタイミング|Youtubeトリガー　を選択|

以下のコードをテキストエリアに貼り付ける

```html:Youtubeリスナー
<script type="text/javascript">
/*
 * YoutubeのJavascriptAPIは、そもそもiframeで読み込むURLに
 * パラメーターでenablejsapi=1がついていないと使用することができない。
 * なので、iframeのタグを順番になめていき、
 * youtubeの埋め込み用かつそのパラメーターがついてない場合は
 * パラメーターの文字列をつけるように修正する
 */
for (var e = document.getElementsByTagName("iframe"), x = e.length; x--;)
  if (/youtube.com\/embed/.test(e[x].src))
     if(e[x].src.indexOf('enablejsapi=') === -1)
        e[x].src += (e[x].src.indexOf('?') ===-1 ? '?':'&') + 'enablejsapi=1';

// 同じページに複数のプレイヤーをサポートできるように配列形式で保持をします
var gtmYTListeners = [];

// APIがロードされた時にこのYTListenerを追加していく
function onYouTubeIframeAPIReady() {
    for (var e = document.getElementsByTagName("iframe"), x = e.length; x--;) {
        if (/youtube.com\/embed/.test(e[x].src)) {
            gtmYTListeners.push(new YT.Player(e[x], {
                events: {
                    onStateChange: onPlayerStateChange,
                    onError: onPlayerError
                }
            }));
            YT.gtmLastAction = "p";
        }
    }
}


/*
 * 再生と一時停止が押された時の処理を追加します。
 * if条件を追加することにより、巻き戻しや終了などの他の処理も追加することができます。
 * また、何％再生が完了したかの処理を仕込んでいます
 * 
 */ 
function onPlayerStateChange(e) {
    e["data"] == YT.PlayerState.PLAYING && setTimeout(onPlayerPercent, 1000, e["target"]);
    var video_data = e.target["getVideoData"](),
        label = video_data.video_id+':'+video_data.title;

    /*
     * 再生ボタンが押された時に再生イベントを発生させます。
     * 直前の動作が一時停止でないと発生しません
     * つまり、自然に停止（一度再生完了）した場合は、発生しません。
     * 何度再生完了しても、発生させたい場合はYT.gtmLastAction == "p"の条件を外します
     */ 
    if (e["data"] == YT.PlayerState.PLAYING && YT.gtmLastAction == "p") {
        dataLayer.push({
            event: "youtube",
            action: "play",
            label: label
        });
        YT.gtmLastAction = "";
    }

    /**
     * 一時停止が押された時のイベントを発生させます。
     */
    if (e["data"] == YT.PlayerState.PAUSED) {
        dataLayer.push({
            event: "youtube",
            action: "pause",
            label: label
        });
        YT.gtmLastAction = "p";
    }
}



/*
 * GTMのデータレイヤーを介してエラーレポートするための処理
 * GTMでエラーが出力されると、UniversalAnalyticsではそれをトラッキングできます
 * 例えば、動画が削除されていたり動画IDが間違っていた場合にこのエラーが動きます。
 *
 * 参考：https://developers.google.com/youtube/js_api_reference#Events
 */
function onPlayerError(e) {
    dataLayer.push({
        event: "error",
        action: "GTM",
        label: "youtube:" + e
    })
}


/*
 * 動画を何％再生したかをトラッキングします。
 * 0%、25%、50%、75%、100%を再生した時点でそのイベントを送信します。
 * 1秒毎に処理を実行して再生時間を確認し、
 * しきい値を超えていたらイベントを送信するという流れです。
 * この処理は、再生もしくは一時停止が押された時に監視が開始します。
 */
function onPlayerPercent(e) {
    if (e["getPlayerState"]() == YT.PlayerState.PLAYING) {
        var t = e["getDuration"]() - e["getCurrentTime"]() <= 1.5 ? 1 : (Math.floor(e["getCurrentTime"]() / e["getDuration"]() * 4) / 4).toFixed(2);
         if (!e["lastP"] || t > e["lastP"]) {
            var video_data = e["getVideoData"](),
                label = video_data.video_id+':'+video_data.title;
            e["lastP"] = t;
            dataLayer.push({
                event: "youtube",
                action: t * 100 + "%",
                label: label
            })
        }
        e["lastP"] != 1 && setTimeout(onPlayerPercent, 1000, e);
    }
}



/*
 * クロスブラウザ処理。
 * 参考：https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload
 */
window.onbeforeunload = function (e) {
 var e = e || window.event;
 // IEとFirefix4以前のバージョン用
 if(e)
 e.returnValue = 'na';
 // Safari用
 return 'na';
};
window.onbeforeunload = trackYTUnload;


/*
 * gtmYTUnloadが破棄された時にする処理。
 * ページが変わったり閉じる直前に行われる。
 */ 
function trackYTUnload() {
    for (var i = 0; i < gtmYTplayers.length; i++){
        if (gtmYTlisteners[i].getPlayerState() === 1) { // 再生
            var video_data = gtmYTlisteners[i]['getVideoData'](),
                label = video_data.video_id+':'+video_data.title;
            dataLayer.push({
                event: 'youtube',
                action: 'exit',
                label: label
            });
        }
    }
}



/*
 * 現在のページにYoutubeのJavascriptAPIのソースファイルを読み込む
 */
var j = document.createElement("script"),
    f = document.getElementsByTagName("script")[0];
j.src = "//www.youtube.com/iframe_api";
j.async = true;
f.parentNode.insertBefore(j, f);
</script>
```

###2.Youtubeイベントタグ

|設定項目|値|
|---|---|
|カテゴリー|タグ（Tag）|
|名前|Youtubeイベント|
|プロダクトの選択|Google Analytics|
|タグの種類を選択|ユニバーサルアナリティクス|
|トラッキングID|UA-XXXXXX-Y（ご自身のトラッキングIDを使用してください）|
|トラッキングタイプ|イベント|
|カテゴリ|{{Event}}|
|アクション|{{データレイヤー_action}}|
|ラベル|{{データレイヤー_label}}|
|配信するタイミング|Youtubeイベントトリガー　を選択|

-----------


以上のマクロ、トリガー、タグを設定することにより、
GAのイベントレポート画面で動画の再生/一時停止回数、再生進行度（0%〜100％）を確認することができます。


「動画を再生しているユーザーのほうがコンバージョン率が高い」とか、
「意外と最後まで再生しているユーザーのほうが直帰している」などの示唆を得られることが出来るかもしれません。


#余談
[YoutubeのAPIリファレンス](https://developers.google.com/youtube/js_api_reference)をみると、他にも色々とできることが書いてあります。
バッファリング中のイベントハンドラなども用意されているため、他にも何か色々と計測が出来るかもしれません。