GA4 + BigQuery: raw analytics for serious measurement
GA4 can export raw, event-level data to BigQuery for free; you pay BigQuery for storage, queries and streaming at $0.05 per GB. Standard properties cap the daily export at 1 million events. The export carries GCLID but not wBRAID or gBRAID, so plan joins to Google Ads data around those gaps.
A 47-point written audit of your Google, Meta or Shopping account, back in five business days.
Get your auditBook a callWhat this integration unlocks
- Raw, event-level GA4 data with no report sampling, since you query the events yourself
- Exact counts you control, instead of the HyperLogLog++ estimates GA4 uses for distinct counts
- Joins between GA4 events and backend or CRM revenue on a transaction or user ID
- The GCLID per event in collected_traffic_source, for matching sessions to Google Ads clicks
- Custom attribution and reconciliation queries the GA4 interface cannot run
Setup steps
- 1
Choose sandbox or a billed project
You can export GA4 to the free BigQuery sandbox, with no card needed. The sandbox has a lifetime 10 GiB storage limit, and every table, view and partition expires after 60 days. It also does not support streaming data. That is enough to test the schema, but not to keep history.
For anything you plan to rely on, enable billing on the Google Cloud project. Billed projects still get the first 10 GiB of storage and the first 1 TiB of query processing free each month, and on-demand queries are then charged per TiB scanned, at a price that varies by region. After upgrading from the sandbox, change the default table expiration, or the 60-day expiry keeps deleting your export.
- 2
Create the link in GA4 Admin
In GA4, go to Admin > Product links > BigQuery links. You need the Editor role or above on the GA4 property and OWNER access to the BigQuery project. Choose the project, pick a data location, then use Configure data streams and events to decide which streams and events to include.
Pick the export type next. Daily writes one complete table per day. Streaming writes events within minutes and has no event limit, but it is a best-effort service, it costs $0.05 per GB (Google estimates roughly 600,000 events per GB), and it excludes new-user and new-session traffic source data. Fresh daily is a GA4 360 feature. Google says data should start flowing within 24 hours of linking, and its setup guide does not describe any backfill, so treat the link date as day one.
- 3
Stay under the 1 million daily event cap
Standard (non-360) properties have a limit of 1 million events per day for the daily export. Streaming has no limit. If a property consistently exceeds the cap, Google pauses the daily export, and previous days are not reprocessed. Property editors are emailed when the property approaches or exceeds the limit.
The fix Google gives is data filtering: exclude whole data streams, or exclude specific events, from the export. For PPC work, the events that matter are the key events and the ones that carry revenue. High-volume diagnostic events such as scrolls are usually the first to cut.
- 4
Learn what the export leaves out
The export holds raw event and user-level data, without the additions GA4 makes for its own reports. Two gaps matter for paid search. wBRAID and gBRAID are not included, so clicks that carry those parameters instead of a GCLID cannot be joined to Google Ads clicks from the export alone. And streaming tables exclude new-user and new-session traffic source data; Google notes user attribution data needs about 24 hours of full processing.
The GCLID is exported in collected_traffic_source. Google suggests using it with the Google Ads API or the BigQuery Data Transfer Service to fill in missing Google Ads campaign dimensions. Cookieless pings from consent mode do appear in the export, so your event counts include them.
- 5
Query the event schema and reconcile
GA4 writes one row per event, with event parameters and user properties stored as nested, repeated fields that you UNNEST in SQL. Limit queries to the dates you need and select only the columns you need, because on-demand pricing charges for the data processed in the columns you select.
Then build the reconciliation: purchases and revenue by campaign from the export, compared against what Google Ads reports and what the backend recorded. Save these as scheduled queries so the comparison runs without anyone remembering to run it.
Common issues
Fix. On a standard property this is usually the 1 million events per day cap. Google pauses the daily export when a property consistently exceeds it and does not reprocess missed days. Add stream or event exclusions in the BigQuery link settings, or switch to streaming, which has no event limit but costs $0.05 per GB.
Fix. The project is in the BigQuery sandbox, where every table and partition expires after 60 days. Enable billing, then update the dataset's default table expiration so new tables are kept.
Fix. The export does not include wBRAID or gBRAID, only the GCLID. Clicks measured through those parameters cannot be joined to Google Ads click data from the export, so expect a gap when reconciling iOS traffic.
Fix. GA4 reports use aggregate tables and estimate distinct counts such as users with HyperLogLog++, and any report or exploration that exceeds the quota (10 million events on standard properties) is sampled. The export is raw, so exact counts differ. Small gaps are expected.
Fix. Streaming excludes new-user and new-session traffic source data, and user attribution data needs about 24 hours of processing. Use the daily tables for attribution work, or wait for processing before reading source fields.
Common questions
Want this checked on your own account?
A 47-point written audit of your Google, Meta, or Shopping account. Five business days, no sales call.

