GA4の購入とカゴ落ちをBigQueryで数え直す|カートを飛ばす購入者と重複ID

GA4のカゴ落ちをBigQueryで数えると、順番を問うか、人かセッションかで数字が変わります。公開サンプルの2021年1月では購入者の2割に同じ月のカート追加が無く、transaction_idの(not set)と重複もありました。

この記事をシェア:
目次 クリックで開く

この記事の要点

  1. GA4 の BigQuery エクスポートで add_to_cart → begin_checkout → purchase を数えると、順番を問うか、人で数えるかセッションで数えるかで、別の数字になります。Google の公開サンプルの2021年1月では、カートに入れた 3,832人のうち順番どおり購入まで進んだのは 848人(22.1%)、セッション単位では 18.3% でした。
  2. このサンプルの1月では、購入した 1,069人の 20.5%(219人)に、同じ月のカート追加の記録がありませんでした。順番を守ると購入が 848人に減る分は、ほとんどがこの「カートの段を飛ばした人」です。画面の購入経路レポートは既定ではクローズドで、こうした人は数えられません。スイッチでオープンにすると、カート追加が無くても購入まで数えます。
  3. 購入の件数と売上は、さらに transaction_id で変わります。このサンプルの1月では、purchase の 24.9% が ‘(not set)’ で売上は 0、同じ ID が2行ある購入が 10個あり、うち 9個は同じ人が 9〜762秒あけて同じ売上で送った形でした。

同じ1月の「購入」を、4つの数え方で数えた数

4本目だけ単位がセッション。1,069人と850人の差の 219人が、カートの段を飛ばして購入した人

順番を問わない(purchase が1回以上)1,069人
カート追加と購入手続きもある(順番は問わない)850人
順番どおり(カート追加→購入手続き→購入)848人
同じセッションの中で順番どおり830セッション

出典:当社の照会(Google の公開サンプル、2021年1月分)

Google が公開している GA4 のサンプルデータの2021年1月分で、カートに入れた人のうち何人が購入まで進んだかを BigQuery で数えたところ、購入した人の5人に1人には、同じ月にカートに入れた記録がありませんでした。カート追加から順番どおりに追う数え方にすると、その人たちは購入から消え、購入した人は 1,069人から 848人になります。カゴ落ちの割合は、どの段を分母にし、段を飛ばした人をどう扱うかを決めないと、1つに決まりません。

当社は、GA4 の計測の設計と、BigQuery を使ったデータの集計基盤づくりを支援している会社です。この記事では、当社の検証用の Google Cloud プロジェクトから 2026年10月15日にこのサンプルを照会した結果を、4つの数え方(順番を問わない、段を飛ばした人を分ける、順番を守る、セッションで数える)と、transaction_id による件数・売上の数え直しの順に載せます。扱うのは add_to_cart・begin_checkout・purchase の3段だけです。GA4 の画面は開いておらず、画面との違いはアナリティクス ヘルプの定義から言える範囲で書きます。エクスポートのリンクの作り方とセッションの数え方の基本はGA4×BigQuery 連携の記事に、1本の照会が読む量の仕組みはエクスポートの処理量の記事に書いています。

試したデータ:公開サンプルの2021年1月、3つのイベント

使ったのは bigquery-public-data.ga4_obfuscated_sample_ecommerce です。Google のグッズの通販サイト(Google Merchandise Store)の GA4 のエクスポートを難読化したもので、2020年11月1日から2021年1月31日までの3か月分が入っています。公式の説明には、一部の値がプレースホルダーに置き換えられていること、難読化のためデータの内部の整合性が若干限られる可能性があること、Google Merchandise Store のデモアカウントのデータとは異なるので比較できないことが書かれています(Google アナリティクス 4 e コマースウェブ実装向けの BigQuery サンプル データセット)。この記事の割合と人数は、どれもこのサンプルの1月の値で、EC サイト一般の水準ではありません。

期間は _TABLE_SUFFIX BETWEEN '20210101' AND '20210131' で1月に絞り、順番は event_timestamp(イベントを受け取った時刻、UTC のマイクロ秒)で比べ、人は user_pseudo_id(仮名の ID)で数えました([GA4]BigQuery Export スキーマ)。1月の各イベントの件数と、起こした人数は次のとおりです。

公開サンプルの2021年1月のイベント(抜粋)
イベント件数起こした人数
view_item(商品を表示)86,97119,629
add_to_cart(カートに追加)15,5223,832
begin_checkout(購入手続きの開始)11,0341,924
add_shipping_info(配送情報の追加)3,9521,924
add_payment_info(支払い情報の追加)2,8411,395
purchase(購入)1,2041,069

