GA4によるカスタムディメンション値の自動変換とその対策

GA4とUniversal Analyticsは別のツールなので様々な点で挙動が異なっています。
注意すべき挙動の１つとしてGA4ウェブストリームのカスタムディメンションに情報を送信したときに**値が数値とみなされて自動変換される**ことがあります。

この挙動は**数字と一部の記号や英字からなるIDのような文字列情報**をGA4のカスタムディメンションに送信するときに問題となる場合があります。また、Androidのアプリストリーム経由で文字列を送信したときは自動変換されないので、アプリストリームとウェブストリームの同じカスタムディメンションに同じ値を送っていてもレポートの同じ行に集計されない状況が発生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/f2590378-411d-ca40-998a-a25f33c6cb3e.png)

※ GA4は頻繁に改良が行われているプロダクトのため、本記事で紹介する動作は今後変更される可能性があります。

## カスタムディメンションの自動変換が発生する状況の例
自動変換が発生する状況を再現するため、サイト上のdataLayerに出力された「`0001234E-05`」のような商品IDの値をGA4のカスタムディメンション「item_id」に送信する設定を作成して動作を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/aae7c865-2b5f-ce89-4800-00f82165ae90.png)

カスタムディメンションの値はGTMプレビューモードとブラウザのDevToolsで通信内容を確認する限り、いずれも意図した通りに送信されているように見えます。

画像: GTMプレビューモードによる変数が取得した値の確認結果
![GTMプレビューモードによる変数が取得した値の確認結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/cbd1b4ae-a93b-99a7-1d53-4a89c5c9568a.png)

画像: GTMプレビューモードによるタグ発火内容の確認結果
![GTMプレビューモードによるタグ発火内容の確認結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/b5423b44-9634-ffe6-108c-43da70ce1fc2.png)

画像: Chrome DevToolsによるGA4への通信内容の確認結果
![Chrome DevToolsによるGA4への通信内容の確認結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/eb240e5d-7e78-cc2f-f642-dd6714a306d0.png)

## 自動変換の結果
### DebugViewによる確認結果
DebugViewで受信した結果を確認すると、「`0001234E-05`」で送信した筈のカスタムディメンションの値が何故か「0.01234」に化けてGA4に記録されてしまいました。これは値がGA4内部でE表記の指数の数値（ $1234×10^{-5}$ ）として扱われて自動変換が行われたためです。

画像: DebugView : GA4 ウェブストリームのカスタムディメンションに送信した値「0001234E-05」が「0.01234」に自動変換された
![DebugView : GA4 ウェブストリームのカスタムディメンションに送信した値「0001234E-05」が「0.01234」に自動変換された](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/8f6c60cc-17bc-e68f-bfce-20576773942a.png)

### レポート上での確認結果
DebugViewはあくまで簡易表示であり、「99.99999」が「100」に丸められて表示されるなど実際に格納される値とやや異なる値が表示される場合もあるためレポート上でも確認します。しかし残念なことにこちらでも変換済みの値が格納されています。

画像 : 探索レポートでも自動変換された値が保存されている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/069bd258-8a0a-06e7-b7bd-10818010b463.png)

執筆時点で自動変換そのものを無効化する方法はありませんが、変換が生じうるパターンを把握すれば事前対応が可能です。

## GA4によるカスタムディメンション値の自動変換の例
これらのパターンに該当する値を文字列として拾う可能性がある変数設定はタグ設定側で事前に対策を行うことにより自動変換を防ぐことができます。

