GA4に参照元は3つある|Data APIとBigQueryで数値がズレる理由

この記事でわかること

GA4のレポート(Data API)とBigQueryエクスポートで、同じコンバージョンの参照元が食い違うことがあります。エクスポートに3つのトラフィックソース項目があること、公式の定義文がそもそも違うこと、そして自分のプロパティで乖離を測る手順を解説します。

生成AIによる要約

目次開く閉じる

GA4のBigQueryエクスポートを使い始めると、必ず一度はぶつかる現象があります。管理画面では「直接流入」になっているコンバージョンが、BigQueryでは「有料検索」になっている。同じGA4のデータのはずなのに、どこから来たのかが食い違う。

これは不具合ではありません。エクスポートにはトラフィックソースの項目が3つあり、それぞれスコープと値の決め方が違うためです。そして、そのうちどれもレポート側の「セッションの参照元」と同じ規則にはなっていません。

この記事では、3つの項目の違いを整理したうえで、公式の定義文がどう違うのかを示し、最後に自分のプロパティで乖離を測る手順まで扱います。

前提: BigQueryエクスポートは「別システム」ではない

まず押さえておきたいのは、BigQueryエクスポートがGA4とは別の計測システムではないという点です。同じタグが集めた同じデータを、別の形で書き出したものです。

にもかかわらず数字が食い違うのは、収集の問題ではなく処理の問題です。レポートは問い合わせた時点で計算し、エクスポートは書き出す時点で確定した値をイベント1件ずつに焼き付けます。処理する仕組みが別なので、同じ入力から別の出力が出ます。

運用メモ:媒体管理画面とGA4の乖離は「別の計測システムだから」で説明できますが、レポートとBigQueryの乖離はそうではありません。同じデータから出発しているぶん、原因は定義の中にあります。

参照元は3つある

BigQueryエクスポートのイベント行には、トラフィックソースに関する項目が3つ入っています。名前が似ていますが、指しているものが違います。

3つの項目とスコープcollected_traffic_sourceイベント単位。そのイベント自身が持ってきた情報だけ。何も足さないイベントsession_traffic_source_last_clickセッション単位。直近のクリックまでさかのぼって値を決めるセッションtraffic_sourceユーザー単位。最初に獲得した参照元。以後は変わらないユーザー上から下へ、値が決まる範囲が広くなる

スコープが違うということは、そのまま入れ替えられないということです。レポート側にもスコープ別のディメンションがあるので、対応関係を押さえておくと迷いません。

BigQueryの項目スコープ値の決め方レポート側の対応物
collected_traffic_sourceイベントそのイベントが持ってきた情報のみ対応するディメンションなし
session_traffic_source_last_clickセッション直近のクリックまでさかのぼる完全に対応するものはない
traffic_sourceユーザー最初に獲得した参照元ユーザーの最初の参照元

注意したいのが真ん中の行です。セッションスコープどうしなのに、レポートの「セッションの参照元」と完全には対応しません。 粒度は同じでも、値の決め方が別だからです。

collected_traffic_source の性質も押さえておくと理解が早まります。この項目は、そのイベントが持ってきた情報だけを入れます。URLのUTMパラメータ、広告のクリックID、遷移元のドメイン。持っていなければ空のままで、前のイベントから引き継ぐこともしません。サイト内を移動して発生したイベントには、原則として何も入りません。

定義文がそもそも違う

なぜセッションスコープどうしで食い違うのか。答えは公式ドキュメントの定義文にあります。並べてみると、規則が別物であることがそのまま書かれています。

BigQuery Export スキーマは session_traffic_source_last_click をこう説明しています。

Google 広告と手動コンテキスト全体のラストクリックが関連付けられているセッションのトラフィック ソース データ

いっぽう Data API のディメンション定義では、セッションの参照元はこうです。

ウェブサイトまたはアプリでセッションを開始した参照元

片方は「直近のクリックを探しにいく」と書いてあり、もう片方は「そのセッションが始まったときの値」だと書いてあります。同じものを指す名前に見えて、別の規則です。

1件のコンバージョンがどう記録されるか

図にすると、どこで分岐しているかがはっきりします。

