真策堂
· アクセス解析

GTMのデータレイヤー変数がundefinedになる原因と確認手順|命名・タイミング・スコープの3層切り分けフロー

GTMのデータレイヤー変数がundefinedになる・dataLayer.pushの値が取れない原因を、命名ミス・タイミング・スコープの3層で切り分ける確認手順を解説。プレビューモードの正しい読み方、Version 1/2の違い、SPAの持ち越し問題まで当日中に原因を特定できます。

GTMのデータレイヤー変数がundefinedになる原因と確認手順|命名・タイミング・スコープの3層切り分けフロー

GTMのプレビューでVariablesタブを開いた瞬間、狙った変数がすべてundefined——この状態で数時間手が止まってしまう運用者は珍しくありません。原因の候補が多すぎて、どこから手をつければいいか分からなくなるためです。

結論から言うと、GTMのデータレイヤー変数がundefinedになる原因は、命名ミス・タイミング・スコープの3層にほぼ集約されます。この順番で確認していけば、遠回りせずに原因へたどり着けます。闇雲にタグやトリガーの設定を見直す前に、まずこの3層のどこに問題があるかを切り分けることが最短ルートです。

本記事では、Googleタグマネージャー(GTM)のプレビューモードでの読み方から、dataLayer配列とGTM内部データモデルの違い、SPA特有の持ち越し問題まで、当日中に原因を特定できる手順に絞って解説します。

この記事のポイント

  • undefinedの原因は命名ミス・タイミング・スコープの3層に整理でき、この順で確認するのが最短ルートである
  • プレビューのイベントタイムラインで「どの時点のスナップショットか」を選ばないと正しい値は読めない
  • dataLayer配列とGTM内部データモデルは別物で、一度pushした値はページ遷移まで残り続ける
  • ネストした値はドット記法(例:ecommerce.items)で参照しないとVersion設定次第でundefinedになる
  • マーケ側で直せる原因と開発者に依頼すべき原因を切り分け、依頼文まで用意しておくと再発しにくい

深夜、undefinedの山に頭を抱える運用者

GTMのデータレイヤー変数がundefinedになる原因は何か

命名→タイミング→スコープの3層切り分けフロー 図1: 命名→タイミング→スコープの3層切り分けフロー

GTMのデータレイヤー変数がundefinedになる原因は、命名ミス・タイミング・スコープのいずれか、もしくはその組み合わせです。この3層を上から順に確認すれば、大半のケースは切り分けられます。

3層切り分けフローの全体図

第1層は命名・参照ミスです。変数名の綴りや大文字小文字、ネストしたキーの参照方法が誤っているケースで、体感として最も件数が多い原因です。第2層はタイミングです。dataLayer.pushが実行される前にタグが評価されてしまい、まだ値が存在しない状態で読み取ろうとしているケースです。第3層はスコープです。dataLayer配列とGTM内部のデータモデルの違いを理解していないために、前のページの値が残っていたり、逆に消えるはずの値が消えなかったりするケースです。

この3層は独立していません。命名は合っているのにタイミングもズレている、といった複合パターンもあります。ただし確認の優先順位としては、まず命名、次にタイミング、最後にスコープという順序が効率的です。命名ミスは静的に確認できるため一番早く潰せる一方、スコープの問題は挙動を追う必要があり時間がかかるためです。

どの層の問題かを見分ける初期症状の違い

3層のどこに原因があるかは、症状の出方でおおよそ推測できます。常にundefinedになる場合は命名ミスの可能性が高く、初回だけundefinedで2回目以降は値が取れる場合はタイミングの問題である可能性が高いです。逆に、前のページの値が消えずに残っている、あるいは複数回pushしたうちの一部だけが反映されないという場合はスコープの問題が疑われます。

まずこの初期症状の分類だけでもメモしておくと、以降の確認作業がぐっと早くなります。

最初にやる確認手順|プレビューモードでどこを見ればいいか

原因を特定する最初の一歩は、Tag Assistantのプレビューモードでイベントタイムラインを正しく読むことです。ここを誤ると、正しい設定でも「undefinedに見える」だけの誤診断をしてしまいます。

まずGTMの管理画面右上の「プレビュー」からTag Assistantを起動し、対象ページを開きます。Tag Assistantが接続できずプレビュー自体が立ち上がらない場合は、GTMプレビュー自体が接続できない場合の切り分けチェックリストを先に確認してください。本記事の手順はプレビューが開けている前提で進みます。

イベントタイムラインで「どの時点の値か」を選ぶ

