GA4の流入元別集計をAIに書かせて検算:合計が1.6万人ずれた理由

GA4 の流入元別のユーザー数と購入率を AI に SQL で出させ、公開サンプルの 2021 年 1 月分で検算しました。単位を書かない質問で合計が 16,083 人多く出た理由と、数え方をそろえる質問文の型を紹介します。

18分で読めます Data
同じ人が 2 つの流入元の箱に重複して入る左側と、1 人 1 つの箱に収まる右側を矢印で対比したイラスト
この記事は AI が下書きを補助し、運営者が内容を確認して公開しています。

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 人のユーザーの中に複数のセッション、その中に複数のイベントが入れ子になり、traffic_source はユーザー単位、event_params の medium はイベント単位、session_traffic_source_last_click はセッション単位を指すことを示した構造図

図 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 回だけ数えます。

流入元別の人数を足した合計を、実際の人数と比べると次のとおりです。

質問人数購入者
質問 1110,8731,109
質問 294,7901,069
実際94,7901,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,7900
パラメータ176,906+82,116

「差」は、実際の人数 94,790 人との差です。行ごとの合計は実際の人数の 1.17 倍、パラメータの合計は 1.87 倍になりました。

流入元別ユーザー数の合計を、実際のユーザー数 94,790 人、AI 質問 1 の行ごと 110,873 人、AI 質問 2 の 1 人 1 行 94,790 人、event_params の medium 176,906 人で比べた横棒グラフ

図 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)パラメータ
organic38,48935,46734,303
(none)25,81422,5908,950
referral18,39714,15828,495
<Other>17,43516,3676,219
(data deleted)5,5151,3181,609
cpc5,2234,8901,841

organic・(none)・referral・Other・(data deleted)・cpc の 6 つの medium について、行ごと・1 人 1 行・event_params の 3 通りで数えたユーザー数を並べた棒グラフ。行ごとは全 medium で 1 人 1 行より多い

図 3 のとおり、行ごとの数え方は、どの medium でも 1 人 1 行より多くなりました。パラメータの数え方は referral が 28,495 人と多く、(none) は 8,950 人と少ないなど、並び方そのものが違います。単位が違うので、同じ「流入元別ユーザー数」でも別の問いに答えていると考えるのが安全です。

購入率(購入ユーザー ÷ ユーザー)は、筆者が次のように計算しました。

medium行ごと(AI 質問 1)1 人 1 行(AI 質問 2)パラメータ
organic0.81%1.03%0.37%
(none)0.99%1.13%1.01%
referral1.31%1.25%2.62%
<Other>0.66%0.97%1.01%
(data deleted)2.70%4.86%1.93%
cpc0.71%1.00%0.98%

medium 別の購入率を、行ごとに数えた場合と 1 人 1 行の場合で結んだ比較図。cpc は 0.71% から 1.00%、(data deleted) は 2.70% から 4.86% に変わる

図 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,8720
2 種類8,8338,833
3 種類2,1734,346
4 種類7512,253
5 種類154616
6 種類735
合計94,79016,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 を検算する手順

ここまでの検算を、自分のデータで試すときの手順にまとめます。

質問文を書く、AI の SQL を受け取る、使われた項目を確かめる、合計人数を突き合わせる、区分別に突き合わせる、の 5 段階を上から順に矢印でつないだフロー図。合計が多いときは質問文に戻る

  1. 質問文に、数える単位と「1 人を何回数えるか」を書きます。
  2. AI の SQL で、GROUP BY がどの行に対してかかっているかを読みます。
  3. 流入元の項目が traffic_source か event_params かを確かめます。
  4. medium 別のユーザー数を足し、全体の COUNT(DISTINCT user_pseudo_id) と比べます。
  5. 合計が合ったら、検算用の 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 レビューパックもご利用いただけます。

参考にした一次情報