同じコンバージョンの、2通りの記録広告クリックセッション A離脱(数時間〜数日)直接来訪セッション BコンバージョンBigQuery広告経由レポート直接流入セッションが2つに分かれること自体は、どちらの出力でも同じ。違うのは、セッション B にどの参照元を貼るかだけ。

ここで見落としやすいのが、セッションの区切り方は食い違っていないという点です。後日の訪問を別セッションとして数えるのは、どちらの出力でも同じです。分かれるのは、その新しいセッションに何を貼るかだけです。

逆方向のズレもある

BigQueryのほうが広く拾うのだから、常にBigQueryのコンバージョン数が多くなる、とは限りません。逆方向のズレもあります。

BigQueryエクスポートは端末単位です。 ユーザーIDによる統合はレポート側の機能で、エクスポートには反映されません。つまり、スマートフォンで広告をクリックしてパソコンで購入した場合、パソコン側のデータには広告の痕跡がありません。レポートは統合して拾えますが、BigQueryでは追えません。

もうひとつ、ラストクリックの性質による取りこぼしもあります。「直近の非ダイレクト」なので、広告をクリックしたあとに自然検索から訪れると、自然検索のほうが上書きします。 レポート側が別の規則で広告に紐づけていれば、そこでも差が出ます。

ズレの向き主な原因どちらが拾えるか
BigQueryのほうが広告が多い時間をあけた直接再訪を、直近のクリックに紐づけるBigQueryが拾い、レポートは拾わない
レポートのほうが広告が多い端末をまたぐ導線をユーザーIDで統合するレポートが拾い、BigQueryは拾えない
レポートのほうが広告が多い広告クリック後の自然検索がラストクリックを上書き規則の違いによる

どちらの出力にも死角があります。 どちらが大きいかはサイトの性質次第で、検討期間が長い商材では時間方向のズレが、複数端末での比較検討が多い商材では端末方向のズレが大きくなります。

自分のプロパティで測る手順

一般論では判断できないので、実際に測ります。コンバージョン単位で突き合わせるのが最も確実です。トランザクションIDのような一意のキーがあれば、1件ずつ照合できます。

手順1: Data APIでレポート側の値を取る

トランザクションIDとセッションの参照元・メディアを軸にレポートを取得します。

{
  "dateRanges": [{ "startDate": "2026-07-01", "endDate": "2026-07-31" }],
  "dimensions": [
    { "name": "transactionId" },
    { "name": "sessionSource" },
    { "name": "sessionMedium" },
    { "name": "sessionCampaignName" }
  ],
  "metrics": [{ "name": "transactions" }],
  "limit": 100000
}

行数が多い場合は offset を進めて全件取得します。トランザクションIDのようにカーディナリティが高いディメンションは (other) にまとめられることがあるため、返ってきた行数と rowCount を必ず突き合わせてください。

手順2: BigQueryで同じ期間を取る

エクスポート側は、購入イベントに貼られているセッションスコープの値を読みます。

SELECT
  ecommerce.transaction_id AS tid,
  LOWER(IFNULL(session_traffic_source_last_click.cross_channel_campaign.source, '(direct)')) AS src,
  LOWER(IFNULL(session_traffic_source_last_click.cross_channel_campaign.medium, '(none)')) AS med,
  session_traffic_source_last_click.cross_channel_campaign.campaign_name AS campaign