Tag Assistantの画面左側には、Page View・カスタムイベント・DOM Readyなど、発生したイベントが時系列で並びます。Analytics Maniaの解説記事では、undefinedの相談の多くが「イベント選択を誤っているだけ」のケースだと指摘されています。日本の現場でも同様に、Variablesタブに表示される値はクリックして選択したイベント時点でのスナップショットである、という前提を見落として「値が取れない」と誤認するケースが目立ちます。

つまり、目的のデータがpushされるカスタムイベントより前のイベント(例えばPage View)を選んだまま変数を確認しても、undefinedと表示されるのは仕様通りです。まず該当のpushが発生したイベントを正確に選ぶことが第一歩になります。

VariablesタブとData Layerタブの読み分け

Variablesタブは、GTMで定義した「データレイヤーの変数」がそのイベント時点でどう解決されたかを一覧表示します。一方Data Layerタブは、dataLayer配列に対して行われたpush操作そのものの履歴を、生のオブジェクトの形で表示します。

変数の定義自体を疑うならVariablesタブ、pushされたデータの中身や構造を確認したいならData Layerタブ、という使い分けが基本です。Variablesタブでundefinedと出ているのにData Layerタブには値が存在する場合、原因は変数の参照設定(キー名やドット記法)にある可能性が高くなります。

タグ発火時点の値とpush時点の値は別物

見落とされがちですが、タグが発火した瞬間の変数値と、dataLayer.pushを実行した瞬間の値は同じとは限りません。タグの発火条件(トリガー)が満たされるタイミングと、目的のデータがpushされるタイミングがズレていれば、タグ発火時点ではまだ値が入っていないという状況が起こり得ます。この考え方は次の「タイミング」の層に直結します。

【第1層】命名ミス・参照ミスの確認|キー名は合っているか

キー名を指差し照合して食い違いに気づく瞬間 キー名を指差し照合して食い違いに気づく瞬間

undefinedの最頻出原因は、GTM側で設定した変数のキー名がdataLayerに実際にpushされているキー名と一致していないことです。まずここを機械的に照合します。

大文字小文字・アンダースコアの完全一致チェック

GTMのデータレイヤー変数名は完全一致で参照されます。userIduserIDitem_priceitemPriceのような表記ゆれは、人の目では見過ごしやすい典型的な失敗パターンです。Data Layerタブで実際にpushされているキー名をコピーし、GTMの変数設定画面に貼り付けて突き合わせるのが確実です。目視だけで済ませず、コピー&ペーストで照合する癖をつけると取りこぼしが減ります。

ネストした値はドット記法で参照する(ecommerce.items等)

ecommerceオブジェクトの中のitemsのように、値がネストした構造で渡されている場合、GTMの「データレイヤーの変数」ではドット記法(例:ecommerce.items)で参照する必要があります。ここをitemsだけで参照してしまい、undefinedになるケースは非常に多く見られます。

配列の中のさらに特定要素を取りたい場合はecommerce.items.0.item_nameのようにインデックスも含めて記述します。ネストが深いオブジェクトほど、どこまでの階層を書けば値が取れるのか分かりにくくなるため、Data Layerタブで実際のオブジェクト構造をツリー表示で確認しながら記述するのが安全です。

Data Layer Version 1と2の違いでundefinedになるケース

GTMの変数設定には「Data Layer Version」という項目があり、Version 1とVersion 2で挙動が異なります。Analytics Maniaの解説では、Version 2はpushされるたびにデータが再帰的にマージされる仕組みであり、この挙動差を理解していないとネストした値の参照に失敗しやすいと整理されています。日本語の解説記事はキー名の一致にばかり焦点を当てがちですが、Version設定とネスト参照の失敗を切り分けて考える視点は実務でかなり有効です。

特にecommerce計測でitemsだけがundefinedになる場合、Versionの設定とドット記法の組み合わせを両方確認してください。片方だけ直しても解決しないことがあります。

【第2層】タイミングの確認|pushより先にタグが動いていないか

命名が正しくてもundefinedになる場合、次に疑うべきはタイミングです。dataLayer.pushが実行される前にタグが評価されてしまっていないかを確認します。

dataLayer定義はGTMスニペットより上に置く

window.dataLayer = window.dataLayer || [];という初期化コードは、GTMのスニペットより先に読み込まれる必要があります。この順序が逆になっていると、GTMが読み込まれた時点でdataLayerが存在せず、初期状態の値がすべて取れなくなります。以降の値についてはdataLayer.pushで随時追記していく形が原則です。スニペット設置順は、サイト全体のテンプレートを触った直後に崩れやすい箇所なので、実装変更のたびに確認しておく価値があります。

ページビュー系トリガーで拾うのをやめてカスタムイベントで拾う