数え方1:順番を問わず、段ごとの人数を数える

いちばん単純なのは、その月に各イベントを1回以上起こした人を、段ごとに数える方法です。このサンプルの1月では、カートに追加が 3,832人、購入手続きの開始が 1,924人、購入が 1,069人でした。

数え方1:その月に各イベントを1回以上起こした人

購入÷カート追加=27.9%。ただし分母と分子は同じ人の集まりではない

add_to_cart3,832人
begin_checkout1,924人
purchase1,069人

出典:当社の照会(Google の公開サンプル、2021年1月分)

割り算すると、購入手続き÷カート追加が 50.2%、購入÷購入手続きが 55.6%、購入÷カート追加が 27.9% です。間違えやすいのは、この 27.9% を「カートに入れた人の 27.9% が買った」と読むことです。分子の 1,069人には、その月にカートに入れていない人も入っています。

前の段も起こした人に絞ると、それが見えます。このサンプルの1月では、カート追加と購入手続きの両方がある人は 1,456人、3段とも起こした人は 850人でした。では、購入した人のうち、この 850人に入らない人は何をしていたのか。次の数え方で分けます。

数え方2:段を飛ばした人を分けて数える

850人に入らない購入者は 219人(購入者の 20.5%)で、全員、同じ月に add_to_cart が1件もありませんでした。購入手続きを始めた 1,924人でも、同じ月に 468人(24.3%)にカート追加が無く、begin_checkout の無いまま購入した人は 0人でした。飛ばされていたのは、カートの段だけです。

購入した 1,069人の内訳(2021年1月)

カート追加の無い購入者のうち、期間の前のカート追加で説明できるのは 23人

同じ月にカート追加と購入手続きがある850人
同じ月にカート追加が無い(購入手続きはある)219人
うち、11〜12月にカート追加があった23人

出典:当社の照会(Google の公開サンプル、2021年1月分)

期間の端で説明できるかも確かめました。1月に買った人が12月にカートに入れていたなら、1月だけを見ると段を飛ばしたように見えるからです。2020年11〜12月の表も読むと、219人のうち11〜12月にカート追加があったのは 23人、購入手続きの 468人では 30人で、このサンプルでは期間の前のカート追加ではほとんど説明できませんでした(この照会は表の日付だけで判定し、順番は見ていません)。

なぜカートの段を飛ばした購入があるのかは、このデータからは特定できません。難読化の影響か、元のサイトの計測の実装か、カートを通らない購入の導線があったのか、どれとも言えないためです。

画面の定義では、この人たちの扱いが設定で分かれます。ファネルデータ探索には、途中のステップから始めたユーザーも数えるオープンと、最初のステップを経たユーザー以外は無視するクローズドがあり、[ファネルをオープンにする]で切り替えます([GA4]ファネルデータ探索)。標準レポートの[収益化]にある[購入経路]は、セッションの開始・商品を表示・カートに追加・購入手続きの開始・購入の5ステップで、既定ではクローズド ファネルとして、抜かしたステップがあるユーザーを数えません。ファネルの上のスイッチでオープンに切り替えると、カートに追加が無くても、購入手続きと購入まで数えます。公式は、オープンの用途として、不完全なエクスペリエンスやデバイス間で途切れたエクスペリエンスの評価や、データ インポート・Measurement Protocol でファネルの下流のイベントを取り込んでいる場合の確認を挙げています(購入経路レポート)。定義からは、219人は既定のクローズドでは購入に入りません。オープンにすれば、購入手続きのあとに購入していれば入る側になります(購入手続きと購入の順番は、この219人については今回数えていません)。

数え方3:順番を守って数え、段を飛ばした人も同じ SQL で出す

カートに入れた人を追いかけるなら、順番を守って数えます。人ごとに最初のカート追加の時刻を取り、それより後に購入手続きがあるか、さらにその後に購入があるかを見ます。同じ SQL の中で、順番を問わない購入者と、カート追加の無い購入者も数えておくと、2つの差の中身が分かります。当社が流した SQL から、この5つの数を出す部分を抜き出して整形したものです。

