真策堂
· アクセス解析

GA4のMeasurement Protocolで送ったイベントが反映されない・セッションが(not set)になる原因と切り分け手順|api_secret・client_id・session_id

GA4のMeasurement Protocolで送ったイベントが反映されない、セッションが(not set)になる原因を、api_secret・ペイロード・client_id/session_id・24時間ルール・表示面の5層で切り分けます。/debug/mp/collectでの検証や、2026年の仕様変更もまとめました。

この記事のポイント

  • GA4のMeasurement Protocolが反映されない問題は、「204なのに出ない」と「出るが(not set)」の2症状に分けると原因層が絞れる。
  • 本番の/mp/collectは壊れたペイロードにも2xxを返すため、204は成功の証拠にならず/debug/mp/collectでの検証が必須になる。
  • セッションの参照元を引き継ぐには、client_idとsession_idの両方をブラウザ側から取得し、セッション開始から24時間以内に送る必要がある。
  • 翌日バッチで送る設計は参照元が(not set)になりやすいので、送信時刻とID保存の設計から見直すのが先決である。

サーバーやCRMからGA4へ購入・成約のイベントを送ったのに、レポートのどこにも見当たらない。あるいは件数は合っているのに、参照元もランディングページも(not set)で、広告の評価に使えない。Measurement Protocolの実装を任された担当者が最初にぶつかるのが、この2つの壁です。

GA4のMeasurement Protocol(以下MP)が反映されない原因は、1つではありません。ただ、症状を最初に2つへ分けるだけで、見るべき場所は大きく絞れます。この記事では、認証、ペイロード、ID、時間、表示面の5層に沿って、当日中に切り分けられる手順をまとめます。そのうえで、MPのイベントをGoogle広告の評価に使ってよいかという判断まで扱います。

204なのに、GA4に成約が出ない夜

Measurement Protocolのイベントが反映されないときは、まず症状を2つに分ける

症状2分類と確認する5層 図1: 症状2分類と確認する5層

MPのイベントが反映されないときは、「全く出ない」のか「出るが参照元が(not set)」なのかを最初に分けてください。前者は認証・形式の問題、後者はclient_idとsession_idの紐付けの問題であることがほとんどで、確認する層が違います。

Measurement Protocolとは、ブラウザやアプリのタグを介さず、サーバーなどからHTTPでGoogle Analytics 4(GA4)へイベントを直接送るための仕組みです。タグが動いていない環境でも計測できる反面、ブラウザが自動でやってくれていたことを、送る側が自前で埋める必要があります。

症状A:レスポンスは204なのにリアルタイムにもDebugViewにも出ない

HTTPステータスが204で返ってくるのに、リアルタイムレポートにもDebugViewにも出ない場合です。この症状では、api_secretの誤り、測定IDの取り違え、ペイロードの形式崩れが疑わしい順に並びます。後述するとおり、本番エンドポイントは壊れたデータにも2xxを返すので、204を見て安心するのが最大の落とし穴です。

症状B:イベントは出るが参照元・ランディングページが(not set)

イベント自体は届いているのに、セッションの参照元やランディングページが(not set)になる場合です。MPで送ったイベントが、元のセッションに結び付かず、単独の新しいセッションとして扱われています。見るべきはclient_id、session_id、送信タイミングの3点です。MP以外の要因も混ざる可能性があるので、ブラウザ側の問題はランディングページが(not set)になる原因と照らして見分けてください。

確認する5層:認証・ペイロード・ID・時間・表示面

層見るもの主に疑う症状
1. 認証api_secret、測定ID、エンドポイントA
2. ペイロードJSON形式、イベント名、パラメータ名A
3. IDclient_id、session_idの有無と一致B
4. 時間24時間・72時間などの期限A・B
5. 表示面engagement_time_msec、フィルタ、反映ラグA

この順で上から潰していくと、無駄な往復が減ります。

204が返っても成功ではない理由と、/debug/mp/collectで検証する方法

Measurement Protocolの本番エンドポイント(/mp/collect)は、ペイロードが壊れていても常に2xxを返す仕様です。Googleの「Validate events」にも、中身の検証は検証用エンドポイントでしかできないと書かれています。204を成功の合図と読むのは、やめたほうがいいです。

検証に使うのは、https://www.google-analytics.com/debug/mp/collect です。URLの /mp/collect を /debug/mp/collect に変えるだけで、測定IDとapi_secretのクエリはそのまま使えます。

検証用エンドポイントの使い方とENFORCE_RECOMMENDATIONS

検証用にPOSTすると、本番と違って、レスポンスのボディに validationMessages が返ります。問題がなければ空配列です。開発中は、リクエストボディに "validationBehavior": "ENFORCE_RECOMMENDATIONS" を加えるのが公式の推奨です。必須ではない推奨事項への違反も、メッセージとして拾えるようになります。

