😎

GA4 RAWデータをBigQueryにExportするときの100万イベント制限を突破する方法とそれによる注意点

2024/12/17に公開

GA4 RAWデータをBigQueryにExportする際の100万イベント制限を突破する方法と注意点

Google Analytics 4(GA4)は、従来のUniversal Analyticsとは異なり、BigQueryへの生ログエクスポートを標準機能として提供しています。これにより、企業はユーザー行動データをより詳細に分析し、自由なクエリでインサイトを得ることが可能です。しかし、無料版GA4にはいくつかの制約があり、その中でも「1日あたり100万イベントのエクスポート制限」は多くの分析者やエンジニアを悩ませるポイントです。本記事では、この100万イベント制限を突破するための手段と、それに伴う注意点・リスクについて整理します。

GA4からBigQueryへのエクスポートと制限

GA4のBigQuery Exportは、無料版でも利用可能な強力な機能です。とはいえ、下記のような制限があります。

  • 無料版GA4:1プロパティあたり1日100万イベントまでBigQueryにDailyエクスポート可能
  • 有料版GA4(Google Analytics 360):制限緩和や上限拡大が可能。

多くのビジネスで、イベント数は容易に100万を超えてしまいます。特に大規模なECサイトや高トラフィックメディアであれば、1日に数百万、数千万イベントが発生することは珍しくありません。この上限を超えた場合、超過分はエクスポートされず、分析可能なデータが欠けてしまいます。

100万イベント制限を超える戦略

この記事ではGA4 360にUpgrdeせずに100万イベントの制限を突破する方法を記述します。ただし注意点もあるため、GA4 RAWデータをDWH(ここでは最終Snowflakeを想定)に取得後に加工(Viewとして加工でも)できることを前提としています。

SnowflakeのGA4 RAWデータのAPIも結局はGA4→BigQueryのExportしたものをSnowflakeに取得しているので、まずはExportが正しく意図した結果になっていることが重要。

100万イベント問題が起きるとどうなるか

無料での知っている限りの対処法は以下の二つです。
最後の対処法がトライアンドエラー検証でもっとも有効的な手段と思っています。

以下のような状況になっている方を対象としています。


ここではすでに180万イベントが選択されており、すでにDaily Exportの要件を満たしていません。
この要件を満たさないとDaily Exportは7日以内に停止してしまいます。

Sub Properties(サブプロパティ)

提案する解決手段とは別にまずはSub Propertiesでの対処法に触れます。
GA4ではPropertyごとにデータを管理しており、それぞれのPropertyで同様のUSERIDを設定しておくことで、複数のProperyで同じデータを管理できます。
それぞれのPropertyからのDaily Exportが100万イベントまでなので、BigQueryへのExportの設定でイベントを取捨選択して、100万イベントに収まるようにすることで、結果的に全量のイベントを保持するやり方です。


このように複数Propertyを同一USERIDで準備する。


この画像ではどのようなイベント含めるかを指定します。イベント数が横に記載されているので、100万イベントに収まるようにします。


含めてしまうと100万イベントを超える場合のExportで除外するイベントを決めます

まとめると

  1. 同じUSERID設定のプロパティをいくつも用意する。
  2. 1イベント名が100万イベントを超えない限り、それぞれから調整してExport設定する
  3. それぞれからBigQueryにDaily Exportする

これで解決できます。

しかしこのやり方ではGA4での管理も大変ですし、BigQuery内での管理も煩雑になるのであまりお勧めしません。一つの選択肢としてはあり得る程度です。
このやり方のメリットは後述するStreamingでは叶えられないシステム側でAttribution処理されたデータをBigQueryにExportできるので、ここを重視するのであればこのサブプロパティをお勧めします。

Daily Limitを超えない限りはシステム側でAttribution処理が行われます。
これによってTraffic Sourceにorganicなのかpaidなのかが付与されたデータになります。


公式参照

ここで大事なのはルックバックウィンドウは90日間ということです。
つまりは過去90日のユーザーの流入元を見てsession_trafficを受け継いでいます

Streaming(ストリーミング)

ストリーミングはGA4のExportの選択肢のDailyの下にあるものです。


書いてある通りにBest effortです。ということは何かが実現されていないわけです。
Google側からも「もしお金をかけないのであればこの方法なら無料で全量データを保持できるよ」とのことでしたが、ではどうしてGA4 360の意義があるかというと、前述のAttribution処理の有無になります。

Attribution処理があるということはUSERIDに対してTraffic Sourceがすでに処理されて付属していますが、StreamingでデータをBigQueryにバッチ的に送り続けると、SessionごとのAttribution処理が未処理のままExportされます

そのためAttribution処理を自前でしなくてはいけません。
ここがハードルを高くしている部分です。逆にいうとこの部分を乗り越えられるということは年間x00万円~x000万円分の節約になるということです。

USERIDは会社ごとに異なりますし一様に今回のやり方が適用できるわけではないのですが、GoogleがAttributionのルールを明確に説明してくれない限りは、データと睨めっこしてAttribution処理を公式ドキュメントに添いながら独自に行います。

昔の攻略本の注意書きみたいになってしまいましたが、早速データから見ていってどのように処理するほうが良さそうかを見ていきましょう。
ここからは脱線していきます。

GA4 RAWデータは実際にどんなデータか

ここではBigQueryからSnowflakeにIngestionされ半構造化データを構造化データに変換済みとして扱います。
GA4データはEvent propertyにnestされたさまざまな情報が入っているので、ここの処理はDE(データエンジニア)もしくは詳しい人が処理したほうが良いところです。

今回の着目ポイントはTraffic Sourceの処理の違いです。
したがって細かくGA4 RAWデータには触れません。がTrrafic Sourceのところを細かく説明します。
そのため全容には触れず重要なデータにだけ今回は抽出して触れます。