WITH e AS (
  SELECT user_pseudo_id AS u, event_name AS n, event_timestamp AS t
  FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
  WHERE _TABLE_SUFFIX BETWEEN '20210101' AND '20210131'
    AND event_name IN ('add_to_cart', 'begin_checkout', 'purchase')
),
k AS (  -- 人ごとに、その月に各イベントがあったか
  SELECT u,
    COUNTIF(n = 'add_to_cart') > 0 AS has_a,
    COUNTIF(n = 'purchase') > 0 AS has_p
  FROM e GROUP BY u
),
a AS (  -- 最初のカート追加
  SELECT u, MIN(t) AS ta FROM e WHERE n = 'add_to_cart' GROUP BY u
),
b AS (  -- 最初のカート追加より後の、最初の購入手続き
  SELECT e.u, MIN(e.t) AS tb FROM e JOIN a USING (u)
  WHERE e.n = 'begin_checkout' AND e.t > a.ta GROUP BY e.u
),
p AS (  -- その購入手続きより後の購入
  SELECT e.u FROM e JOIN b USING (u)
  WHERE e.n = 'purchase' AND e.t > b.tb GROUP BY e.u
)
SELECT
  (SELECT COUNT(*) FROM a) AS add_to_cart,
  (SELECT COUNT(*) FROM b) AS begin_checkout_after_cart,
  (SELECT COUNT(*) FROM p) AS purchase_in_order,
  (SELECT COUNTIF(has_p) FROM k) AS purchase_any_order,
  (SELECT COUNTIF(has_p AND NOT has_a) FROM k) AS purchase_without_cart

このサンプルの1月では、元の SQL で出した5つの数は、順に 3,832・1,446・848・1,069・219 でした。カートに入れた人のうち購入手続きに進んだのは 37.7%(抜けたのは 62.3%)、購入手続きから購入に進んだのは 58.6%(抜けたのは 41.4%)、カート追加から購入まで進んだのは 22.1% です。

数え方3:順番どおりに進んだ人(2021年1月)

かっこ内はカートに追加した人に対する割合

カートに追加3,832人
その後に購入手続き1,446人(37.7%)
その後に購入848人(22.1%)

出典:当社の照会(Google の公開サンプル、2021年1月分)

順番を問わない購入者 1,069人と、順番どおりの 848人の差は 221人です。このうち 219人が、上の SQL の purchase_without_cart に出るカート追加の無い人で、残りの 2人は3段とも起こしたものの順番どおりではなかった人です(3段とも起こした 850人が、順番を守ると 848人)。カート追加と購入手続きの両方がある人でも、順番を守ると 1,456人が 1,446人になっただけでした。このサンプルの1月では、差の大半は逆の順番で動いた人ではなく、カートの段を飛ばした人でした。

時刻の比べ方には1つ注意があります。同じリクエストで送られた複数のイベントは同じ event_timestamp を持つことがあり([GA4]BigQuery Export スキーマ)、この SQL は同じ時刻を「後」に数えません。このサンプルの1月では、最初のカート追加と同じ時刻の購入手続きがある人は 0人でした。

この数え方は、ファネルデータ探索のクローズドで「次の間接的ステップ」(前のステップとの間に別のアクションが挟まってもよい)を選んだときに近い考え方です。ファネルデータ探索では、1人のユーザーが期間内にステップを複数回完了したときは最初の一連のステップだけがレポートされ、「次の直接的ステップ」や[以内](制限時間)も選べます(同じページ)。直接的ステップと制限時間の付いた数え方は、今回の SQL では数えていません。

数え方4:セッションで数える

同じ順番の判定を、人ではなくセッションの中で行うと、数字はまた変わります。セッションは user_pseudo_id と、event_params の ga_session_id の組で数えました(組で数える理由は連携の記事のセッションの節に書いています)。このサンプルの1月では、3つのイベント 27,760行のうち ga_session_id が無い行は 0行でした。

人単位とセッション単位(公開サンプル、2021年1月)
人単位セッション単位
add_to_cart(順番を問わない)3,8324,537
begin_checkout(順番を問わない)1,9242,159
purchase(順番を問わない)1,0691,115
カート追加→購入手続き(順番どおり)1,4461,535
→購入(順番どおり)848830
カート追加の無い purchase219282
カート追加の無い begin_checkout468616

このサンプルの1月をセッション単位にすると、購入のあった数は 1,069人から 1,115セッションに増えます。1人が複数のセッションで買えば、その分だけ増えるからです。ところが、順番どおり購入まで進んだ数は 848 から 830 に減り、カート追加から購入までの割合も、人単位の 22.1% に対してセッション単位では 18.3% です。

カート追加から順番どおり購入まで進んだ割合

分母も分子も、数える単位で変わる

人単位(848÷3,832)22.1%
セッション単位(830÷4,537)18.3%

出典:当社の照会(Google の公開サンプル、2021年1月分)

人単位の数がセッション単位より多いのは、あるセッションでカートに入れ、別のセッションで購入手続きと購入をした人が、人単位では順番どおりに数えられるからだと読めます。人ごとの内訳までは数えていません。セッションの中だけで見ると、カート追加の無い購入も 282セッションに増えました。