POST https://www.google-analytics.com/debug/mp/collect?measurement_id=G-XXXXXXXXXX&api_secret=YOUR_SECRET

{
  "client_id": "123456789.1700000000",
  "validationBehavior": "ENFORCE_RECOMMENDATIONS",
  "events": [{
    "name": "purchase",
    "params": {
      "session_id": "1700000000",
      "engagement_time_msec": 100,
      "transaction_id": "T-1001",
      "value": 12000,
      "currency": "JPY"
    }
  }]
}

よく出るvalidationMessages:予約済みイベント名・パラメータ名・形式エラー

実務でよく見るのは、次の3系統だと言われます。

  • 予約済みのイベント名やパラメータ名を使っている(GAが内部で使う名前は、MPからは送れません)
  • 名前の長さや文字種の違反(イベント名は英数字とアンダースコアで、先頭は英字にします)
  • JSONの型違反(valueを文字列で送る、eventsが配列になっていない、など)

メッセージの fieldPath を見れば、どのフィールドが原因かまで特定できます。

検証用に送ったイベントはレポートに残らない点に注意

ここは混乱しやすい箇所です。検証用エンドポイントに送ったイベントは、レポートにもDebugViewにも一切残りません。「検証したのに画面に出ない」は仕様どおりの挙動で、画面で確認するには、検証が通ったあとで本番エンドポイントへ送り直します。

api_secretと測定IDはどこを確認すればいい?認証まわりの切り分け

管理画面の値を1文字ずつ照合する 管理画面の値を1文字ずつ照合する

認証の確認は、api_secret・測定ID(またはfirebase_app_id)・エンドポイントの3点を、GA4管理画面の値と1文字ずつ照合するのが近道です。ここが違っていても、本番は204を返し続けます。

api_secretの発行場所と、取り消し・別ストリームのsecretを使っていないかの確認

api_secretは、GA4の管理画面で「データストリーム」から対象のストリームを開き、「Measurement Protocol API secret」で作成します。確認したいのは次の3点です。

  1. 送信先の測定IDと、secretを作ったストリームが同じか。複数ストリームがあるプロパティで、別ストリームのsecretを使うミスが起きがちです
  2. 担当者が入れ替わった際などに、secretが削除・再作成されていないか
  3. コードや環境変数に貼る段階で、大文字小文字や末尾の空白が崩れていないか

secretは大文字小文字を区別します。コピー時の改行混入も、地味ですが定番の原因です。

Webはmeasurement_id、アプリはfirebase_app_idの使い分け

Webストリームに送るならクエリは measurement_id(G-から始まる値)、アプリストリームなら firebase_app_id を使います。両者を混ぜると、データは別の場所に入るか、拒否されます。アプリではclient_idではなく app_instance_id を使う点も、あわせて確認してください。

EU向けエンドポイント(region1)の扱い

欧州のデータ所在地を指定するEU向けエンドポイント(region1.google-analytics.com)は、通常のエンドポイントとは別の入口です。社内に特別な要件がなければ通常のエンドポイントのままで足ります。ただし、他社コードの流用などでregion1が混ざっている場合は、意図したものか確認しておきましょう。

イベントは届いているのにレポートに出ないのはなぜ?表示面と時間の問題

形式が通っているのに画面に出ないときは、表示面の条件が足りていないケースがほとんどです。順に見ていきます。

engagement_time_msecを入れないとリアルタイムやエンゲージメント指標に出にくい

engagement_time_msec は、そのイベントで操作していた時間をミリ秒で示すパラメータです。MPでこれを省くと、リアルタイムレポートやエンゲージメント関連の指標に現れにくくなる傾向があります。session_idを付けたサーバーサイドのイベントでは、1以上の値(たとえば100)を入れておくのが無難です。

debug_modeを付けてDebugViewで見る

DebugViewで確認したいときは、イベントのparamsに debug_mode: 1 を入れて本番エンドポイントへ送ります。検証用エンドポイントではなく、本番で送る点を間違えないでください。それでも出ない場合は、ブラウザ側の切り分けを扱ったDebugViewにイベントが表示されない時の切り分けも参考になります。

データフィルタ・反映ラグ・timestamp_microsの72時間制限

表示面では、次の3つも見落とされがちです。

  • データフィルタ:内部トラフィックを除外するフィルタが「有効」だと、社内サーバーから送ったイベントが落ちる場合があります。送信元IPが対象に入っていないか確認します
  • 反映ラグ:標準レポートは、リアルタイムより反映が遅れます。当日のデータが埋まるまで、数時間から1日程度かかることは珍しくありません
  • timestamp_micros:過去の時刻を指定できるのは、おおむね72時間以内です。これを超えた古い時刻は受け付けられません