traffic sourceの理解はこれですので、頭に入れておきましょう

Daily Export

Daily Exportで処理されたGA4 RAWデータを構造化するとこのようなデータになっています。

o1 pro mode先生に作成してもらったサンプルデータ
本来はもっとカラムありますが絞っています。

event_timestamp user_id os device_model event_name traffic_source_name traffic_source_medium traffic_source_campaign event_params:source event_params:medium event_params:campaign
2024-01-01T09:00:00Z user_11111 iOS 16.1.2 iPhone 14 session_start google cpc winter_sale google cpc winter_sale
2024-01-01T09:00:10Z user_11111 iOS 16.1.2 iPhone 14 page_view google cpc winter_sale null null null
2024-01-01T09:00:30Z user_11111 iOS 16.1.2 iPhone 14 scroll google cpc winter_sale null null null
2024-01-01T09:05:00Z user_22222 iOS 15.7.1 iPhone 12 session_start (direct) (none) (not set) (direct) (none) (not set)
2024-01-01T09:05:15Z user_22222 iOS 15.7.1 iPhone 12 view_item (direct) (none) (not set) null null null
2024-01-01T09:05:30Z user_22222 iOS 15.7.1 iPhone 12 add_to_cart (direct) (none) (not set) null null null
2024-01-01T09:10:00Z user_33333 Android 13.0 Galaxy S21 session_start facebook social summer_campaign facebook social summer_campaign
2024-01-01T09:10:20Z user_33333 Android 13.0 Galaxy S21 user_engagement facebook social summer_campaign null null null
2024-01-01T09:20:00Z user_44444 Android 12.0 Pixel 6 session_start twitter social jan_sale bing organic bonus_sale
2024-01-01T09:20:15Z user_44444 Android 12.0 Pixel 6 page_view twitter social jan_sale null null null
2024-01-01T09:20:30Z user_44444 Android 12.0 Pixel 6 purchase twitter social jan_sale null null null

データ量は絞っていますが、見づらい場合はスクロールしてください。
着目するところはtraffic_surceevent_params:の部分です。ユーザーごとにデータが並んでいますが、多くの分析者は、「traffic_sourceがユーザーの流入元なんだな」「これを使ってorganicなのかpaidなのかとか判別すればいいんだ」となってしまいます。

しかし、これは半分正解で半分不正解です。
もし、「最初の流入元」を判別したいのであれば間違いありません。しかし、GA4レポートにあるような「最後に触れたセッション流入元」はこの方法では取得できません。
それぞれのイベントのevent_params:に入っているsource/medium/campaignから判別していく必要があります。

Daily Exportであればこの最後に触れたセッションの情報を引き継いだデータがExportされるので、基本的に抜け漏れが少ない状態、または集計しても基本的にGA4レポート側と数字が大きく変わらない状態になっています。

ただしRAWデータの性質上、session_start以外にはこのsession_traffic情報は紐づかないので、データ処理をして各イベントがどのsession_trafficなのかを識別できるようにしたほうがベターです

そしてデータの処理が終わってSession Trafficのsource/medium/campaignを仕分けられた状態の時に、仮にorganicとpaidとsession_trafficをgroupに分けたとしましょう。
例えば以下のデータが得られるとします。

session_group unique_user_count (2024-04)
organic 34,245
paid 1,580

これは2024-04のイベントでsession_strafficをorganicとpaidでそれぞれuser_idをユニークカウントしています。

Streaming

一方でStreamingで取得したデータを先ほどと同じように集計したとしましょう。
このような結果に多くの場合がなってしまいます。

session_group unique_user_count (2024-04)
organic 26,545
paid 1,380
unassigned 8,680

このようにorganicともpaidとも振り分けられないデータが出てきます。

これは前述のルックバックウィンドウ90日がないからです。
つまりはユーザーのその日その日の時間別のデータを逐次的にBigQueryにExportしているが故にAttribution処理をせずに送っていることが原因です。
このため、ここの処理をこちら側でやらないといけません。ここにStreamingの大きな落とし穴と攻略しがいのあるポイントになるわけです。

まとめにかかる

僕の環境でもそうだと思いますが、GA4 RAWデータは膨大なデータですので、これを如何に処理するのかは効率的にやる必要があります。
検証ありきでの対症療法的な結果論で言えば、おおよそ30日間のルックバックによるAttribution処理を独自にやれば大体網羅できます。

もちろん90日間にしたほうが良いですが、Snowflake側でこの処理を行うと30日間のルックバックはMediumサイズのWHで12-15分かかります。
これを毎日行いますから、ツヨツヨ環境でない限りは30日分でいいいと思います。
つまり90日分を毎日振り返れば30分以上はかかりますので、それだけの時間を毎朝かけるにはデータの迅速性に欠けてしまいます(LookerやBIツールへの反映などに影響が出る)ので、ここはそれぞれの置かれた環境でどうするかは決めるほうがベターです。

またこれはGA4側のデータを扱う方皆さんが経験しているであろう、「いつデータ反映されているんだ」問題ですが、もちろんどれだけのイベント数かにもよりますが、Daily Exportできる範囲であれば処理が終わるのは大体9:00 AM~12:00 PMです。Streamingは大体朝の3:00 AM~8:00 AMまでには終わっています。GA4レポート側だともっと遅れるようで、場合によっては12:00 PM~3:00 PM
ごろになります。

これらの条件を鑑みてどのようにGA4 RAWデータを扱うのかを検討するのをお勧めします。
僕としてはデータ処理をこちらで行えるのであれば100万イベント制限はStreamingで対処するのがおすすめです。

Discussion