The GA4 interface is fine for high-level reporting. But the moment you need to answer a question like “what’s the average number of sessions before a user converts, broken down by traffic source and device type”, you’ve hit a wall. BigQuery removes that wall.
Why Connect GA4 to BigQuery?
The GA4 UI applies sampling to many reports. BigQuery gives you raw, unsampled event-level data. Every event, every user, every session — available for SQL queries.
You also get:
- Data retention beyond 14 months (GA4 limits raw data retention; BigQuery keeps it as long as you want)
- Joins with your own data — combine GA4 events with your CRM, ad spend, or revenue data
- Custom attribution modelling — build your own models rather than relying on GA4’s
- Bulk exports for Looker Studio — much faster dashboards when you’re querying BigQuery rather than GA4 directly
Prerequisites
- A Google Cloud project with billing enabled (you’ll stay within the free tier for most small-to-medium sites)
- Editor or Owner access to your GA4 property
- The BigQuery API enabled in your Cloud project
The Setup (Shorter Than You Think)
- In GA4, go to Admin → Product Links → BigQuery Links → Link
- Select your Google Cloud project
- Choose your data location (pick the region closest to you)
- Select Daily and/or Streaming export
- Click Save
That’s it. GA4 will start exporting to BigQuery within 24 hours. You’ll find your data in a dataset named after your GA4 property ID.
Understanding the Schema
Each day’s data lives in a table named events_YYYYMMDD. The core fields you’ll use constantly:
SELECT
event_name,
event_date,
user_pseudo_id,
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page_url,
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'session_id') AS session_id
FROM `your-project.analytics_XXXXXXXX.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20250101' AND '20251231'
AND event_name = 'page_view'
The UNNEST(event_params) pattern trips people up at first but becomes second nature quickly.
Your First Useful Query
Session count by channel, last 30 days:
WITH sessions AS (
SELECT
user_pseudo_id,
(SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS session_id,
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'medium') AS medium,
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'source') AS source
FROM `your-project.analytics_XXXXXXXX.events_*`
WHERE _TABLE_SUFFIX >= FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY))
AND event_name = 'session_start'
)
SELECT
CONCAT(source, ' / ', medium) AS channel,
COUNT(*) AS sessions
FROM sessions
GROUP BY channel
ORDER BY sessions DESC
Costs
For most sites under a few million monthly sessions, you’ll comfortably stay within BigQuery’s free tier: 10 GB of storage free, 1 TB of query processing per month free. The GA4 export itself is free.
If you want help setting this up or writing your first set of queries, book an hour with me — it’s a good use of the session.