GA4 のデータを BigQuery に出し、流入元(検索・広告・参照元など、訪問のきっかけ)別の人数を AI に SQL で出させている方向けの記事です。GA4 の流入元別集計を AI に書かせると、どの単位で数えるのかを公開サンプルで検算しました。読み終わると、AI の SQL がどの単位で数えたかを見分けて、質問文で数え方をそろえられるようになります。
この記事で分かること
- GA4 の流入元には「ユーザー」「セッション」「イベント」という単位があり、BigQuery のどの項目がどれに当たるか
- 単位を書かずに AI に頼むと、流入元別のユーザー数の合計が実際の人数より 16,083 人多く出たこと
- 数え方によって、流入元別の購入率がどれだけ変わるか
- 単位をそろえるために、AI への質問文に書くべき 3 つのこと
流入元には単位がある:ユーザー・セッション・イベント
GA4 では、データが「ユーザー > セッション > イベント」の階層で整理されています(Google アナリティクス ヘルプ: トラフィック ソース ディメンションのスコープ)。セッション(1 回の訪問のまとまり)の中に、イベント(ページを見た・購入したなど 1 つひとつの操作の記録)が入る形です。
流入元にも、この単位ごとの値があります。同じヘルプでは、ユーザーの最初の参照元(その人を最初に連れてきた流入元。後で戻ってきても変わらない)と、セッション参照元(訪問のたびに新しく決まる流入元)を区別しています。管理画面では、前者はユーザー獲得レポート、後者はトラフィック獲得レポートで見られます。
BigQuery に書き出したデータ(エクスポート)では、項目ごとに単位が違います。公式のスキーマ(BigQuery Export スキーマ)の説明を表にまとめました。
| 項目 | 単位 | 何の流入元か |
|---|---|---|
traffic_source.medium | ユーザー | 最初に獲得したメディア |
session_traffic_source_last_click | セッション | 訪問のラストクリック |
collected_traffic_source | イベント | イベントと集めた流入元 |
event_params の medium | イベント | イベントの medium |
メディアとは、オーガニック検索・有料検索・メールなどの流入の種類のことです。event_params は、イベントに付いたパラメータ(付加情報)の一覧です。
図 1 のとおり、エクスポートは 1 行が 1 イベントです。traffic_source はユーザー単位の値なのに、どの行にも付いています。1 人の中で行によって値が違うと、行ごとに集計した時に同じ人を何度も数えてしまいます。
使うデータと、AI への質問文
データは、Google が公開している GA4 のサンプル(ga4_obfuscated_sample_ecommerce)の 2021 年 1 月分です。Google Merchandise Store の 2020 年 11 月から 2021 年 1 月までのデータを、値を伏せて(難読化して)公開したものです(Google for Developers: ウェブ e コマースのサンプル データセット)。BigQuery を使える方なら、同じ結果を出せます。
筆者が実行した問い合わせでは、1 月のイベントは 1,210,147 件、ユーザーは 94,790 人、購入したユーザーは 1,069 人でした。なお、筆者がテーブルの項目の一覧(スキーマ)を確かめたところ、2021 年のテーブルには traffic_source はありますが、session_traffic_source_last_click と collected_traffic_source はありませんでした。
AI(Claude Sonnet 5.5)には、次の 2 種類の質問をしました。
質問 1(単位を書かない版)
GA4 の BigQuery エクスポート(bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*)の 2021 年 1 月分で、流入元(medium)別のユーザー数、購入したユーザー数、購入率を出す SQL を書いてください。
質問 2(単位を書いた版)
(質問 1 の文に続けて)数える単位は「ユーザー」です。1 人のユーザーは必ず 1 つの medium にだけ入れてください。そのユーザーが 1 月中に最初に記録したイベントの traffic_source.medium を、そのユーザーの流入元とします。全 medium のユーザー数を足すと、1 月のユーザー総数と一致するようにしてください。
AI が書いた SQL はどの項目で数えたか
質問 1 に対して、AI は次の SQL を返しました(筆者が実行した AI の答えの原文)。
SELECT
traffic_source.medium AS medium,
COUNT(DISTINCT user_pseudo_id) AS users,
COUNT(DISTINCT IF(event_name = 'purchase', user_pseudo_id, NULL)) AS purchasers,
SAFE_DIVIDE(
COUNT(DISTINCT IF(event_name = 'purchase', user_pseudo_id, NULL)),
COUNT(DISTINCT user_pseudo_id)
) AS purchase_rate
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20210101' AND '20210131'
GROUP BY medium
ORDER BY users DESC
項目は、ユーザー単位の traffic_source.medium です。ただし GROUP BY はイベントの行に対してかかっています。そのため、行によって medium が違う人は、複数の medium に 1 回ずつ数えられます。AI の説明は、この点に触れていませんでした。
質問 2 に対しては、ユーザーごとに 1 行にまとめる SQL が返りました。
WITH first_touch AS (
SELECT
user_pseudo_id,
ARRAY_AGG(traffic_source.medium ORDER BY event_timestamp LIMIT 1)[OFFSET(0)] AS medium,
MAX(IF(event_name = 'purchase', 1, 0)) AS purchased
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20210101' AND '20210131'
GROUP BY user_pseudo_id
)
SELECT
IFNULL(medium, '(null)') AS medium,
COUNT(*) AS users,
SUM(purchased) AS purchasers,
SAFE_DIVIDE(SUM(purchased), COUNT(*)) AS purchase_rate
FROM first_touch
GROUP BY medium
ORDER BY users DESC
ARRAY_AGG(複数の行を 1 つの配列にまとめる関数)で、ユーザーごとに時刻が一番早い行の medium だけを取り出しています。どちらの答えも使った項目は同じ traffic_source.medium で、違うのは「1 人を何回数えるか」です。質問 1 の SQL は行ごとに数えるため、1 人を複数回数えることがあります。質問 2 の SQL は、1 人を 1 月の最初の行で 1 回だけ数えます。
流入元別の人数を足した合計を、実際の人数と比べると次のとおりです。
| 質問 | 人数 | 購入者 |
|---|---|---|
| 質問 1 | 110,873 | 1,109 |
| 質問 2 | 94,790 | 1,069 |
| 実際 | 94,790 | 1,069 |
「人数」はユーザー数の合計、「購入者」は購入したユーザーの合計です(単位はどちらも人)。
検算:3 通りの SQL で流入元別の人数と購入率を比べる
筆者は、AI の 2 つの SQL に加えて、event_params の medium で数える問い合わせも実行しました。3 通りの数え方は次のとおりです。
- 行ごと(AI 質問 1):
traffic_source.mediumをイベントの行ごとに集計する - 1 人 1 行(AI 質問 2): ユーザーごとに 1 月の最初の行の
traffic_source.mediumだけ使う - パラメータ:
event_paramsのmediumで、ユーザーと medium の組を数える
流入元別ユーザー数を足した合計は、次のようになりました。
| 呼び名 | 合計 | 差 |
|---|---|---|
| 行ごと | 110,873 | +16,083 |
| 1 人 1 行 | 94,790 | 0 |
| パラメータ | 176,906 | +82,116 |
「差」は、実際の人数 94,790 人との差です。行ごとの合計は実際の人数の 1.17 倍、パラメータの合計は 1.87 倍になりました。
図 2 のとおり、合計が実際の人数と一致したのは 1 人 1 行の数え方だけでした。パラメータの数え方の合計には、medium を持たないイベントがある人の行(94,757 人)も入っています。
この行を除くと 82,149 人で、全体より 12,641 人少なくなります。ただし 82,149 人は「人と medium の組」の合計で、重複を含みます。medium のパラメータを 1 つも持たない人は 30,915 人いて、重複がその一部を埋めています。パラメータの数え方は、重複と抜けの両方が起きます。
1 月のイベントのうち medium のパラメータを持つのは 336,342 件で、筆者の計算では全体の 27.79% です。
流入元別に並べると、次のようになります(人数)。
| medium | 行ごと(AI 質問 1) | 1 人 1 行(AI 質問 2) | パラメータ |
|---|---|---|---|
| organic | 38,489 | 35,467 | 34,303 |
| (none) | 25,814 | 22,590 | 8,950 |
| referral | 18,397 | 14,158 | 28,495 |
<Other> | 17,435 | 16,367 | 6,219 |
| (data deleted) | 5,515 | 1,318 | 1,609 |
| cpc | 5,223 | 4,890 | 1,841 |
図 3 のとおり、行ごとの数え方は、どの medium でも 1 人 1 行より多くなりました。パラメータの数え方は referral が 28,495 人と多く、(none) は 8,950 人と少ないなど、並び方そのものが違います。単位が違うので、同じ「流入元別ユーザー数」でも別の問いに答えていると考えるのが安全です。
購入率(購入ユーザー ÷ ユーザー)は、筆者が次のように計算しました。
| medium | 行ごと(AI 質問 1) | 1 人 1 行(AI 質問 2) | パラメータ |
|---|---|---|---|
| organic | 0.81% | 1.03% | 0.37% |
| (none) | 0.99% | 1.13% | 1.01% |
| referral | 1.31% | 1.25% | 2.62% |
<Other> | 0.66% | 0.97% | 1.01% |
| (data deleted) | 2.70% | 4.86% | 1.93% |
| cpc | 0.71% | 1.00% | 0.98% |
図 4 のとおり、cpc(クリック課金の広告)の購入率は 0.71% と 1.00% で、0.29 ポイント違います。広告の成果を報告する場面では、この差で評価が変わりえます。
ただし、購入ユーザーの定義も数え方で違う点に注意が必要です。行ごととパラメータの数え方は「購入の行にその medium が付いていた人」を数えます。
1 人 1 行は「1 月の最初の行がその medium で、1 月中に購入した人」を数えます。そのため organic の購入ユーザーは、行ごとで 312 人、1 人 1 行で 364 人と、1 人 1 行のほうが多くなっています。
同じ人に複数の流入元が付くと、合計は何人ずれるか
筆者が実行した問い合わせで、1 人に付いた traffic_source.medium の種類を数えました。
| 1 人に付いた medium の種類 | 人数 | 余分に数えられる回数(種類 − 1) |
|---|---|---|
| 1 種類 | 82,872 | 0 |
| 2 種類 | 8,833 | 8,833 |
| 3 種類 | 2,173 | 4,346 |
| 4 種類 | 751 | 2,253 |
| 5 種類 | 154 | 616 |
| 6 種類 | 7 | 35 |
| 合計 | 94,790 | 16,083 |
2 種類以上が付いた人は 11,918 人で、全体の 12.57% です。余分に数えられる回数を足すと 16,083 になり、行ごとの合計の水増し(110,873 − 94,790 = 16,083)とぴったり一致しました。行ごとの数え方の水増しは、1 人に複数の medium が付く人の重複だけで説明できます。
medium 別に見ると、行ごとと 1 人 1 行の差は referral で +4,239 人、(data deleted) で +4,197 人でした。(data deleted) は 1,318 人が 5,515 人と、4.18 倍になっています。
ここで 1 つ引っかかる点があります。公式のスキーマは、traffic_source の値は後で別のキャンペーンを操作しても変わらない、と説明しています(BigQuery Export スキーマ)。
それなのに、このサンプルでは 1 人の中で値が一定ではありません。その理由を説明する公式のページは、今回は確認できませんでした。
AI の SQL を検算する手順
ここまでの検算を、自分のデータで試すときの手順にまとめます。
- 質問文に、数える単位と「1 人を何回数えるか」を書きます。
- AI の SQL で、
GROUP BYがどの行に対してかかっているかを読みます。 - 流入元の項目が
traffic_sourceかevent_paramsかを確かめます。 - medium 別のユーザー数を足し、全体の
COUNT(DISTINCT user_pseudo_id)と比べます。 - 合計が合ったら、検算用の SQL と medium ごとの人数を比べます。
図 5 のとおり、4 番目で合計が多ければ、質問文に単位を書き足して聞き直します。セッション単位の数え方の考え方は、AI に書かせた GA4 の SQL をセッション数・ユーザー数・購入率で検算した記事でも扱っています。
つまずきやすい点
公開サンプルは値が伏せられている
このサンプルには <Other> や NULL、空の文字などの代わりの値が入っています。公式の説明でも、難読化によってデータの内部の整合性が少し損なわれる可能性があるとされています(ウェブ e コマースのサンプル データセット)。そのため、今回の 16,083 人というずれの大きさが、自分のプロパティでも同じになるとは言えません。
合計が全体の人数と合わない時の見方
流入元別の人数を足して全体より多ければ、同じ人を複数の区分で数えています。報告に使う前に、区分別の人数の合計が全体の人数と一致するかを必ず確かめてください。少ない場合は、medium が NULL の人が抜けていないかを疑います。
「1 人 1 行」も正解とは限らない
今回の「最初の行」は、1 月の中で最初のイベントです。その人が本当に初めてサイトに来た時の流入元とは限りません。また、event_params の medium は、公式のセッション単位の項目の代わりに使ったもので、セッション参照元と同じものではありません。
セッションごとに event_params の medium を 1 つ選んで数えると、購入のあったセッションは referral 624 件、organic 349 件、(none) 62 件でした。medium を持たないセッションも 37,267 件ありました。どの単位が正しいかは、知りたい問いで決まります。
AI の答えは 1 回の結果にすぎない
今回は 1 つのモデルに、各質問を 1 回ずつ聞いただけです。同じ質問でも、別の数え方の SQL が返る可能性があります。AI に SQL をレビューさせる方法は、AI に GA4 の SQL をレビューさせるプロンプト 4 本も参考になります。
そのまま使える質問文の型
質問 2 で合計がそろった書き方を、型にしました。質問 1 の文の後ろに、次の 3 行を足します。
・数える単位は「ユーザー」です。1 人のユーザーは必ず 1 つの medium にだけ入れてください。
・そのユーザーが期間中に最初に記録したイベントの traffic_source.medium を、そのユーザーの流入元とします。
・全 medium のユーザー数を足すと、期間のユーザー総数と一致するようにしてください。
セッション単位で知りたい場合は、「セッション(user_pseudo_id と ga_session_id の組)ごとに 1 つの medium」と書き換える方法が考えられます。ただし、この書き換えは今回 AI に試していません。順番に進む指標で同じ考え方を使う例は、GA4 ファネルを AI に数えさせて検算した記事にまとめています。
まとめ
- 単位を書かずに頼むと、AI は
traffic_source.mediumを行ごとに集計し、流入元別ユーザー数の合計が 16,083 人(1.17 倍)多く出ました。 - 水増しは、1 人に複数の medium が付く 11,918 人の重複だけで説明できました。購入率も数え方で変わり、cpc は 0.71% と 1.00% でした。
- 質問文に「1 人を 1 つの medium に」「どの行を使うか」「合計を総数と一致させる」と書くと、合計が全体の人数と一致しました。
次にやること
流入元別の数字をどう見せるかの参考には、ダッシュボードの一覧で、このサイトが公開データから作ったダッシュボードの例をご覧ください。流入元別の SQL が意図した単位で数えているかを第三者の目で確かめたい場合は、BigQuery SQL レビューパックもご利用いただけます。
参考にした一次情報
- Google アナリティクス ヘルプ: トラフィック ソース ディメンションのスコープ(2026-11-11 確認。ユーザー・セッション・イベントの階層、ユーザーの最初の参照元とセッション参照元)
- Google アナリティクス ヘルプ: BigQuery Export スキーマ(2026-11-11 確認。traffic_source・collected_traffic_source・session_traffic_source_last_click・event_params)
- Google for Developers: Google アナリティクス 4 の BigQuery サンプル データセット(ウェブ e コマース)(2026-11-11 確認。期間、難読化と代わりの値)