【GTM】指定したURLパラメータを別ドメインへのリンクに引き継ぐカスタムHTMLタグ

指定のURLパラメータを別ドメイン向けのリンク先URLに自動付与するコード。


## まえがき

最近の広告のコンバージョントラッキングは1st-Party Cookie技術に頼るものが増えてきたため、広告のランディングページとサンクスページが異なるドメインになっている場合はコンバージョン計測漏れの発生率が高くなり、自動入札による広告配信精度の低下に繋がる場合があります。

**コンバージョンを計測できるパターン**
![1stPartyCookieによるCV計測（通常）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/3ef996b8-acbc-9e14-c496-e29f1875c2b9.png)

**コンバージョンを計測できない可能性があるパターン : LPとサンクスページのドメインが異なる**
![1stPartyCookieによるCV計測（失敗）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/67251fe8-45d7-dde1-1dfd-25e24cb7206b.png)

しかし、Yahoo広告など一部の広告媒体ではランディングページのURLに付与されたyclidのようなパラメータとその値を別ドメインに移動するリンクのURLパラメータに何らかの手段で引き継ぐことでコンバージョントラッキング精度を高めることが可能です。
本記事ではこの「何らかの手段」の一例をご共有いたします。

**LPとサンクスページのドメインが異なっていてもコンバージョンを計測できるパターン**
※ 広告サービスのタグが対応している場合のみ
![スライド3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/b4e8e1ab-d0cd-3df7-008b-0051b861f1c7.png)

> **コンバージョン測定の補完機能について**
> クロスドメインの場合の設定方法
> ウェブサイトがクロスドメインの場合、以下の設定が必要です。
> （a）コンバージョン測定タグを設置したページと同一ドメインのページに「サイトジェネラルタグ」「コンバージョン測定補完機能タグ」を設置する。
> （b）「サイトジェネラルタグ」「コンバージョン測定補完機能タグ」を動作させるために「yclid」が必要なため、**（a）でサイトジェネラルタグを設置したページに、パラメータ「yclid」を引き継ぐ**。
> ※パラメータの引き継ぎ方法は、ウェブサイトの構成によって異なります。パラメータの引き継ぎの可否も含め、サイト管理者に確認してください。
>
> コンバージョン測定の補完機能について - ヘルプ - Yahoo!広告
> https://ads-help.yahoo.co.jp/yahooads/ss/articledetail?lan=ja&aid=32877#c04

## ご利用前の注意
本コードは<font color="#ff0000">必ず入念なテストの元にご利用下さい</font>。
本コードはリンク先URLを書き換える機能を持っているため、サイト仕様や他のJavaScriptとの干渉によって「ページが開かなくなる」「注文できなくなる」「ページの内容が真っ白になる」「リンク先ページの挙動がおかしくなる」という<font color="#ff0000">重大なトラブルに繋がる</font>恐れがあります。
たとえば、幾つかの注文フォームページはシステムが予め想定していないパラメータがURLに着いた状態で開かれた場合、フォームが表示されずエラーページに強制リダイレクトします。この場合、本コードの設置によりサイトが<font color="#ff0000">注文不可能な状態</font>になります。

加えて、ドメインをまたいで情報を受け渡すこと自体についてブラウザによる制限が強化されていく流れがあるため、長期的な目線で一番理想的な対処は本コードを使わずにLPとサンクスページのドメインを一致させることで問題を解決する方法です。

## 本コードの動作について
本コードは予め指定した幾つかのURLパラメータとドメインをコードに設定した上でサイトに設置することで、
指定のURLパラメータを1st-Party Cookieに保存し、指定の外部ドメインに移動するaタグによるリンクをページ内で発見する度に保存したパラメータをリンク先URL（href属性値）に付け足して上書きします。
JavaScriptによるページ移動やフォームによる移動には非対応です。

### 動作例：パラメータ`yclid`と`affiliateid`を保存して`otherdomain.com`に引き継ぐ設定を行った場合
1. サイト訪問者が`mysite.com/lp/001.html?yclid=0523413&other=abc` に訪問 → コードによりパラメータがCookieに保存（yclid:0523413）
2. サイト訪問者が`mysite.com/lp/001.html?affiliateid=111111` に訪問 → コードによりパラメータがCookieに保存（yclid:0523413, affiliateid:111111）
3. サイト訪問者が`mysite.com/lp/001.html?yclid=1234567890&another=aaa` に訪問 → コードによりパラメータがCookieに保存。既に保存しているyclidの値が上書き（yclid:1234567890, affiliateid:111111）
4. サイト訪問者が開いた`mysite.com`内のページに`https://otherdomain.com/detail.html?hoge=foo`に移動するaタグが存在した場合 → コードによりリンク先URLが`https://otherdomain.com/detail.html?hoge=foo&yclid=1234567890&affiliateid=111111`に上書き