セッションが(not set)になる原因は?client_idとsession_idの紐付けを確認する

MPのセッションが(not set)になる主因は、session_idの欠落と、ブラウザ側と一致しないclient_idです。GA4はclient_idとsession_idの組み合わせでセッションを判定するため、どちらかが欠けたり違ったりすると、イベントは元のセッションに結び付きません。

WeltPixelのブログ「GA4 session_id on Shopify」では、client_idが合っていてもsession_idが無い、または違うと、購入が別セッションとして扱われると解説されています。外部決済や会員システムを挟む日本のECでも、同じ構造で購入の参照元が消えると考えて差し支えありません。

session_idを送らない・新しく作ると新規セッション扱いになる

session_idを付けずに送ると、MPのイベントは単独の新しいセッションになり、参照元とメディアは(not set)になります。「それらしい数値を自前で生成して付ければよい」というのも、よくある失敗です。ブラウザ側のセッションに存在しない値を作ると、これも新規セッション扱いです。取得したものをそのまま送ってください。

client_idがブラウザ側と一致しない(フォールバックIDの量産)

Cookieが読めない決済フローなどで、システムが代わりのclient_idを作って送ると、ブラウザ側のユーザーと別人のユーザーが増えていきます。WeltPixelはこのフォールバックIDが(not set)ユーザーを量産すると指摘しています。日本市場でも、決済ドメインが別になる構成は珍しくないので、注文確定の前にclient_idを自社側へ保存しておく設計が前提になります。

(not set)とUnassignedは別物:取り違えないための見分け方

Bounteousの「GA4 Attribution Issues Explained」によれば、(not set)は参照元データそのものが無い状態で、Unassignedは参照元はあるのにチャネルグループの定義に当てはまらない状態です。MP起因で典型的なのは前者です。そのため、Unassignedの対処のようにチャネルグループの定義を直しても解決しません。日本の運用では、この2つを一括りに「おかしい」と報告してしまい、設定いじりに時間を使う例が起こりがちです。

client_idとsession_idはどう取得する?3つの方法と2026年の仕様変更

client_idとsession_idの取得方法は、gtag.jsのgetコマンド、Googleタグマネージャー(GTM)の組み込み変数、Cookie値の直接読み取りの3つです。Googleは引き続きCookie以外の値を推奨しているので、基本はgetコマンドかGTM変数を選びます。

方法取得元向いている場面注意点
gtag(‘get’)gtag.jsgtag.jsを直接実装している非同期のため取得完了を待つ
GTM変数Analytics Session IdGTMで計測している2025年12月から形式を受付
Cookie値_ga・セッションCookie上の2つが使えない2026年2月から値をそのまま利用可

gtag(‘get’)で取得してフォームやAPIに渡す

gtag.jsでは gtag('get', 'G-XXXXXXXXXX', 'client_id', callback) と 'session_id' の2回呼び出して、値を受け取ります。取得したIDは、フォームの隠しフィールドやCRMの項目に入れて、サーバーへ渡します。後でバッチで送る可能性があるなら、取得時刻も一緒に保存してください。次の章で理由を説明します。

GTMのAnalytics Session Id変数を使う(2025年12月から形式を受付)

GTMには、セッションIDを返す組み込み変数があります。Googleの変更履歴では、2025年12月11日からこの変数の形式をMP側で受け付けるようになりました。この変数をフォーム項目に流し込む運用が、手間の少ない選択肢です。

Cookie値をそのまま使える(2026年2月から)がGoogleは非Cookie値を推奨

Measurement Protocol changelogによると、2026年2月17日から、_ga Cookieの値をそのままclient_idに、セッションCookieの値をそのままsession_idに使えるようになりました。以前は、Cookieを分解してから送る手順が定番でした。古い日本語記事のパース手順を今も実装していると、IDの形式がずれて紐付けに失敗する恐れがあります。実装を見直す場合は、先に検証用エンドポイントで通しておきましょう。

送るタイミングの期限は?24時間・30日・63日のルール

翌日バッチでは間に合わない 翌日バッチでは間に合わない

MPのイベントには、用途ごとに別々の時間の期限があります。Googleの「Measurement protocol use cases」に基づく整理は、次の表のとおりです(2026年時点)。

用途期限
セッションの参照元を引き継ぐセッション開始から24時間以内
User-IDの付与同じ営業日
オーディエンス(Web)最終のオンラインイベントから30日
Google広告へのエクスポート63日以内かつアトリビューション期間内

セッションの参照元を引き継ぐならセッション開始から24時間以内

参照元を元のセッションに残したいなら、セッション開始から24時間以内に送る必要があります。CRMの受注確定が、問い合わせの翌週になるBtoBでは、期限を過ぎるのは最初から確定しています。この場合、参照元を引き継ぐ設計そのものが成り立たない点を、先に理解しておくことが大切です。