FROM `<project>.<dataset>.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260701' AND '20260731'
  AND event_name = 'purchase'
  AND ecommerce.transaction_id IS NOT NULL

同じトランザクションIDが複数行返る場合は、最初の購入イベントに絞ります。

手順3: 突き合わせて一致率を出す

トランザクションIDをキーに結合し、参照元とメディアが一致した割合を数えます。あわせて、「広告経由と判定した件数」がそれぞれいくつになるかも出しておくと、判断に直結します。

手順4: ズレた行の原因を切り分ける

一致しなかった行について、次の2つを確認すると原因が分かれます。

ひとつめは、同じ端末の過去に広告クリックがあるかです。購入セッションより前のセッションに collected_traffic_source.gclid が入っていれば、時間方向のズレです。そのセッションのキャンペーン名と、購入セッションに貼られているキャンペーン名が一致すれば、引き継ぎが起きていることまで確認できます。

WITH pur AS (
  SELECT
    ecommerce.transaction_id AS tid,
    user_pseudo_id,
    (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS sid,
    event_timestamp AS ts,
    session_traffic_source_last_click.cross_channel_campaign.campaign_name AS camp_now
  FROM `<project>.<dataset>.events_*`
  WHERE _TABLE_SUFFIX BETWEEN '20260701' AND '20260731'
    AND event_name = 'purchase'
),
clicks AS (
  SELECT
    user_pseudo_id,
    event_timestamp AS ts,
    (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS sid,
    session_traffic_source_last_click.cross_channel_campaign.campaign_name AS camp_click
  FROM `<project>.<dataset>.events_*`
  WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260731'
    AND collected_traffic_source.gclid IS NOT NULL
)
SELECT
  COUNT(*) AS n,
  COUNTIF(camp_now = camp_click) AS same_campaign
FROM (
  SELECT
    p.camp_now,
    c.camp_click,
    ROW_NUMBER() OVER (PARTITION BY p.tid ORDER BY c.ts DESC) AS rn
  FROM pur p
  JOIN clicks c
    ON c.user_pseudo_id = p.user_pseudo_id
   AND c.ts <= p.ts
   AND c.sid <> p.sid
)
WHERE rn = 1

ふたつめは、同じユーザーIDの別端末に広告クリックがあるかです。user_id が一致して user_pseudo_id が違う行にクリックがあれば、端末方向のズレです。

運用メモ:traffic_source に替えれば近づくのではないか、と考えたくなりますが逆効果です。これはユーザーを最初に獲得した参照元で、レポート側の対応物はセッションの参照元ではありません。別の概念どうしを比べることになり、乖離はかえって広がります。

どちらを使うか

測ったうえで、目的に応じて選びます。近似を作ろうとしないのが要点です。

目的向いている出力理由
実績の共有・定点報告Data API誰が管理画面を開いても同じ数字が出る。説明の手間がかからない
予算配分・注力度の判断BigQueryエクスポート直接流入や分類不能に埋もれる分が減り、規則を説明できる
長期の遡及分析BigQueryエクスポートレポートはデータ保持期間の制約を受けるが、エクスポートは残る
クロスデバイスの評価Data APIユーザーIDによる統合はエクスポートに反映されない

ひとつ補足すると、チャネル同士の比較なら、どちらを使っても結論は大きく変わりません。 時間方向の引き継ぎは広告だけでなく自然検索にも同じように効くためです。基準を変えて動くのは、各チャネルの絶対量と、「どこから来たか分からない」に残る量です。

分かっていないこと

最後に、公開情報からは確認できない点を明記しておきます。

「直接来訪のとき、レポート側が前回の参照元を引き継ぐかどうか」を明記した公式資料は見つかりません。 公開されているのは「セッションを開始した参照元」という一文だけです。日本語の解説記事には「ノーリファラー訪問では過去の参照元が引き継がれる」と説明しているものもありますが、それはコンバージョンのアトリビューションや、session_traffic_source_last_click が追加される前の状況を指している場合があります。

また、「session_traffic_source_last_click を使えばレポートと揃う」という記述も見かけますが、揃うかどうかはプロパティの性質に左右されます。 一致率は自分のデータで測ってください。この記事の手順は、そのために書いています。

関連記事

この記事をシェア

参照元

この記事をAIと深掘りする

要約・疑問の解消に。記事のタイトル・URL・参照元を入れた質問文が自動で入力されます。

ryottaman

ryottaman

広告代理店で17年、現在は事業会社でインハウスマーケティングを担当しています。

SIGNALZの記事はAIを活用して作成し、10年以上の運用型広告の実務経験をもとに内容を確認・監修しています。制作方針の詳細はサイトについてをご覧ください。

この記事について感想やご質問を送れます

誤りの指摘、補足情報、ご質問など、お気軽にどうぞ。

Google検索の優先ソースにSIGNALZを追加

追加すると、Google検索のトップニュースでSIGNALZの記事が見つけやすくなります。AIモードとAIによる概要でも「優先」バッジが付きます。設定はいつでも解除できます。

追加する