Yahooタグマネージャーのデータバインディング機能をマニアックに使いこなす

Yahooタグマネージャーのデータバインディングとイベントデータバインディングについてマニアックに解説。

##公式ヘルプ
- [「データディクショナリー」について - 運用サポートツール - Yahoo! JAPAN マーケティングソリューション ヘルプ](https://help.marketing.yahoo.co.jp/ja/?p=12454)
- [「データバインディング」の作成 - 運用サポートツール - Yahoo! JAPAN マーケティングソリューション ヘルプ](https://help.marketing.yahoo.co.jp/ja/?p=12468)
- [「データバインディングエクスプレッション（DBE）」の作成 - 運用サポートツール - Yahoo! JAPAN マーケティングソリューション ヘルプ](https://help.marketing.yahoo.co.jp/ja/?p=12472)


##バインディング設定について
###データバインディング
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/103957/6ffed5ba-b82e-e641-1104-afe3b1ca5409.png)

**データバインディング**とは、**データバインディングエクスプレッション**に設定したJavaScriptコードにより出力された情報を、Yahooタグマネージャー(以下、YTMと呼ぶ)内で使える[変数](https://senews.jp/2017/10/18/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%80%8C%E5%A4%89%E6%95%B0%E3%80%8D%E3%81%A8%E3%81%AF%EF%BC%9F%E5%88%86%E3%81%8B%E3%82%8A%E3%82%84/)である**データエレメント**に格納する機能。
サイト訪問者が開いたページのURLがYahooタグマネージャーのページ設定に合致した瞬間(=PV時)に、紐付けられたタグ設定が発火する前に呼び出される。

※「変数」とはデータが一時的に記録される箱のこと。それぞれの箱には「ユーザーID」「土日判定」のような任意の名前を付けることが可能である。
![YTM_DBE.png](https://qiita-image-store.s3.amazonaws.com/0/103957/9a04a735-60f4-93fd-b6a9-4201552e7308.png)

####動作順序

1. YTMタグが設置されたWebページをサイト訪問者がブラウザで閲覧
2. 閲覧されたWebページのURLがYTM内に登録したいくつかの**ページ設定**と合致
3. 合致した**ページ設定**が呼び出され、ページ設定に登録された**データバインディング設定**が呼び出される。
4. **データバインディング設定**の**データバインディングエクスプレッション**に設定されたJavaScriptコードが動作
5. 動作の結果出力された内容が**データエレメント**に保存される
6. ページ設定に紐付けられた複数のタグ設定が動作、出力される。このときにタグの設定に応じて**データエレメント**に保存された情報を利用する

また、発火条件設定が行われたタグはこの後に動作する。

####使用例
以下のような用途に使用することができる。

- サイト訪問者のユーザーエージェント情報をJavaScriptで読み取り、スマートフォンかどうか判定して、あるタグがスマートフォン上でしか動作しないよう設定する
- 指定したCookieを持つユーザーに対してのみタグを動作させる
- 特定の商品を買い物カゴに入れて注文完了したときのみタグを動作させる
- サイト訪問者のユーザーID情報をJavaScriptで抜き出し、Webトラッキングツールに送信する
- オンラインショッピングサイトでサイト訪問者が買い物カゴに入れた商品の情報を抜き出し、これをWebトラッキングツールに送信する
- ユーザーが開いているページに表示されている商品名の情報をJavaScriptで抜き出し、加工した上でWebトラッキングツールに送信する

たとえば、`userId`というJavaScript変数にユーザーID情報が出力されており、これをWebトラッキングツールに送信したいときは、以下の何れかのコードをデータバインディングエクスプレッションに登録して、その出力結果を「ユーザーID」のような分かりやすい名前のデータエレメントに保存すれば実現できる。

```js:userIdを抜き出すコード例1
userId
```

```js:userIdを抜き出すコード例2
userId;
```

```js:userIdを抜き出すコード例3
(function(){
  return userId;
})();
```

**実行される動作のイメージ**
![image](https://qiita-image-store.s3.amazonaws.com/0/103957/04a9ceec-6c51-6ac9-8fed-f517b8a1d35c.png)

**ユーザーIDをデータエレメントに格納するデータバインディングの設定画面**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/103957/aab47ca0-beff-baf8-5c4d-37dfe4d02593.png)

**タグが送信する情報にデータエレメントを利用するタグの編集画面**
![image](https://qiita-image-store.s3.amazonaws.com/0/103957/b2ae3b90-03fd-ff4d-d774-7b61ab2870e9.png)


データエレメントをタグに組み込むときは、フォーム内編集中にのフォームの右側に現れる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/103957/dcc0a808-4a87-a07e-f883-82cf980f1751.png)
ボタンをクリックすると、使用することができるデータエレメントの一覧を表示することができる。


####データエレメントをスマートカスタムタグに組み込むとき
[スマートカスタムタグ](https://help.marketing.yahoo.co.jp/ja/?p=10544)のCustom Markupにデータエレメントを埋め込むことができる。

Custom Markup内で`[[データエレメント名]]`のように文中に書くと、コード実行前に該当箇所にデータエレメントの内容が文字列として埋め込まれた上で、完成したCustom Markupの文がhtmlとして出力される。
このとき、データエレメント内のデータ型は考慮されない。

#####実験
以下のような2つのデータエレメントを用意して出力する。

**コードから数値型の数字が出力されるデータエレメント「num 01」**
数値型での出力となるため、`return 01;`となっているが2桁目の0は無意味であり、`return 1;`と同じ出力結果となる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/103957/1d3fa7c7-d7b8-2124-8039-42c88c917c75.png)

**コードから文字列型の数字が出力されるデータエレメント「str 01」**
文字列型での出力となるため、`return '01';`の出力結果は文字列型として処理される限り「ゼロイチ」であり、「イチ」ではない。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/103957/a42be59f-d797-290f-e153-ffd2152ffb44.png)

これらがどのように扱われるのかスマートカスタムタグにデータエレメント「num 01」と「str 01」を埋め込んで検証する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/103957/23f95574-8b58-8ef1-c5ae-a9f9895a0830.png)

Consoleでの出力結果
完成したコードでは元の文字列型が無視され、5行目のコードは`console.log('2.str',01,typeof 01);`というコードとなって実行されるため、データエレメントにより埋め込まれた01は、単なる数値としての01、即ち1（イチ）として処理されている。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/103957/7eaa87ec-8eda-4569-d8fc-51708e96478b.png)

実際に実行されたコード

```html:
<script>
console.log('スマートカスタムタグ内でデータエレメントの出力結果を利用するとき、データエレメントに登録されたJSコードから出力された情報がそのままコードに埋め込まれる');
console.log('故に、データエレメント内での計算結果のデータ型は考慮されない');
console.log('1.num',1,typeof 1); // 1.num 1 number
console.log('2.str',01,typeof 01);  // 2.str 1 number
console.log('3.',1 === 01);  // 3. true

console.log('文字列型で出力したいならクォーテーションマークで囲む');
console.log('4.num','1',typeof '1');  // 4.num 1 string
console.log('5.str','01',typeof '01');  // 5.str 01 string
console.log('6.','1' === '01'); // 6. false
</script>
```

###イベントバインディング
エレメントセレクターで指定した要素への`click`イベントや`keydown`イベントなどが起きたことを検知し、タグの発火条件設定に使用することができる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103957/3a5f98cf-0bcd-11f1-daab-b63854f9c37e.png)