Page ViewやDOM Readyといったページビュー系トリガーで変数を拾おうとすると、目的のデータがまだpushされる前にタグが発火してしまうことがあります。この場合の解法は、データが確定したタイミングでカスタムイベントをdataLayer.pushし、そのイベント名をトリガーとして使うことです。トリガーの種類をページビュー系からカスタムイベントに変更するだけで解決するケースは実務上かなりの割合を占めます。

SPA(React/Vue)でHistory Changeより先にデータが無いケース

React/VueなどのSPAでは、URLが変わるHistory Changeイベントの発火タイミングと、画面のデータ描画が完了するタイミングが一致しないことがあります。Analytigrowの記事では、SPAにおいてHistory Changeトリガーの発火時点でまだページデータの描画が終わっておらず、pushより先にタグが走るレースコンディションが起きると指摘されています。これは日本のSPAサイトでも構造的に同じ問題が起きるため、対策の考え方はそのまま適用できます。

対策として、ページビュー系トリガーでの取得はやめ、データ確定後にコンポーネント側からカスタムイベントをpushさせ、それ自体をトリガーにする設計が推奨されています。SPAでの計測実装は開発側との連携が前提になるため、後述の依頼文テンプレートを使うと話が早く進みます。

【第3層】スコープの確認|dataLayer配列とGTMのデータモデルは別物

dataLayer配列とGTM内部データモデルの関係図 図2: dataLayer配列とGTM内部データモデルの関係図

命名もタイミングも問題がないのにundefinedになる、あるいは逆に消えるはずの値が残ってしまう場合、原因はスコープにあります。ここは最も見えにくい層です。

dataLayer配列そのものと、GTMが内部で保持しているデータモデルは別のものだという理解が出発点になります。Simo Ahava氏のブログでは、一度pushされた値はページ遷移が起きるまでGTMの内部データモデルに残り続けると解説されています。dataLayer配列に見えているものと、GTMが実際に参照しているデータの状態は完全に同期しているわけではない、という点は日本語の解説記事ではあまり触れられていません。

一度pushした値はページ遷移まで残り続ける(持ち越し問題)

SPAのようにページ遷移せずにコンテンツだけが切り替わる環境では、前のイベントでpushした値が次のイベントにも「持ち越される」ことがあります。前のイベントでitem_idが123だった場合、次のイベントでitem_idをpushし忘れると、GTMの内部データモデル上は123が残ったままになり、意図せず古い値が使われてしまいます。undefinedになるべき場面で古い値が出てくる、という逆パターンのバグはこの持ち越しが原因であることが多いです。

dataLayer = [] の代入で上書きしていないか

dataLayer.push(...)ではなくdataLayer = []のような代入でリセットを試みるコードが混入していると、GTMが参照しているオブジェクトの参照自体が切り替わり、正しく値を追跡できなくなります。データレイヤーへの操作はpushメソッドで行うのが原則で、代入によるリセットは避けるべきというのが基本的な考え方です。この記述はサイト全体のテンプレートに埋め込まれていることもあるため、疑わしい場合はソースコード全体をキーワード検索して洗い出す必要があります。

不要な値はundefinedをpushしてフラッシュする

持ち越し問題への対処として推奨されるのが、不要になった変数にundefinedを明示的にpushして値をクリアする方法です。Simo Ahava氏のブログでもこの「フラッシュ」の手法が紹介されています。次のイベントで使わないキーをそのまま放置せず、{ item_id: undefined }のように明示的にクリアしてからpushする運用にすると、意図しない値の持ち越しをかなり防げます。

プレビューでは値が取れるのに本番でundefinedになるのはなぜか

プレビューと本番で結果が分かれる判断ツリー 図3: プレビューと本番で結果が分かれる判断ツリー

プレビューでは正しく値が取れるのに本番環境だけundefinedになる場合、原因はコンテナの公開設定か、本番特有の読み込みタイミングのどちらかに絞られます。

バージョン公開とワークスペースの確認

最も基本的な確認は、修正した内容を含むワークスペースが実際に「公開」されているかどうかです。プレビューはワークスペースの内容をそのまま反映しますが、本番サイトが参照するのは最後に公開されたバージョンです。修正後に公開ボタンを押し忘れているだけ、というのは頻度の高い見落としです。公開したつもりでも実際には反映されていないケースの詳しい切り分けは、GTMで公開したのに本番に反映されない原因の4層切り分けで扱っています。

本番だけ発生するタイミング差(キャッシュ・遅延読み込み)