|送信した文字列|レポートに保存された値|変換の発生|メモ|
|:-----------|:-----------|:-------:|:-----------|
|`00123`|`123`|○|上位桁の0が消えた|
|`.8`|`0.8`|○|小数として扱われたため、0が増えた|
|`99.99999999999999`|`99.999999999999986`|○|下位桁の数が丸められた|
|`99.9999999999999999`|`100`|○|下位桁の数が丸められて繰り上がりが発生した|
|`+100`|`100`|○|正の数として扱われたため、プラス記号が省略された|
|`0x11`|`17`|○|[16進数](https://e-words.jp/w/0x.html)として扱われて10進数に変換された|
|`0x12af`|`4783`|○|[16進数](https://e-words.jp/w/0x.html)として扱われて10進数に変換された|
|`0o11`|`0o11`|なし|8進数としては扱われない|
|`0b11`|`0b11`|なし|2進数としては扱われない|
|`1234E5`|`123400000`|○|指数( 1234E+5 )として扱われた|
|`001234E+5`|`123400000`|○|指数( 1234E+5 )として扱われた|
|`0001234E-05`|`0.01234`|○|指数( 1234E-5 )として扱われた|
|`9223372036854775808`|`9.2233720368547758e+18`|○|int64の最大値を超える数値文字列。指数表記になった上で下位桁の数値が丸められた|
|`9223372036854775807`|`9223372036854775807`|なし|int64の最大値 ( $2^{63}-1$ )以下の長い19桁の正の数値文字列|
|`-9223372036854775808`|`-9223372036854775808`|なし|int64の最小値 ( $-2^{63}$ )以上の長い19桁の負の数値文字列|
|`-9223372036854775809`|`-9.2233720368547758e+18`|○|int64の最小値を超える数値文字列。指数表記になった上で下位桁の数値が丸められた|

## GA4カスタムディメンションの自動変換対策
数値と解釈されうる値を送信した場合に自動変換が起きるので、数値と解釈できない値を常にカスタムディメンションに送信するようにします。
### GTMでの対策例
以下のスクリーンショットは対策前の設定状態です。

画像 : 対策前のGA4タグ設定
![対策前のGA4タグ設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/0712023c-5c14-bc24-81e4-da9cc9e9926d.png)

変数設定「dl – item_id」が取得する文字列の値が数値として自動変換される可能性がある値である場合、カスタムディメンションitem_idの値の前に常にアンダースコアが付くようにすることで数値として解釈不能な文字列が常に送信されるように設定します。

画像 : 対策後の設定カスタムディメンション値の先頭にアンダースコア記号を付与
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/0721e857-b5b5-154b-374c-397199cacfe0.png)

上記の設定方法は非常にシンプルですが変数が値を取得できなかったときであってもアンダースコア記号1つのみの値をカスタムディメンションに送信してしまいます。

**変数設定「dl – item_id」が取得する文字列が「0001234E-05」の場合…**
- 対策前に保存される値 : `0.01234` （自動変換された結果）
- 対策後に保存される値 : `_0001234E-05` （記号の付与により自動変換を回避）

**変数設定「dl – item_id」が値を取得できなかった場合…**
- 対策前に保存される値 : （カスタムディメンション送信自体が行われない）
- 対策後に保存される値 : `_` （アンダースコア記号のみの値が送信される）

この動作に問題がある場合はカスタムJavaScript変数を作成して、値が取得できたときだけ先頭にアンダースコアが付与されるように設定します。

画像 : GA4による自動変換を防止する変数設定の例
![GA4による自動変換を防止する変数設定の例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/5214b240-01bd-16cc-3e39-55321ff7a783.png)


```javascript
function(){
  var val = {{dl - item_id}};  // 数値と解釈される情報を取得する可能性がある変数を処理対象としてセット
  if(typeof val === 'undefined' || val === null){
    return val;  // 対象の値が取得できなかったときは何もしない
  }
  return '_' + val; // 対象の値が取得できたときは先頭に"_"を付け足す
}
```

![GA4による自動変換を防止するGA4タグのパラメータ値の設定例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103957/ab2aa54d-3ab5-9dfe-bdaf-31a494e29615.png)
画像 : GA4による自動変換を防止するGA4タグのパラメータ値の設定例

**変数設定「dl – item_id」が取得する文字列が「0001234E-05」の場合…**
- 対策前に保存される値 : `0.01234` （自動変換された結果）
- 対策後に保存される値 : `_0001234E-05` （記号の付与により自動変換を回避）
**変数設定「dl – item_id」が値を取得できなかった場合…**
- 対策前に保存される値 : （カスタムディメンション送信自体が行われない）
- 対策後に保存される値 : （カスタムディメンション送信自体が行われない）

アンダースコア記号以外でも数値と解釈されない文字や記号でも対策可能ですが、組み合わせ次第では思わぬ変換が生じることがあるので要検証です。
また、アプリストリームでも同じカスタムディメンションに情報を送信している場合はウェブストリーム側とデータを揃えるために同じ対応が必要になります。

## おわりに
GA4は新しいツールでまだ情報が少なく今後も小さな仕様の変更が起こりうるため、このような想定外の挙動に気づくためにタグ設定を行った後に以下の確認を行うことを強くオススメします。


- タグが指定のタイミングで呼び出されたか、どんな情報を使ったかの確認
    - [GTMプレビューモード](https://support.google.com/tagmanager/answer/6107056?hl=ja)によるタグ発火確認
- 実際に動作したタグが通信したのか、どんな通信を行ったかの確認
    - [ブラウザのDevTools](https://qiita.com/aqril_1132/items/f461a5b235a58ef8d32b)による通信内容の確認
- ツール側で通信がどのように受理されたのかの確認
    - [GA4 DebugView](https://support.google.com/analytics/answer/7201382?hl=ja)によるGA4が受信したイベントの簡易確認
    - レポートに記録された値の確認