Tutorial · BigQuery · 18 min
BigQuery GA4 Export — From Linking to First Query
Link GA4 to BigQuery, understand the events_* table schema, and run your first cohort query.
- Step 01
Link GA4 to BigQuery
Admin → BigQuery Links. Pick daily + streaming. Streaming costs basically nothing at most B2B scales and saves you a debugging headache later.
- Step 02
Understand events_*
Each row is one event.
event_paramsis a repeated record — you'llUNNESTit constantly.user_propertiesis structured the same way. - Step 03
Your first cohort query
SELECT DATE(TIMESTAMP_MICROS(event_timestamp)) AS d, COUNT(DISTINCT user_pseudo_id) AS users FROM `project.dataset.events_*` WHERE event_name = 'session_start' AND _TABLE_SUFFIX BETWEEN '20250101' AND '20250131' GROUP BY d ORDER BY d; - Step 04
Extracting an event param
SELECT event_date, (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page_location, COUNT(*) AS views FROM `project.dataset.events_*` WHERE event_name = 'page_view' GROUP BY 1, 2; - Step 05
Funnel with SQL (instead of GA4's UI)
WITH steps AS ( SELECT user_pseudo_id, MAX(IF(event_name = 'sign_up', 1, 0)) AS s1, MAX(IF(event_name = 'wallet_funded', 1, 0)) AS s2, MAX(IF(event_name = 'p2p_send_completed', 1, 0)) AS s3 FROM `project.dataset.events_*` WHERE _TABLE_SUFFIX BETWEEN '20250101' AND '20250131' GROUP BY user_pseudo_id ) SELECT SUM(s1) AS signed_up, SUM(s2) AS funded, SUM(s3) AS sent FROM steps; - Step 06
Cost control
Always filter by
_TABLE_SUFFIX— wildcard scans ofevents_*cost real money. Materialize daily aggregates into a separate table for dashboards.