上書き前のリンク

```html
<a href="https://otherdomain.com/detail.html?hoge=foo">LINK</a>
```

上書き後のリンク：リンク先URLにパラメータ`yclid=1234567890&affiliateid=111111`が追加

```html
<a href="https://otherdomain.com/detail.html?hoge=foo&yclid=1234567890&affiliateid=111111">LINK</a>
```


## カスタムHTMLタグ「パラメータ引き継ぎコード」
以下のHTMLの<font color="#ff0000">幾つかの箇所を変更</font>（後述）の上カスタムHTMLタグとして作成して、広告のLPとなりうるページとドメインまたぎのリンクを持つページにて<font color="#ff0000">DOM Ready</font>のタイミングで稼働するように設定します。

トラブル発生の可能性、発生した場合の被害範囲を抑えるため、<font color="#ff0000">不必要なページ・重要なページではなるべく稼働しないように</font>設定をお願いいたします。

### コード

```html:
<script>
(function(){
  var targetParams = ['yclid', 'affiliateid'];  // 引き渡したいパラメータのリスト
  var targetDomains = ['example.com', 'mydomain.com', 'otherdomain.com'];  // パラメータを引き渡したいリンク先ドメインのリスト
  var cookieName = 'gtmStoredUrlParams';  // パラメータを保存するCookie名
  var cookieMaxAgeDays = 7;  // Cookieの有効日数
  var cookieOption = 'Secure; SameSite=Strict';

  var currentUrl = new URL(window.location.href);
  var currentUrlHost = currentUrl.hostname;
  var currentUrlParams = currentUrl.searchParams;
  var filteredDomains = targetDomains.filter(function(domain) {
    return !currentUrlHost.endsWith(domain); 
  });
  var storedParams = {};
  var storedCookieStr = document.cookie.split('; ').find(function(row) {
    return row.startsWith(cookieName + '='); 
  });
  if (storedCookieStr) {
    storedParams = JSON.parse(decodeURIComponent(storedCookieStr.split('=')[1]));
  }
  currentUrlParams.forEach(function(value, key) {
    if (targetParams.includes(key)) {
      storedParams[key] = value;
    }
  });
  var anchorElements = document.getElementsByTagName('a');
  Array.from(anchorElements).forEach(function(anchor) { 
    if (/^https?:\/\//.test(anchor.href)) {
      var anchorUrl = new URL(anchor.href);
      var anchorUrlHost = anchorUrl.hostname;
      if (filteredDomains.some(function(domain) {
        return anchorUrlHost.endsWith(domain);
      })) {
        targetParams.forEach(function(param) {
          if (storedParams.hasOwnProperty(param)) {
            anchorUrl.searchParams.set(param, storedParams[param]);
          }
        });
        anchor.href = anchorUrl.href;
      }
    }
  });
  if (Object.keys(storedParams).length !== 0) {
    var setCookieStr = cookieName + '=' + encodeURIComponent(JSON.stringify(storedParams)) + ';path=/; max-age=' + (cookieMaxAgeDays * 24 * 60 * 60) + ';' + cookieOption;
    document.cookie = setCookieStr;
  }
})();
</script>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/caf8a0a0-9308-10b1-c842-31d2c4e2544f.png)

## 要変更箇所
### targetParams : 別ドメインへのリンクに引き継ぐパラメータを複数指定
`yclid`など、ドメインをまたぐリンクに付与して別ドメインに引き継ぎたいURLパラメータをすべて記述します。

```js
var targetParams = ['yclid', 'affiliateid'];
```

### targetDomains : パラメータを引き継ぐリンク先ドメインを複数指定
広告のランディングページからサンクスページに辿り着くまでに経由するドメインすべてを記述します。ここで記述されたドメインに移動するリンクすべてにTARGET_PARAMSで指定されたパラメータが引き継がれます。
「`mydomain.otherdomain.com`へ移動するリンクにはパラメータを引き継ぎたいが`himdomain.otherdomain.com`には引き継ぎたくない」というときはサブドメインも含めて`mydomain.otherdomain.com`と指定します。

```js:
  var targetDomains = ['example.com','mydomain.com','otherdomain.com'];
```

### cookieName : パラメータを一時保存するCookieの名前
通常変更する必要はありませんが、既に同名のCookieを使用している場合など別の名前に変更可能です。

```js
  var cookieName = 'gtmStoredUrlParams';
```

### cookieMaxAgeDays : パラメータをCookieに保存する期間
通常変更する必要はりませんが、ご希望であれば変更可能です。

```js
  var cookieMaxAgeDays = 7;
```

===

以上、必ず入念なテストの元に自己責任でのご利用をお願いします。