ネット広告用のFriendly iFrameを作る


## 前提

ネット広告を配信する枠としてのFriendly iFrameを前提にしています。
また、広告を配信する側の立場としてのお話です。

## そもそもiframeって？

>入れ子になった閲覧コンテキストを表現し、実際に現在のページに他の HTML ページを埋め込むことができます。[*1]

[*1]:https://developer.mozilla.org/ja/docs/Web/HTML/Element/iframe

### iframeの面倒なところ

同じドメインでiframeを呼び出す場合は問題ないんですが、異なるドメインをiframeで呼び出す場合、クロスオリジン対応をしないとiframe内部、さらにiframe内から外部のHTMLにアクセスできません。

つまり、リファラーも取れないし、「300x250のレクタングルの枠だけど、パスバックで320x50のバナー出したいからiFrameの枠を変更しちゃえ」的なDOM操作もできない。

素のiFrameでは、ネット広告的には面倒なことがいっぱいなのです。

## SafeFrameとFrinedly iFrame

ネット広告で使われる代表的なiFrameとして、SafeFrame（以下、SF）とFrinedly iFrame(以下、FIF)という二種類があります。

### SafeFrame

>ページ コンテンツと広告の間の透過的でリッチな通信を実現すると同時に、広告がサイト運営者のデータにアクセスするのを防止するクロスドメインのiFrameです。[*2]

Google謹製の広告配信システム、DoubleClick for Publishers（以下、DFP）激推しのiFrame。（というかDFPでしか扱ってない）

> 追記
> 2024/08/14時点、主要な広告はSafeFrameのようです。

DFPで広告を作る際、デフォルトでSFに設定されます。

媒体（サイト）側はリファラー取ったりはできるけど、広告側からサイト上のコンテンツやデータにアクセスできない、つまりiFrameやサイト上のコンテンツに対するDOM操作もできません。

◯セキュリティ
✕柔軟性


[*2]:https://support.google.com/dfp_premium/answer/183282?hl=ja

※追記
SFでもAPI等を使って色々できるそうです。

- [「SafeFrame ver1.1 仕様読解、媒体側の実装例」](https://qiita.com/nag4/items/de044690dd227865a134)
- [iab SafeFrame](https://www.iab.com/guidelines/safeframe/)

### Friendly iFrame

媒体からリファラー取れる、広告側からサイト上のコンテンツやデータにアクセスできる、つまりDOM操作もやり放題なiFrameです。

「300x250の広告のパスバックに320x180の動画を設定して、さらにそのパスバックに320x50のバナーを出したい！」というサイズ違いの広告も、DOM操作によって素敵に表示することができます。

様々なサイズや種類の広告を紐付けると、収益性も上がる（？）ので、基本的にはFIFを推奨していきたい所存。


ただ、収益性よりも安全性を取りたい場合はSFが良いと思います。
あと、将来的にはSFも色々柔軟になるのでは？と思ってます。

## FIF実装ベストプラクティス

オンライン広告の国際的な仕様決めを行っている組織・IAB（Interactive Advertising Bureau）によるFIF実装のベストプラクティス。[*3]

[*3]:https://www.iab.com/wp-content/uploads/2015/09/rich_media_ajax_best_practices.pdf

-  IFrame要素を作成し、SRCをabout：selfに設定して文書に配置します
- サードパーティのurlを指定したスクリプト要素をiFrame内に配置します
-  IFrameドキュメント内でinDapIF = trueという変数を生成し、動的IFrame内で実行されている広告コードを識別します

コードにするとこんな感じ。

```js
var target = document.getElementById('targetID'); 
var iframe = document.createElement('iframe'); //動的にiframeを作成
iframe.width = 300;
iframe.height = 250;
iframe.frameBorder = "0";
iframe.scrolling = "no";
iframe.marginWidth = 0;
iframe.marginHeight = 0;
iframe.src = "about:self"; //iframeのsrcをabout:selfに設定
target.appendChild(iframe);
var src = adUrl; // サードーパーティのurl
var doc = iframe.contentWindow.document;
doc.open();
var d = "";
d += '<html><head></head>';
d += '<body>';
d += '<script src="'+src+'"></script>'; //サードパーティのurlをスクリプトに設定
d += '<script>inDapIF = true;</script>';
d += '</body></html>';
doc.write(d);
doc.close();
```
（参考：[「Friendly iFrameで広告コードを遅延読み込みする」](http://kakakazuma.hatenablog.com/entry/2015/03/10/221117)）


## 現実

FIFを作るだけならもっと簡単です。

- iFrameを動的に作成し、サードパーティのurlをsrcに指定する。

のみ。

コードにするとこんな感じ。

```js
var target = document.getElementById('targetID'); 
var iframe = document.createElement('iframe');
iframe.width = 300;
iframe.height = 250;
iframe.frameBorder = "0";
iframe.scrolling = "no";
iframe.marginWidth = 0;
iframe.marginHeight = 0;
var src = adUrl;
iframe.src = adUrl
var doc = iframe.contentWindow.document;
```

about:selfじゃなくても、inDapIFなくてもFIFになります。

## おまけ

また、SFかFIFかを判定するには、以下のスクリプトを使ってください。

```iframe判定.js
if (window !== parent) {
  //iframe
  if (window.$sf) {
    //safeframe
    console.log('SF');
  } else {
    try {
      //friendly iframe
      console.log('FIF');
    } catch (e) {
      // FIFじゃないとconsole.logはエラーになります
      // cross-domain iframe
      console.log('iFrame');
    }
  }
} else if (window === parent) {
  //not iframe
  console.log('notIFrame');
}
```

## 参考

*1 [MDN <iframe>](https://developer.mozilla.org/ja/docs/Web/HTML/Element/iframe)
*2 [GPT リクエストとレンダリング モード(DoubleClick for Publishers ヘルプ)](https://support.google.com/dfp_premium/answer/183282?hl=ja)
*3 [Best Practices for Rich Media Ads in Asynchronous Ad Environments](https://www.iab.com/wp-content/uploads/2015/09/rich_media_ajax_best_practices.pdf)