GA4 BigQuery連携とは?エクスポートの手順・料金とECで使うSQL例

GA4をBigQueryに出すとできること、連携の手順、毎日とストリーミング、料金と上限、サンドボックス、events_YYYYMMDDとevent_paramsの読み方、計測漏れ・重複を確かめるSQL例まで。
GA4の画面では出せない集計がある、14か月より前のデータが探索で見られない、という壁に当たったら、BigQueryへのエクスポートで解決できます。この記事では、連携の手順と料金、テーブルの構造に加え、当社がShopifyのストアで使ってきた、計測漏れや重複を確かめるSQLの例を紹介します。仕様と料金、画面は2026年10月時点のものです。
GA4をBigQueryにエクスポートすると何ができるか
GA4をBigQueryにエクスポートすると、GA4が集めたイベントを加工しないまま1行1イベントで手元に置き、SQLで自由に数えられるようになります。BigQueryは、Google Cloudの大量のデータを扱うデータベースです。GA4のヘルプによる、画面のレポートとの違いは次のとおりです。
| GA4の画面(レポート・探索) | BigQuery | |
|---|---|---|
| データの単位 | 集計した数字 | イベント単位・ユーザー単位の未加工のデータだけ |
| サンプリング | 探索で量が多いと、一部のデータから推計することがある | 無い |
| 種類の多い値の「(other)」 | 行が多いと、まとめられることがある | 無い |
| モデリングとデータドリブン アトリビューション | 入る | 入らない(参照元は、ユーザーの最初の参照元・イベントの値・セッションの最後のクリックの3種の列で入る。後述) |
| データの期間 | 探索はデータ保持期間(標準は2か月か14か月)まで | 自分で消すまで残せる |
データ保持期間が効くのは探索とファネルだけです(探索レポートの記事)。ECでは、取引IDをShopifyの注文と突き合わせる、二重の購入を探す、2回目の購入までの日数を数える、といった用途に使います。画面と同じ数字を見るだけなら、BigQueryは要りません。
GA4とBigQueryの連携手順(リンクの設定)
GA4とBigQueryの連携は、Google Cloudのプロジェクトを用意してから、GA4の「BigQuery のリンク」で設定します。後から変えにくい項目があるので、先に決めておきます。
始める前に決めること
| 決めること | 内容 | 後から変えられるか |
|---|---|---|
| Google Cloudのプロジェクト | エクスポート先。自社のGoogleアカウントで作る | リンクを作り直せば変えられる |
| 権限 | GA4のプロパティの「編集者」以上と、プロジェクトの「オーナー」 | — |
| データのロケーション | データを置く地域(米国、東京など) | 既にデータセットがあると変えられない。変えるにはリンクの削除と作り直しが要り、その間のデータが欠ける |
| 除外するデータストリームとイベント | 1日100万イベントの上限に収めるために使う | 変えられる |
ロケーションは、一緒に使う予定のデータ(広告費など)と同じ地域にそろえます。ロケーションの違うデータセットは、1つのSQLで扱うのに制限があるためです。権限はGA4の権限の記事にまとめています。
1. Google Cloudのプロジェクトを作り、BigQuery APIを有効にする
Google Cloud コンソールでプロジェクトを作るか選び、APIの一覧で「BigQuery API」を有効にします。請求先アカウントを付けなければ、無料のサンドボックスで動きます(制限は後述)。
2. GA4の「BigQuery のリンク」で設定する
- GA4の左下の「管理」を開き、「サービス間のリンク設定」の「BigQuery のリンク」を押します。一覧(プロジェクト ID、プロジェクト名、プロジェクト番号)が出るので、右上の青い「リンク」を押します。
- 「BigQuery でリンクを作成する」の画面が開きます。「リンクの設定」は「BigQuery プロジェクトを選択」「構成の設定」「確認して送信する」の3段階です。
- 「管理している BigQuery プロジェクトへのリンク」の「BigQuery プロジェクトを選択」で1のプロジェクトを選び、「確認」を押します。データのロケーションを選び、「次へ」を押します。
- 「構成の設定」では、「データ ストリームとイベントを設定」で書き出すデータストリームと除外するイベントを指定して「完了」を押し、頻度で「毎日」「ストリーミング」のどちらか、または両方を選んで「次へ」を押します(アナリティクス 360は「毎日(高頻度)」も選べます)。
- 「確認して送信する」で設定を確かめ、「送信」を押します。
リンクすると、analytics_<プロパティID> というデータセットに日ごとのテーブルが作られます。リンク前のデータを後から出す方法はヘルプに無いので、早めにリンクしておくと後で過去の分を使えます。
「毎日」と「ストリーミング」の違い
「毎日」は前日分を1日1回、「ストリーミング」は当日分を数分以内にエクスポートします。ECの分析は前日までのデータで足りることが多く、最初は「毎日」だけで足ります。
| 毎日 | ストリーミング | |
|---|---|---|
| 届くタイミング | 前日分が1日1回。ふつうはプロパティのタイムゾーンで昼過ぎ、遅れると翌日 | 当日分が数分以内 |
| できるテーブル | events_YYYYMMDD | events_intraday_YYYYMMDD(その日の毎日のテーブルができると消える) |
| 標準プロパティの上限 | 1日100万イベント | 無い |
| 追加の料金 | 無い | データ1GBあたり0.05ドル |
| 注意 | — | 欠けることがある。新規ユーザーと新規セッションの参照元は入らない。サンドボックスでは使えない |
毎日のテーブルは、遅れて届いたイベントで日付の3日後まで更新されます(20261001のテーブルなら10月4日まで)。ヘルプは、Measurement Protocolで遅れて届いたイベントもこの対象に挙げています。
GA4 BigQueryの料金と上限(無料枠・サンドボックス・1日100万イベント)
GA4のBigQuery連携にGA4側の料金はかからず、かかるのはBigQueryの保存とクエリ(SQLを実行してデータを読むこと)の料金です。中小規模のストアなら、月数ドル以内に収まることが多いと見ています。
| 料金の種類 | 無料枠(毎月) | 超えた分 |
|---|---|---|
| 保存 | 10GiB | 1GiBあたり月数セント(地域と、よく変わるデータかで変わる) |
| クエリ(オンデマンド) | 1TiB | 1TiBあたり6.25ドル(料金ページの既定の表示。地域で変わる) |
| ストリーミングのエクスポート | — | 1GBあたり0.05ドル |
GiB・TiBは、ほぼGB・TBと同じです。GA4のヘルプでは1GBはおよそ60万イベントで、1日3万イベントのストアで試算すると月約1.5GB、1年で約18GBです。無料枠を超えた分の保存料は月1ドルに届かず、ストリーミングを足しても月約0.08ドルです。
クエリの料金は選んだ列のデータ量で決まり、LIMIT では減りません。参照するテーブル1つにつき最低10MBが課金されるので、events_* で1年分を読むと約3.6GBの扱いです(無料枠には収まります)。SELECT * を避け、_TABLE_SUFFIX で期間を絞ります。
標準プロパティの1日100万イベントの上限
毎日のエクスポートは1日100万イベントまでで、超える日が続くと一時停止され、止まる前の日も出し直されません。1日のイベント数は「レポート」の「エンゲージメント」の「イベント」で分かります。100万に近いなら、使わないイベントやデータストリームを除外します。
サンドボックスで始めるときの制限
サンドボックスは、請求先アカウントを付けずに使える無料の範囲です。保存は生涯で10GiBまで(消しても戻らない)、クエリは毎月1TiBまで、テーブルは60日で自動的に消え、ストリーミングやデータを書き換えるSQL(UPDATE・DELETEなど)は使えません。GA4のテーブルも60日で消えるので、続けて使うなら請求先アカウントを付けて、テーブルの期限を外します。
エクスポートされるテーブルの構造(events_YYYYMMDDとevent_params)
GA4のBigQueryのテーブルは日ごとの events_YYYYMMDD で1行1イベント、パラメータは event_params という配列の列に入るので、UNNESTで取り出して使います。
| 列 | 中身 |
|---|---|
| event_date | イベントの日付(YYYYMMDD、プロパティのタイムゾーン) |
| event_timestamp | イベントの日時(マイクロ秒、UTC) |
| event_name | イベント名(page_view、purchase など) |
| event_params | パラメータ。キーと値の組が並んだ配列 |
| user_pseudo_id | GA4がブラウザごとに振るID(クライアントIDにあたる) |
| ecommerce | 購入の情報。transaction_id(取引ID)、purchase_revenue(購入による収益)など |
| items | 商品の配列。item_id、item_name、price、quantity、item_revenue など |
event_paramsの取り出し方
event_paramsは、1つの列に「キー」と「値」の組が何個も入った配列です(考え方はGA4のイベントの記事)。Googleのサンプル(関数にまとめた形)と同じ考え方を関数なしで書くと、次のとおりです。Googleが公開しているECサイトのサンプルで、そのまま試せます。
SELECT
event_timestamp,
(SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS ga_session_id,
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page_location
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
WHERE event_name = 'page_view'
AND _TABLE_SUFFIX BETWEEN '20201201' AND '20201207';
SQLはBigQueryのエディタに貼って実行します。実行前に、処理されるデータ量の見込みが出ます。値は型ごとに string_value(文字)、int_value(整数)、double_value(小数)に分かれます。タグとサーバーで同じパラメータを文字と数字で送り分けた場合など、どこに入るか分からないときは、COALESCE(value.string_value, CAST(value.int_value AS STRING), CAST(value.double_value AS STRING)) のようにまとめて取り出します。
_TABLE_SUFFIX には events_* の * の部分(日付)が入るので、BETWEEN で期間を絞ります(events_intraday_ のテーブルは入りません)。自社のデータでは、テーブル名を my-project.analytics_123456789.events_* の形で替えます。GA4の画面ではカスタムディメンションへの登録が要るパラメータも、BigQueryには全部入ります。
商品ごとに数えるときは、items を UNNEST します。
SELECT
item.item_name,
SUM(item.quantity) AS quantity,
SUM(item.item_revenue) AS item_revenue
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`,
UNNEST(items) AS item
WHERE event_name = 'purchase'
AND _TABLE_SUFFIX BETWEEN '20201201' AND '20201231'
GROUP BY item.item_name
ORDER BY item_revenue DESC;
items を開いた行で purchase_revenue を合計すると商品の数だけ膨らむので、商品単位では item_revenue を使います。
参照元の列は3つある
参照元の列は3つあり、間違えると、ユーザーを最初に連れてきた参照元をセッションの参照元のつもりで数えることになります。
| 列 | 意味 |
|---|---|
| traffic_source | そのユーザーを最初に連れてきた参照元。後から変わらない。当日のテーブルには入らない |
| collected_traffic_source | そのイベントと一緒に集めたUTMやgclidの値 |
| session_traffic_source_last_click | そのセッションの最後のクリックの参照元。中の cross_channel_campaign は、Google広告・手動のUTM・自然検索などすべてのチャネルを通した値で、GA4の画面のセッションの参照元に近い |
session_traffic_source_last_click は2024年の途中(cross_channel_campaign は2024年後半)から入った列で、それより前の日のテーブルには入っていません。ユーザーとセッションの単位の違いはGA4のスコープの記事で、gclidはgclidの記事で説明しています。
ECでの使い方1:Shopifyの注文と突き合わせて計測漏れを確かめる
BigQueryでGA4の取引IDを出し、Shopifyの注文と突き合わせると、GA4に入らなかった注文が注文単位で、決済方法や販売チャネルと組み合わせて分かります。原因と、探索で突き合わせる方法はShopifyでGA4の購入が計測漏れする原因と埋め方にまとめています。流れを先に図で示します。
- Shopifyの「注文管理」で、3日以上前までの期間の注文をCSVでエクスポートします。
- CSVをGoogleスプレッドシートで開き、注文番号の「Name」、合計の「Total」、決済方法の「Payment Method」、販売チャネルの「Source」の4列だけを残して、見出しを order_name、total、payment_method、source に書き換えます。キャンセルした注文の行を除き、CSVでダウンロードし直します。
- BigQueryのエクスプローラで、プロジェクトのメニューから「データセットを作成」を押し、データセットID(例:shopify)を入れます。ロケーションは
analytics_<プロパティID>と同じにします(違うとSQLがエラーで止まります)。 - そのデータセットに「テーブルを作成」し、ソースに「アップロード」を選んでCSVを読み込みます。スキーマは自動検出で構いません。
- 次のSQLの、プロジェクト名・データセット名・日付を自社のものに替えて実行します。
WITH ga4 AS (
SELECT DISTINCT
REPLACE(ecommerce.transaction_id, '#', '') AS transaction_id
FROM `my-project.analytics_123456789.events_*`
WHERE event_name = 'purchase'
AND _TABLE_SUFFIX BETWEEN '20260930' AND '20261017'
),
shopify AS (
SELECT
REPLACE(TRIM(CAST(order_name AS STRING)), '#', '') AS transaction_id,
MAX(SAFE_CAST(total AS NUMERIC)) AS total,
MAX(payment_method) AS payment_method,
MAX(source) AS source
FROM `my-project.shopify.orders_202610`
GROUP BY transaction_id
)
SELECT
s.payment_method,
s.source,
COUNT(*) AS missing_orders,
SUM(s.total) AS missing_total
FROM shopify AS s
LEFT JOIN ga4 AS g
ON s.transaction_id = g.transaction_id
WHERE g.transaction_id IS NULL
GROUP BY s.payment_method, s.source
ORDER BY missing_orders DESC;
- 期間と注文番号:Shopifyの注文が10月1日〜14日なら、GA4は前後に少し広げます。CSVで商品ごとに分かれた行は
GROUP BYでまとめ、「#」はREPLACEでそろえています - 注文IDを送っているタグ:GA4の取引IDに長い数字の注文IDが入っている場合は、CSVの「Id」列を order_name の代わりに使います。
gid://shopify/…の形なら、REGEXP_EXTRACT(ecommerce.transaction_id, r'(\d+)$')で末尾の数字だけにしてから「Id」列と突き合わせます。経路で形が違う点はShopifyのGA4の設定の記事で説明しています - 1件ずつ見る:最後の
SELECTから末尾の;までをSELECT s.* FROM shopify AS s LEFT JOIN ga4 AS g ON s.transaction_id = g.transaction_id WHERE g.transaction_id IS NULL ORDER BY s.transaction_id;に替えます
偏りがあれば、原因の見当がつきます。外部の決済サービスから完了ページに戻らない購入や、ストアのページを通らない販売チャネルの注文は、ブラウザのタグでは拾えません。決済サービスが参照元になる問題は除外する参照の記事にまとめています。
この突き合わせを毎月手で続けるのは手間です。当社のShopifyアプリ「GapFill」の計測漏れレポートは無料で、同じことを画面で見られます。当社の製品なので、その前提で読んでください。Shopifyの注文とGA4の購入をトランザクションIDで照合し、GA4に無い注文の件数と金額を、購入経路・参照元/メディア・決済方法ごとに出します。有料のプランでは、既存のタグ設定はそのままで、GA4で漏れた購入データを、サーバーサイドで補完します。
ULTROのShopifyアプリGapFill|GA4で漏れた購入データを、サーバーサイドで補完既存のタグ設定はそのまま。計測漏れレポートは無料です。GapFillを見る →ECでの使い方2:サーバーから補った購入を分けて見る
サーバーから補った購入は、識別用のパラメータを付けておけば、BigQueryでタグ経由の購入と分けて数えられます。GapFillが送った購入には、イベントパラメータ gapfill=1 が付きます。
WITH purchases AS (
SELECT
event_date,
ecommerce.purchase_revenue AS revenue,
(SELECT COALESCE(value.string_value, CAST(value.int_value AS STRING), CAST(value.double_value AS STRING))
FROM UNNEST(event_params) WHERE key = 'gapfill') AS gapfill
FROM `my-project.analytics_123456789.events_*`
WHERE event_name = 'purchase'
AND _TABLE_SUFFIX BETWEEN '20261001' AND '20261014'
)
SELECT
event_date,
IF(SAFE_CAST(gapfill AS FLOAT64) = 1, 'サーバーから補完', 'タグ') AS sent_by,
COUNT(*) AS purchases,
SUM(revenue) AS revenue
FROM purchases
GROUP BY event_date, sent_by
ORDER BY event_date, sent_by;
値の型に関わらず数値にそろえて1と比べるので、‘1’ でも ‘1.0’ でも一致し、パラメータの無い購入は「タグ」に入ります。分けて見るのは、補い始めた日を境に計測条件が変わるためです。『クッキー規制を乗り越える! 新しいデジタルマーケティングの本』も、計測条件が変わった期間をそのまま比べないことを勧めています。
ECでの使い方3:購入の重複(二重計測)を見つける
同じ取引IDのpurchaseが2行以上あれば、二重に送られている可能性があります。
SELECT
ecommerce.transaction_id AS transaction_id,
COUNT(*) AS purchase_events,
COUNT(DISTINCT user_pseudo_id) AS users,
MIN(TIMESTAMP_MICROS(event_timestamp)) AS first_at,
MAX(TIMESTAMP_MICROS(event_timestamp)) AS last_at
FROM `my-project.analytics_123456789.events_*`
WHERE event_name = 'purchase'
AND _TABLE_SUFFIX BETWEEN '20261001' AND '20261014'
AND ecommerce.transaction_id IS NOT NULL
AND ecommerce.transaction_id NOT IN ('', '(not set)')
GROUP BY transaction_id
HAVING COUNT(*) > 1
ORDER BY purchase_events DESC;
first_at と last_at(UTC)が数秒しか離れていなければ、タグの二重設置を疑います。users が2以上なら、同じ注文が別のユーザーとして送られています(自分で作ったクライアントIDでサーバーから送った、など)。
GA4のレポートは、ウェブ ストリームで同じユーザー・同じ取引IDの購入を重複として除きます。BigQueryは未加工なので2行でもレポートで2件とは限りませんが、users が2以上ならレポートでも2件の可能性が高いと見ています。直し方はGA4の購入の二重計測の記事にまとめています。
BigQueryの数字がGA4の画面と合わないとき
BigQueryとGA4の画面の数字は一致しません。GA4のヘルプは、イベント数の合計で2〜5%の差は想定内としています。それより大きいときは、次を確かめます。
| 原因 | 確かめ方 |
|---|---|
| レポート用識別子 | BigQueryはデバイスのIDだけを使う。比べるときはGA4のレポート用識別子を「デバイスベース」にする |
| タイムゾーン | BigQueryの日付はプロパティのタイムゾーン。タイムゾーンを変えた日は件数が不自然になる |
| 除外したデータストリームやイベント | リンクの設定で除外したものは入らない。GA4側も探索で同じ条件にそろえる |
| モデリングとアトリビューション | 同意しなかった人の行動の推計や、データドリブン アトリビューションはBigQueryに入らない(Cookie同意バナーの記事) |
| 遅れて届くイベント | 毎日のテーブルは日付の3日後まで更新される。直近の日は数日たってから見直す |
| SQLの列 | 参照元を traffic_source で数えていないか。セッションは user_pseudo_id と ga_session_id の組で数えているか(ユーザー数とセッションの記事) |
データが届かない・途中で止まったとき
リンク直後は届き始めるまで最大24時間かかります。それ以外で止まる主な原因は、支払いの問題(止まった期間は出し直せない)、サンドボックスの保存が10GBに達した、1日100万イベントの上限、リンクで追加されたサービス アカウントの削除や組織のポリシーです。
参考にした情報
- [GA4] BigQuery Export(Google アナリティクス ヘルプ)
- [GA4] BigQuery Export のセットアップ(Google アナリティクス ヘルプ)
- [GA4] BigQuery Export schema(Google Analytics Help)
- [GA4] Compare Analytics reports and data exported to BigQuery(Google Analytics Help)
- [GA4] Analytics data export options(Google Analytics Help)
- [GA4] データ保持(Google アナリティクス ヘルプ)
- [GA4] トランザクション ID を使用してキーイベントの重複を抑える(Google アナリティクス ヘルプ)
- Basic queries for Google Analytics event data export(Google for Developers)
- BigQuery pricing(Google Cloud)
- Enable the BigQuery sandbox(Google Cloud)
- クッキー規制を乗り越える! 新しいデジタルマーケティングの本(広瀬安彦)
よくある質問
GA4のBigQuery連携は無料ですか?
GA4側の料金はかかりません。かかるのはBigQueryの保存とクエリの料金です。BigQueryには毎月の無料枠(保存10GiB、クエリ1TiB)があり、小さなストアならその範囲に収まることも多いです。ストリーミングのエクスポートを選ぶと、データ1GBあたり0.05ドルが加わります。請求先アカウントを付けないサンドボックスでもエクスポートできますが、テーブルは60日で消え、ストリーミングは使えません。
GA4のBigQueryエクスポートに上限はありますか?
標準のGA4プロパティは、毎日のエクスポートが1日100万イベントまでです。上限を超える日が続くと毎日のエクスポートが止まり、止まった間の日は後から出し直されません。ストリーミングには上限がありません。上限を超えそうなときは、リンクの設定で分析に使わないイベントやデータストリームを除外します。
リンクする前のGA4のデータもBigQueryに出せますか?
GA4のヘルプには、リンクより前のデータを後からエクスポートする方法は書かれていません。データはリンクしてから24時間以内に届き始めます。使う予定が決まっていなくても、早めにリンクしておくと、後で過去の分を使えます。
BigQueryにデータが反映されるのはいつですか?
リンクしてから24時間以内に届き始めます。「毎日」のエクスポートは前日分が1日1回、ふつうはプロパティのタイムゾーンで昼過ぎに届き、遅れると翌日になります。「ストリーミング」なら当日のデータが数分以内に届きます。
BigQueryの数字がGA4の画面の数字と合わないのはなぜですか?
BigQueryには、GA4の画面で使われるモデリングやデータドリブン アトリビューション、レポート用識別子の処理が入らないためです。ほかに、タイムゾーンの違い、エクスポートから除外したイベント、SQLで選んだ列の違いでもずれます。GA4のヘルプは、イベント数の合計で2〜5%の差は想定内としています。
GA4のBigQueryでevent_paramsの値を取り出すには?
event_paramsは、キーと値の組が並んだ配列です。SELECTの中で (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') のように、キーを指定して取り出します。値は型ごとに string_value、int_value、double_value に分かれて入るので、パラメータに合った列を選びます。
- GA4のBigQuery連携は、加工しないイベントを1行1イベントでエクスポートする機能。サンプリングや(other)が無く、保持期間に縛られずに残せる
- リンクはGA4の「管理」>「サービス間のリンク設定」>「BigQuery のリンク」から。GA4の編集者とGoogle Cloudのプロジェクトのオーナーの権限が要り、ロケーションは後から変えにくい
- 標準プロパティの毎日のエクスポートは1日100万イベントまで。ストリーミングは上限なしで1GBあたり0.05ドル。BigQueryの無料枠は毎月保存10GiB・クエリ1TiB
- パラメータはevent_paramsにキーと値の組で入り、UNNESTで取り出す。クエリの料金は読む列と日数で決まる
- ECでは、取引IDをShopifyの注文と突き合わせて計測漏れを、取引IDごとの行数で重複を確かめられる
この記事を書いた人永田 龍史
株式会社ULTRO 代表取締役Shopify Partner。Shopifyストアの構築・保守・広告運用・CRMを一気通貫で担当。個人として運用した広告費は累計40億円超。計測設計から逆算して、利益が伸びる仕組みを作っています。Google 広告の認定資格(検索・ディスプレイ・動画・ショッピング・アプリ・P-MAX・測定)と Google アナリティクス認定資格を保有。
経歴と執筆記事112本を見る → Xでフォローする @Ryushi_ULTRO →GA4の購入、どれだけ計測漏れしていますか?
Shopifyの注文とGA4の購入を照合して、漏れた購入データをサーバーサイドで補完するアプリ「GapFill」を作りました。既存のタグ設定はそのままで、計測漏れレポートは無料です。原因と確かめ方はこちらの記事にまとめています。
自分のストアでは、どうなっているか。
無料診断では、あなたのShopifyの実データを見てサイトの健康状態を確認し、何から直すべきかを改善案とあわせてご提案します。