オーディエンスは30日、Google広告へのエクスポートは63日

一方で、参照元が(not set)でも、オーディエンスには30日、Google広告へのエクスポートには63日以内かつアトリビューション期間内の範囲で使えます。「参照元は取れないが、成約の事実は広告側へ返せる」という使い分けが可能です。

翌日バッチ送信で参照元を残す代替設計

夜間バッチで翌日にまとめて送ると、24時間を過ぎやすくなります。代替の設計は次の2つです。

  1. 成約が確定した時点で、ほぼリアルタイムに1件ずつ送る
  2. 参照元の引き継ぎはあきらめ、広告やオーディエンス用途に割り切る。参照元は別途、サイトのBigQueryエクスポートなどで補う

後者を選ぶときは、GA4×BigQueryで生データを確認する方法で、MPイベントのsession_idが意図どおり付いているかを確かめておくと安心です。

MPで送ったイベントを広告のコンバージョンに使ってよいかの判断基準

MPで送ったイベントを広告の評価に使ってよいかは、二重計上が防げていて、キーイベントの定義が広告の目的と合っているかで決まります。使うこと自体は禁止されていません。条件が揃わないまま入札に使うと、数字がぶれます。

ブラウザ側とサーバー側の二重計上はtransaction_idで防ぐ

同じ購入をブラウザ側のタグでも、サーバーからのMPでも送ると、二重に数えます。購入には、transaction_id を必ず付け、両方で同じ値を使ってください。GA4は、同じtransaction_idの購入を重複として扱います。サーバー側とブラウザ側のどちらを正とするかは、事前に決めておきましょう。

キーイベント化してGoogle広告に取り込む前に確認すること

MPのイベントをキーイベントにして、Google広告へ取り込む前に、次の点を確認します。

  • イベントが、実際に「成約」の定義に合っているか(問い合わせ送信と受注確定を混ぜない)
  • 前章の期限を、広告側の設定の運用が満たしているか
  • 同じ成果が、他のコンバージョンアクションと重複していないか

取り込みで不具合が出たときは、GA4キーイベントをGoogle広告にインポートする時の確認に確認項目を整理しています。

オフラインコンバージョンインポート・sGTMとどちらを使うか

CRMの受注データを広告へ戻したい場合、選択肢は3つあります。

手段向いている場面
MP直送実装が軽く、GA4を計測の中心に置きたい
サーバーサイドGTMブラウザとサーバーの計測を一元管理したい
オフラインコンバージョンインポート受注までの期間が長く、クリックIDで照合したい

受注まで数週間かかるBtoBなら、オフライン側が向きやすい構図です。設計の考え方はCRMの受注データをGoogle広告に戻すオフラインCV設計で、sGTMを入れるべきかはサーバーサイドGTMを導入すべきかの判断で整理しています。

よくある質問

Q:Measurement Protocolで送ったイベントがDebugViewに出ないのはなぜ?

debug_modeパラメータが付いていないか、検証用エンドポイントに送っている可能性があります。DebugViewに出すには、paramsへ debug_mode: 1 を入れて本番の/mp/collectに送ります。検証用の/debug/mp/collectに送ったイベントは、DebugViewにもレポートにも残りません。

Q:Measurement Protocolのレスポンスが204なら送信は成功している?

成功とは限りません。本番の/mp/collectは、形式エラーがあっても2xxを返す仕様です。中身が正しいかどうかは、/debug/mp/collectで返るvalidationMessagesを見て判断します。

Q:session_idなしで送るとどうなる?

新規セッション扱いになり、参照元とメディアが(not set)になります。ただし、オーディエンスやGoogle広告へのエクスポートには使えます。参照元の分析が不要な用途なら、割り切って運用する選択もあります。

Q:user_idだけ送ればclient_idはなくてもよい?

Webストリームでは、client_idが必須です。user_idは、ログインユーザーを横断して識別するための補助的な項目と考えてください。user_idだけで、セッションや参照元は決まりません。

Q:MPイベントに地域やデバイスの情報は付く?

session_idの連携によって、元のセッションの情報を引き継げます。連携が難しい場合は、user_locationやdeviceのフィールドで、MPから直接送る方法もあります。

Q:過去の成約データをまとめてMeasurement Protocolで送れる?

制約があります。timestamp_microsで指定できる過去の時刻は72時間以内で、参照元の引き継ぎはセッション開始から24時間以内です。数週間前の成約をまとめて送ると、日付がずれたり、参照元が(not set)になったりします。

真策堂では、こうした計測の切り分けから、広告評価に使える形への設計まで、ご相談を受けています。MPの実装で原因がつかめないときや、CRMの成約データを広告に活かす設計に迷うときは、お気軽にお問い合わせください。

Related Articles
Contact

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