← Back to blog
Analytics

BigQuery + GA4: The Setup Guide Nobody Writes Simply

Connecting GA4 to BigQuery opens up analysis that the GA4 interface simply can't do. Here's how to get started.

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:

Prerequisites

The Setup (Shorter Than You Think)

  1. In GA4, go to Admin → Product Links → BigQuery Links → Link
  2. Select your Google Cloud project
  3. Choose your data location (pick the region closest to you)
  4. Select Daily and/or Streaming export
  5. 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.

Found this useful? Book a free 15-minute call to talk through your setup.

🍓 Book Free Call
🍓 Free 15-Minute Call