**活用例**
[【YTM】リンククリック時に動くように、タグを設定する方法 - でぶててのWEB録](http://tetesuke.hatenadiary.jp/entry/ytm_link_click)

また、[jQueryのtrigger()などによって発生させた独自のカスタムイベント](http://www.bokukoko.info/entry/2016/02/25/%E4%BB%8A%E6%9B%B4%E3%81%AA%E3%81%8C%E3%82%89_jQuery_%E3%81%AE_trigger_%E3%81%AE%E9%AD%85%E5%8A%9B%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E8%AA%9E%E3%82%89%E3%81%9B%E3%81%A6%E3%82%82%E3%82%89%E3%81%86)をトリガーにすることもできる。

###イベントデータバインディング
通常のデータバインディング設定はページ設定がURLに反応した瞬間に作動、結果をデータエレメントに保存するのに対し、
イベントデータバインディング設定は指定した要素への`click`イベントや`keydown`イベントなどが起きたタイミングでデータエレメントに情報を保存することができる。
イベントが起きる度にデータエレメントの内容は上書きされる。

####イベントデータバインディングの応用
イベントデータバインディングに登録したデータバインディング内のJavaScriptでは、[`this`](https://qiita.com/takkyun/items/c6e2f2cf25327299cf03)や[`arguments`](https://qiita.com/kanamin/items/63b9fcd705e680372dfb)を利用することによりイベント発生元についての情報を使用することができる。

#####thisを使った応用例

リンクがクリックされたときにクリックされたリンク先のURLをデータエレメントに保存したい場合、以下のような設定を行えば実現することができる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103957/a6ac5f5b-2983-1bc9-70a3-08bb83ff13e3.png)

**データバインディングエクスプレッション**

```js:
this.href;
```

#####argumentを使った応用例

カスタムイベントを起こす関数`trigger()`の第2引数にイベントに関係する情報を乗せて…

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103957/a5438362-ab34-5b22-bf27-aae0bf9e5d83.png)

イベントデータバインディングの`arguments[1]`で拾って「`trigger()`の第2引数に乗せられた情報」をデータエレメントに格納。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103957/b4985fe1-9d64-d742-3e16-dcb8b1bc9532.png)