公開設定に問題がない場合、次に疑うのはキャッシュや読み込み順序の本番特有の差分です。CDNのキャッシュが古いバージョンのページを配信していたり、本番環境だけ画像や外部スクリプトの遅延読み込みが有効になっていてデータの確定タイミングがずれていたりすることがあります。ブラウザのキャッシュをクリアした上でChromeデベロッパーツールのNetworkタブを確認し、リソースの読み込み順序がプレビュー環境と本番環境で異なっていないかを見比べるのが有効です。

再発防止の設計ルールと開発者への依頼の仕方

依頼メモを手渡し、握手で合意する二人 依頼メモを手渡し、握手で合意する二人

undefinedの原因を特定して直した後は、同じ問題を繰り返さないための運用ルールを決めておくことが重要です。

pushはeventキーを含めて1回にまとめる

Analytics Maniaの解説では、SPAの計測において複数回に分けてpushするのではなく、コンポーネントのマウント完了後に必要なデータをeventキーを含めて1回のpushにまとめるのが安全な実装原則とされています。分割してpushすると、途中の状態でトリガーが発火してしまい、一部のデータが欠けたままタグが動くリスクが高まります。

以下のような整理を開発側と共有しておくと、実装の揺れを防ぎやすくなります。

項目避けたい実装推奨される実装
push回数必要なデータを複数回に分けてpushデータ確定後に1回でまとめてpush
イベント発火ページビュー系トリガーで拾うカスタムイベントをpushして拾う
不要な値前の値をそのまま放置undefinedをpushして明示的にクリア

開発者に渡す依頼文テンプレート(何を・いつ・どの形式でpushするか)

マーケ側で直せるのは主に第1層の命名・参照ミスと、GTM管理画面内で完結するトリガー設計の見直しまでです。dataLayer.pushの実装コード自体を書き換える必要がある場合は、開発者への依頼が必要になります。依頼文には少なくとも次の3点を含めると、やり取りの往復が減ります。

  • 何を:pushしてほしいキー名とデータ構造(ネストがあれば階層も明示)
  • いつ:どのユーザー操作・どの描画完了タイミングでpushするか
  • どの形式で:eventキーを含めた1回のpushでまとめてほしい旨、既存データを上書きしない旨

この3点を明示した依頼文があれば、実装側も迷わず対応しやすくなります。「dataLayerに値を入れてください」だけの依頼では、タイミングやpush回数の解釈が開発者によってばらつくため、可能な限り具体的に書くことをおすすめします。

よくある質問

Q:dataLayerのコードはGTMスニペットの前と後、どちらに書けばいいですか?

初期値を定義するwindow.dataLayer = window.dataLayer || [];はGTMスニペットより前に置くのが原則です。GTMの読み込みより先にdataLayerが存在していないと、初期状態の値を拾えなくなります。それ以降にユーザー操作やページ内の状態変化に応じて追加する値は、dataLayer.pushでスニペットの後からでも問題なく追記できます。

Q:dataLayer.pushしたのにGTMのタグが発火しないのはなぜですか?

変数の値が取得できることと、タグが発火することは別の問題です。dataLayer.pushにeventキーが含まれているか、そのイベント名とトリガー側で設定しているイベント名が完全に一致しているかを確認してください。変数はVariablesタブで値が見えているのにタグが動かない場合は、トリガー条件の不一致を疑います。より詳しい発火不良の切り分けはGTMでコンバージョンタグが発火しない時のデバッグ手順で解説しています。

Q:プレビューでは値が見えるのにGA4に値が送られていません。なぜですか?

タグが発火した瞬間の変数値がundefinedだと、そのパラメータごと送信対象から外れてしまう仕様があります。プレビューで確認した値がpush時点のものなのか、実際にタグが発火した時点のものなのかを区別してください。タグ発火時点の値を確認するには、Tag Assistantでタグが発火したイベントを選択した状態でVariablesタブを見る必要があります。GA4側の受信状況を合わせて確認したい場合は、GA4のDebugViewにイベントが表示されない原因と確認手順も参考にしてください。

Q:ecommerceのitemsだけがundefinedになります。何を確認すべきですか?

まずGTMの変数設定でドット記法(ecommerce.items)で参照できているかを確認します。次にData Layer Versionの設定がpushされているデータ構造と噛み合っているかを確認してください。あわせて、前のイベントのecommerceオブジェクトが持ち越されて意図しない値になっていないか、不要になった時点でクリアする運用になっているかも見直すことをおすすめします。

真策堂では、GTM・GA4を中心とした計測設計の実装確認や、広告運用の前提となるデータ計測の精度改善について相談を受けています。データレイヤー周りの切り分けで手が止まっている場合は、状況の整理からお気軽にお問い合わせください。

Related Articles
Contact

広告運用・マーケティングのご相談はこちらから
お問い合わせフォーム・公式LINEのどちらでもOK