ファネルデータ探索のヘルプはユーザーを単位にした書き方で、ユーザーがファネルに入ったと判定されるのは1回のみとされ、セッションを単位にした数え方の記述はこのページには見当たりませんでした(同じページ)。購入経路レポートの各ステップも、そのステップのイベントをトリガーしたユーザーの数です(購入経路レポート)。画面に寄せて読むなら人単位、1回の来訪の中で買い切ったかを見るならセッション単位、と使い分けることになります。

購入の件数と売上は、transaction_id で数え直す

ここまでは人を数えていたので、購入の行が何行あっても結果は変わりません。購入の件数や売上を出すときは、ecommerce.transaction_id(e コマースのトランザクション ID)を見ます。1月の purchase 1,204行を調べると、2つのことが分かりました。

4分の1の行は ‘(not set)’ で、売上は 0

transaction_id が NULL の行は 0行でしたが、値が '(not set)' の行が 300行(24.9%)あり、その 300行は米ドルの売上(purchase_revenue_in_usd)がどれも 0 か NULL でした。売上が入っていたのは、残りの 904行です。サンプルの説明に挙がっているプレースホルダーの例は <Other>・NULL・'' などで、'(not set)' はその例にはありません。

人で見ると、このサンプルの1月に購入した 1,069人のうち 265人に '(not set)' の購入があり、250人(23.4%)は '(not set)' の購入しかありませんでした。売上の合計を購入した人数で割ると、この 250人は売上 0 のまま分母に入ります。1人あたりの売上を出すなら、'(not set)' の人を分母に入れるかどうかも決めておく項目です。

同じ ID が2行ある購入:9個は同じ人が数秒〜十数分あけて同じ売上

このサンプルの1月では、'(not set)' 以外の 904行に、transaction_id が 894種類ありました。同じ ID が2行ある購入が 10個で、3行以上のものはありません。同じ ID の行は、次のような SQL で探せます(当社が流したのは、重複の数と売上の合計を1行で出す形です)。

SELECT ecommerce.transaction_id,
  COUNT(*) AS purchase_rows,
  COUNT(DISTINCT user_pseudo_id) AS users,
  SUM(ecommerce.purchase_revenue_in_usd) AS revenue_usd
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20210101' AND '20210131'
  AND event_name = 'purchase'
  AND ecommerce.transaction_id <> '(not set)'
GROUP BY 1
HAVING COUNT(*) > 1

10個のうち 9個は、同じ user_pseudo_id の2行で、同じ日の表に入り、売上も商品の種類の数(items の要素数)も同じでした。2行目は1行目の 9秒後から 762秒(約13分)後に記録されていて、時刻まで同じものはありません。残りの1個は別の2人の行で、表の日付は1月20日と24日、記録の時刻は約4.8日離れ、売上は 113 米ドルと 74 米ドルでした。別の取引に同じ ID が付いたように見えますが、難読化の影響かどうかは分かりません。ヘルプは、異なるトランザクションで同じ ID が送られると、キーイベントが本来よりも大幅に少なくカウントされるおそれがあるとしています([GA4]トランザクション ID を使用してキーイベントの重複を抑える)。

1月の purchase 1,204行の内訳

‘(not set)’ 以外の 904行に、ID は 894種類

transaction_id が ‘(not set)’(売上 0)300行
ID が1行だけ884行
同じ ID が2行(同じ人・同じ売上)9個×2行
同じ ID が2行(別の2人)1個×2行

出典:当社の照会(Google の公開サンプル、2021年1月分)

このサンプルの1月では、売上への影響は小さく出ました。904行の売上の合計は 57,350 米ドルで、同じ人の9個の2行目を除くと 56,880 米ドル(470 米ドル、0.8% 減)、別の2人の1個も1行にして大きいほうを残すと 56,806 米ドルです。購入の件数は、行で数えれば 1,204、'(not set)' 以外の ID の種類で数えれば 894 で、どちらを「購入件数」と呼ぶかで 310 の差が出ます。売上はどれも整数の米ドル(最小 2、最大 1,200)で、これが難読化によるものかも分かりません。

同じ人の2行がなぜ残っているかも、このデータからは言えません。GA4 には、同じトランザクション ID で2つの購入が登録されても重複を除去する仕組みがあり、この除去はウェブ ストリームのデータだけで機能し、transaction_id=""(空の文字列)の購入はすべて重複として除去される、とヘルプにあります(同じページ)。ただし、このページに BigQuery のエクスポートについての記述は見当たらず、元のプロパティの画面でこの2行がどう数えられていたかも確かめていません。このサンプルのエクスポートには2行とも残っていたので、BigQuery で件数や売上を出すときは、transaction_id ごとに1行にするかを自分で決めます。

