GTMのカスタムHTMLタグのタグの順序付けを設定する

## はじめに

```google_tag_manager```オブジェクト内の以下メソッドを用いたGTMのカスタムHTMLタグのタグの順序付けの設定方法について、メモ書きとして残しておくことにします。

- ```onHtmlFailure```
- ```onHtmlSuccess```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2290540/76eef0e2-d635-467b-8d8b-9677600e065a.png)

## 結論
GTMのカスタムHTMLタグにタグの順序付け設定を行うには、以下が必要となります。

1. GTMタグのGUI上のタグの順序付け設定
1. カスタムHTMLタグ内のスクリプトに以下メソッドの記述
    - ```onHtmlFailure```
    - ```onHtmlSuccess```

※ 2がなくても想定した順序でタグが発火する場合もあります。

上記メソッドで対象のカスタムHTMLタグの実行完了（成功/失敗）をGTM側に通知することで、GTMはスクリプトの実行完了を認識し、タグの順序付け設定に基づいて適切なタイミングで他タグを発火できるようになります。

## 課題

GTMのカスタムHTMLタグにGUI上のタグの順序付け設定を行っただけでは、想定した順序でタグが発火されない可能性があります。

具体的な例で説明します。

前提として、```console.log```を```setTimeout```で遅延させて実行する2種類のカスタムHTMLタグを用意し、GTMのGUI上でタグの順序付け設定を行います。

```html: tag1.js
<script>
  (function() { 
    setTimeout(function() {
      console.log('tag1');
    }, 1000);
  })();
</script>
```
```html: tag2.js
<script>
  (function() {
    setTimeout(function() {
      console.log('tag2');
    }, 2000);
  })();
</script>
```

なお、タグの順序付け設定は以下の通りとなります。

```setTimeout```の待ち時間が長い```tag2.js```(2000ms)の実行結果が出力された後に```tag1.js```(1000ms)の実行結果が出力されれば問題ありません。

| 期待する発火順 | タグ名 | setTimeoutの待ち時間（ms） |
|:-------------:|:-----------:|:------------:|
| 1 | tag2.js | 2000          |
| 2 | tag1.js | 1000          |

補足となりますが、タグの順序付け設定は```tag1.js```側のみに以下のような形で設定します。この場合、```tag2.js```にトリガーを設定しなくてもタグは発火されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2290540/b3a18b12-19dd-4b6b-b6ab-02d94b7c32d8.png)

Google ChromeのConsoleに、出力された結果は以下の通りです。

期待する発火順とは異なる結果となりました。どうやらタグの順序付け設定が想定通り動作していないようです。

![image_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2290540/a481aaeb-34a4-43c0-96e7-5d8040c0c907.png)

| 期待する発火順 | 実際の発火順 | タグ名 | setTimeoutの待ち時間（ミリ秒） |
|:-----------:|:------------:|:------------:|:------------:|
| 1 | 2 | tag2.js | 2000 |
| 2 | 1 | tag1.js | 1000 |

## 要因

タグの順序付け設定は「タグの開始順序」を制御するものであり、実際のスクリプトの実行順序までは制御できないためとなります。

## 方策

前述の課題に対しての方策が、以下メソッドとなります。

- ```onHtmlFailure```
- ```onHtmlSuccess```

上記メソッドで対象のカスタムHTMLタグの実行完了（成功/失敗）をGTM側に通知することで、GTMはスクリプトの実行完了を認識し、タグの順序付け設定に基づいて適切なタイミングで他タグを発火できるようになります。

なお、メソッドを追加するにあたり、事前に以下GTMの組み込み変数の有効化が必要となります。

- Container ID
- HTML ID

最初に発火する```tag2.js```を以下のコードに修正して、処理の成功通知をGTM側に送信します。再度、実行結果を確認してみます。

```html: tag2.js
<script>
  (function() {
    var gtm = window.google_tag_manager[{{Container ID}}];
    
    setTimeout(function() {
      console.log('tag2');
      gtm.onHtmlSuccess({{HTML ID}});
    }, 2000);
  })();
</script>
```

今度は、想定したタグの発火順となりました。

![image_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2290540/f250e986-5f15-4e6c-ba64-4f8464db2688.png)

| 期待する発火順 | 実際の発火順 | タグ名 | setTimeoutの待ち時間（ミリ秒） |
|:-----------:|:------------:|:------------:|:------------:|
| 1 | 1 | tag2.js | 2000 |
| 2 | 2 | tag1.js | 1000 |

:::note warn
今回、例として```console.log```を利用していますが、```fetch```のような
非同期処理の場合、```gtm.onHtmlSuccess({{HTML ID}});```が先に実行されるため
タグの配信順序が想定通りにならない可能性があります。
:::

## 補足

```onHtmlFailure```の使用方法についても触れておきます。

```onHtmlFailure```は、カスタムHTMLタグ内の処理が失敗した際に、GTM側に通知を行うメソッドとなります。

```html: tag2.js
<script>
  (function() {
    var gtm = window.google_tag_manager[{{Container ID}}];
    
    try {
      setTimeout(function() {
        console.log('tag2');
        gtm.onHtmlSuccess({{HTML ID}});
      }, 2000);
    } catch(error) {
      gtm.onHtmlFailure({{HTML ID}});
    }

  })();
</script>
```

GTM上の設定「添付画像赤枠」のチェックを入れれば、対象のカスタムHTMLタグの処理が失敗した際には他タグの配信を停止できます。

![image_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2290540/5352c490-2b71-4499-a903-c3dcf8bda149.png)

## メソッドの利用シーン

Simo Ahava氏は、今回のメソッドが最も効果を発揮するケースとして「非同期処理を行うカスタムHTMLタグの後に他タグを配信したいケース」をあげています。

> In my view, the purpose of tag sequencing is to establish order when the previous tag has an asynchronous operation. In other words, you want the browser to wait for the operation to complete before telling the next tag to start firing.
引用 - 「[#GTMTips: Tag Sequencing With Custom HTML Tags](https://www.simoahava.com/analytics/tag-sequencing-custom-html-tags/)」 Simo Ahava氏

具体的には、jQueryライブラリをカスタムHTMLタグで非同期的に読み込んだ後に他タグを配信するケースをあげていました。

> For example, here we load the jQuery library asynchronously, waiting for it to have completely loaded before moving to the next tag:
引用 - 「[#GTMTips: Tag Sequencing With Custom HTML Tags](https://www.simoahava.com/analytics/tag-sequencing-custom-html-tags/)」 Simo Ahava氏

たしかに、非同期処理は処理によって完了するタイミングが異なるため、GTM側に処理の成否を通知することでタグの実行順序を制御できますね。

## おわりに

私自身、GTMについてまだまだ未知な部分があると感じました。また、改めてGTMとフロントエンドの親和性の高さを再確認することができました。

アクセス解析関連ツール（GA4やGTM）の理解を深めると同時に、フロントエンドについても理解を深めていきたいです。

## 参考
https://support.google.com/tagmanager/answer/6238868?hl=ja

https://www.simoahava.com/analytics/tag-sequencing-custom-html-tags/