Streaming GA4 into BigQuery: when raw event data is actually worth it
GA4's free BigQuery export is one of its best features and most over-hyped. Raw event-level data unlocks analysis the UI can't touch — and a maintenance surface most teams underestimate. Here's when it's worth it.
The GA4 BigQuery export gives you every raw event, unsampled, unthresholded, with every parameter — the data behind the interface rather than the interface's summary of it. It is worth turning on for almost every property, because it costs little and starts accumulating history the day you enable it. Whether it is worth querying depends on whether you have questions the GA4 interface genuinely cannot answer.
What the export actually gives you
One row per event, with nested fields for event parameters, user properties, items, device, geography, and traffic source. No sampling. No data thresholding hiding rows. No 300-name limits or cardinality collapse into an "(other)" bucket.
That last point is the one people underestimate. GA4's interface applies thresholds that withhold rows to protect user privacy, collapses high-cardinality dimensions, and samples some explorations at volume. BigQuery does none of that — you are reading what was collected.
The catch: it is not retroactive. Enabling it today gives you data from today. This is why "turn it on now, decide later" is the correct default even if you have no immediate use for it.
When BigQuery is genuinely worth it
- Joining tracking data to business data. Revenue in GA4 versus revenue in your finance system; sessions joined to CRM lead status; behaviour joined to customer lifetime value. This is the single biggest reason, and the interface cannot do it at all.
- Custom attribution. GA4 gives you its models. In BigQuery you can build your own, with your own windows and rules, over the raw touchpoint sequence.
- Escaping thresholds and sampling. If your reports show "(other)" rows or withheld data, the answers are still in BigQuery.
- Long retention. GA4's event-level retention is limited; BigQuery keeps data as long as you pay for storage.
- Auditing what was actually collected. The fastest way to answer "is this parameter really being sent?" for historical periods.
- Feeding models and machine learning — propensity scoring, LTV prediction, anything needing event-level input.
When it is not worth the effort
- You need standard reports and the interface answers your questions.
- Nobody on the team writes SQL, and nobody is going to.
- Your traffic is small enough that thresholding and sampling never bite.
- You are hoping it will fix bad tracking. It will not. BigQuery faithfully stores whatever your tags sent, including the wrong values.
That last point deserves emphasis: exporting broken data gives you broken data with better retention.
Setting it up
- Create or choose a Google Cloud project, and enable billing. The export itself has no GA4-side cost; you pay BigQuery's storage and query prices.
- In GA4: Admin → Product links → BigQuery links → Link. Choose the project, the location, and the data streams.
- Choose the export type. Daily is a complete, ordered table per day. Streaming is continuous with near-real-time availability, costs more, and produces a separate intraday table.
- Wait. The first daily export lands within about 24 hours.
Most properties want daily only. Add streaming when you have a genuine real-time need — operational alerting, live dashboards — not because faster sounds better.
The table shape, briefly
Events land in events_YYYYMMDD tables, with intraday tables when streaming is on. The fields that matter most on day one:
| Field | Contains |
|---|---|
| event_name | The event |
| event_timestamp | Microseconds since epoch |
| event_params | Repeated key/value — your parameters live here |
| user_pseudo_id | The client ID |
| user_id | Your own ID, if you send one |
| items | Repeated ecommerce items |
| traffic_source | First-touch source, not per-session |
| device, geo | Nested structs |
Parameters are a repeated field of key/value pairs, which is why almost every GA4 query starts with an UNNEST:
SELECT
event_date,
COUNT(*) AS purchases,
SUM((SELECT value.double_value FROM UNNEST(event_params)
WHERE key = 'value')) AS revenue
FROM
analytics_123456789.events_*
WHERE
_TABLE_SUFFIX BETWEEN '20260701' AND '20260731'
AND event_name = 'purchase'
GROUP BY event_date
ORDER BY event_date
Note the wildcard table with a _TABLE_SUFFIX filter — that filter is what stops you scanning every day you have ever collected.
Controlling cost
BigQuery charges for bytes scanned, and GA4 tables are wide. Three habits keep the bill trivial:
- Always filter on _TABLE_SUFFIX. Querying events_* without a date bound scans your entire history, every time.
- Select only the columns you need. SELECT * on a nested GA4 table is the most expensive thing you can casually type.
- Materialise the queries you run often into small daily summary tables, and point dashboards at those rather than at raw events.
For most properties, following those three rules keeps monthly cost in the range of a coffee.
The one thing to do today
Turn it on. Even if you have no immediate question, the export costs almost nothing while unused, and the history it accumulates cannot be recreated later. The most common regret with BigQuery is not enabling it two years earlier — the interface only keeps event-level detail for a limited window, and GA4's data retention setting is quietly deleting the rest.
FAQ
Does the GA4 BigQuery export cost money?
The export itself is free from GA4's side. You pay Google Cloud for storage and for bytes scanned by queries. With date-filtered queries and summary tables, most small and mid-sized properties spend very little.
Can I get historical data when I enable the export?
No. The export is not retroactive — it begins from the day you link it, which is the main argument for enabling it before you need it.
Do I need streaming export or is daily enough?
Daily is enough for almost everyone. Streaming costs more and is worth it only when you have a real-time operational need rather than a preference for fresher numbers.
Why do my BigQuery numbers not match the GA4 interface?
Expected, and usually explainable: the interface applies thresholding, sampling, and its own attribution modelling, while BigQuery holds raw events. BigQuery is closer to what was collected; the interface is closer to what GA4 reports.
Do I need to know SQL to use the BigQuery export?
To query it directly, yes. You can point Looker Studio at BigQuery for visual reporting, but the value of the export is mostly in questions that require SQL — if nobody will write any, enable the export for the history and revisit later.
Before exporting anything, make sure what you are collecting is correct: the free tracking audit checks GA4 presence, duplicate properties, and consent signals on any URL.
See where your tracking stands
Run the same 13-check audit referenced in this post against any URL. No signup, results in seconds.