データエレメントに格納した情報を広告媒体に情報を送信！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103957/3e9813ec-aac1-9384-d9bc-0f1d2a601419.png)

以下のコードをサイトに埋め込んで、triggerされたカスタムイベントに載せられたパラメータを`arguments[1]`で拾うと捗る。

- [目的のスクロール量到達を検知して何かするためのJavaScriptコード - Qiita](https://qiita.com/AQRiL_1132/items/4212d8ccc0abda83141d)
- [時間経過により何かするためのJavaScriptコード - Qiita](https://qiita.com/AQRiL_1132/items/12e1547b9bc1002033de)


##データバインディング・イベントバインディングの特性
「訪問者のデバイスによって`PC`,`mobile`,`tablet`,`other`と返すデータバインディングエクスプレッション」をデータエレメント「デバイス判定」に出力するデータバインディング設定をページ設定Aに行ったとき、
ページ設定Aに紐付いたタグ設定αがデータエレメント「デバイス判定」を使えるのは勿論、同じURLに反応したページ設定Bに紐付けられたタグ設定βもデータエレメント「デバイス判定」を使うことができる。

![スライド2.PNG](https://qiita-image-store.s3.amazonaws.com/0/103957/1e61c28b-c5f9-4e59-c35a-c443bf23a5e4.png)


また、イベントバインディングについて、同一のイベントバインディング設定を複数のページ設定に対して行った上で、一つのURLに対しこれらの複数のページ設定が同時に反応した場合、反応したページ設定の数だけイベントが重複して発生する。

データバインディングについても同様に、同一のデータエレメントに情報を保存する複数のデータバインディングが一度に動作した場合、一番最後に動作したデータバインディング設定がそれまでのデータエレメントの内容を上書きしてしまう。

###解決策
ページ設定そのものを整理するか、バインディング専用のページ設定を作ることにより、重複あるいは競合するバインディング設定が同時に複数呼び出されないようにする。