IntersectionObserverを使ってビューアブルインプ計測を試しました

## はじめに
この記事は [MicroAd Advent Calendar 2018](https://qiita.com/advent-calendar/2018/microad) の11日目の記事です。

ビューアブルインプはネット広告の効果測定の一つ重要な指標ですので、弊社も導入しています。
いくつ計測手法は存在していますが、本記事ではそのなかの一つ、[intersection-observer API](https://www.w3.org/TR/intersection-observer/) を使った手法を紹介したいと思います。

## 早速 Demo

Domoコードを`html`形式ファイルに保存しておいて、ブラウザで開いてみてどうですか。

```html
<!DOCTYPE html>
<html lang="en">
<body>
<table height="100"></table>
<p>Scroll down</p>
<table height="300"></table>
<p>Scroll down</p>
<table height="300"></table>
<p id="status" style='color:blue'></p>
<img id="target" 
src="https://cdn.qiita.com/assets/public/qiitan-adcal-2018-397463c0775635f7c02fbde287ecb110.png">
<script>
var viewableImpMeasure = function () {
    var status = document.getElementById("status");
    if (typeof IntersectionObserver != "function") {
        status.innerText = "Your browser is not supported!";
        return;
    }
    var target = document.getElementById("target");
    var init = { threshold: 0.5 };
    var timerId = undefined;
    new IntersectionObserver(function (entries, observer) {
        console.log("ratio=" + entries[0].intersectionRatio);
        if (entries[0].intersectionRatio >= init.threshold) {
            if (timerId == undefined) {
                timerId = setTimeout(function () {
                    observer.unobserve(target);
                    observer.disconnect();
                    status.innerText = "Viewable impression measured!"
                }, 1000);
            }
        } else {
            if (timerId != undefined) {
                clearTimeout(timerId);
                timerId = undefined;
            }
        }
    }, init).observe(target);
    status.innerText = "Now measuring...";
};
if (window.addEventListener) {
    window.addEventListener("DOMContentLoaded", viewableImpMeasure , false);
} else if (window.attachEvent) {
    window.attachEvent("onDOMContentLoaded", viewableImpMeasure);
}
</script>
</body>
</html>
```
スクロールしてページの底部にしばらく経ってからから `Viewable impression measured!` のような文字が表示されたのでしょうか？
ブラウザが`Safari`や`IE`場合は、残念ながら現時点 [intersection-observer API](https://www.w3.org/TR/intersection-observer/) はまだサポートしてないため計測できません、`Your browser is not supported` が表示されます。


## 詳細
それでは、実装の詳細を解説します。

```javascript
if (typeof IntersectionObserver != "function") {
    status.innerText = "Your browser is not supported!";
    return;
}
```
↑ `IntersectionObserver`を対応していないブラウザが存在しているので、そのチェックを事前に行います。

```javascript
var init = { threshold: 0.5 };
```

↑`IntersectionObserver`のイベントの発火条件を定義しています。
監視対象の可視面積が`50%以下から50%以上`に、もしくは`50%以上から50%以下`に変わった時にイベントが発生するように定義をしています。

```javascript
if (entries[0].intersectionRatio >= init.threshold) {
    if (timerId == undefined) {
        timerId = setTimeout(function () {
            observer.unobserve(target);
            observer.disconnect();
            status.innerText = "Viewable impression measured!"
        }, 1000);
    }
} 
```
↑ イベントが発生したら、ディスプレイ広告に関するビューアブルインプ判定を行います。
判定条件はこちら
1. 広告ピクセルの`50%`以上がビューアブルなスペースに表示される
2. 1秒(=`1000`ミリ秒)以上連続して上記ピクセルが表示される
一度ビューアブルインプが計測できたら、継続監視する必要がないので `unobserve(target)`と`observer.disconnect()`で監視解除します。

```javascript

else {
    if (timerId != undefined) {
        clearTimeout(timerId);
        timerId = undefined;
    }
}
```
↑ 可視面積が`50%以上から50%以下`に変わった時にはビューアブル状態の継続時間をリセットします。

```javascript
if (window.addEventListener) {
    window.addEventListener("load", viewableImpMeasure , false);
} else if (window.attachEvent) {
    window.attachEvent("onload", viewableImpMeasure);
}
```
↑ 計測キックオフの実装です。

## まとめ
[intersection-observer API](https://www.w3.org/TR/intersection-observer/) を使ってディスプレイ広告のビューアブルインプは簡単に測定できますが、サポートしていないブラウザは別途対応する必要があります。

以上、少しでもお役に立てれば幸いです！

## 参考
* [JIAAのビューアブルインプ計測ガイドライン](http://www.jiaa.org/dbps_data/_material_/localhost/topics/20170531viewable_measurement_guidance.pdf)
* [intersection-observer API](https://www.w3.org/TR/intersection-observer/)