画面の数字と並べる前に、決めておくこと

BigQuery で数えた数字が画面と合わないとき、どちらかが間違っているとは限りません。Google の開発者向けブログは、Google シグナルやモデリング、アトリビューションのように、レポートの側で加わる処理の部分については、多くの用途で標準のレポートと BigQuery のエクスポートが完全に対応することは想定されていない、としています。ほかの違いの要因として、サンプリング、アクティブ ユーザーの定義、HyperLogLog++ による推定、遅れて届くデータなども挙がっています(Bridge the gap between the Google Analytics UI and BigQuery export)。一方、ファネルの数え方そのものの違いは、SQL を書く側で決められます。この記事で数字を動かした項目を並べます。

ファネルを SQL にする前に決める項目

誰を数えるか

段と単位

  • 人(user_pseudo_id)か、セッション(ga_session_id との組)か
  • 最初の段に入った人だけか(クローズド)、途中から入った人も数えるか(オープン)
  • 段を飛ばした人を、別の列で出すか

どう順番を見るか

時刻と期間

  • 前の段より後を条件にするか
  • 間に別のイベントが挟まってよいか、制限時間を付けるか
  • 期間の前に始まった人をどう扱うか

購入をどう数えるか

件数と売上

  • ‘(not set)’ の購入を件数と分母に入れるか
  • 同じ transaction_id の行を1行にするか
  • 売上は米ドルの列か、現地通貨の列か

出典:アナリティクス ヘルプ「[GA4]ファネルデータ探索」、「購入経路レポート」、当社の照会

画面のユーザー数に近づける手がかりとして、同じブログは is_active_user が true の行に絞ってから user_pseudo_id を数えることを挙げ、event_timestamp を使うならレポートのタイムゾーンに直してから画面と比べるよう書いています(同じページ)。この記事の照会では is_active_user で絞っておらず、user_id での数え直し、払い戻し(refund)の差し引き、ほかの月のファネルも数えていません。

同じ月・同じ3段でも、4つの数え方はどれも SQL としては正しい数を返すので、まず社内で使う数え方を1つ決め、画面の数字は「定義の違う別の数字」として並べることをお勧めします。

自分のエクスポートで、まず段を飛ばした人を数える

次にやることは、自社のエクスポートで、同じ月の購入者のうちカート追加の無い人が何人いるかを数えることです。数え方3の SQL の FROM を自社の analytics_<プロパティID>.events_* に、_TABLE_SUFFIX を見たい月に替えて流すと、purchase_without_cart にその人数が出ます。読む列は user_pseudo_id・event_name・event_timestamp の3つで、このサンプルの1月では 50.3 MB でした。セッションで数えるために event_params を読むと、同じ月で 277.5 MB と5倍以上になります。直近の月を数えるなら、日ごとの表にはその日に発生したイベントが最長3日後まで記録される([GA4]BigQuery Export スキーマ)ので、月が明けて数日たってから流します。

その人数が多ければ、カートを通らない購入の導線があるのか、add_to_cart が送られていない画面があるのか、購入のイベントをデータ インポートや Measurement Protocol で取り込んでいないかを、計測の実装と照らして確かめます。ファネルの数え方の取り決めを、BigQuery の中のビューや集計の表として残し、どのダッシュボードからも同じ数字が出るようにする設計は、当社のデータ分析・BI 支援で一緒に進められます。

アナリティクス ヘルプ、Google Analytics の開発者向け文書・ブログは 2026年10月15日に確かめました。GA4 の仕様は変わることがあるので、画面の項目名は最新のヘルプで確かめてください。

データ分析・データ基盤支援

Snowflake・BigQuery・Treasure Dataといったデータ基盤の選定から、基幹・SaaS・広告・POSに散らばったデータの集約、dbtでの指標統一、Lookerなどでのダッシュボード化までを支援します。

AT
aurant technologies 編集

上場企業からスタートアップまで、数多くのデータ分析基盤構築・AI導入プロジェクトを主導。単なる技術提供にとどまらず、MA/CRM(Salesforce, Hubspot, kintone, LINE)導入によるマーケティング最適化やバックオフィス業務の自動化など、常に「事業数値(売上・利益)」に直結する改善実績多数。

この記事が役に立ったらシェア:

データ基盤・データ分析の資料

「BIツール選定チェックリスト&4社比較」

データ分析・データ基盤支援の内容を見る