Skip to content
Docs menu

Connecting data

Google Analytics 4

Connect GA4 through its BigQuery export, and understand the tables, settling window and cost controls.

GA4's reporting API only returns aggregates. They're capped, sampled over long date ranges, and fold rare values into (other). The only way to get event-level data out of GA4 is its BigQuery export, so that's what Datachef reads. Two things have to exist before you connect.

In GA4, go to Admin → Product links → BigQuery links → Link. Choose a Google Cloud project, turn on the daily export (and the streaming export if you want today's data too), and save. The first events_YYYYMMDD table appears about a day later.

The export isn't backfilled. It holds data from the day you link it, and nothing earlier, so link it before you need the history.

2. Create a service account

In that Google Cloud project, create a service account and give it two roles:

RoleWhere
BigQuery Data ViewerOn the analytics_<property id> dataset
BigQuery Job UserOn the project that runs the queries

Then download a JSON key for the service account. Job User is the role people usually forget. The connection test runs a free dry-run query, so if the role is missing you'll find out when you save, not at the first sync.

Connection fields

FieldNotes
Google Cloud projectThe project that holds the export dataset
Billing projectLeave blank unless the queries should be billed to a different project, for example when the export is shared to you from another project
Export datasetanalytics_<property id>
Service account keyPaste the whole JSON key
Sync data fromDefaults to one year ago
Days to let a shard settleDefaults to 3. See below.
Days per queryOptional. Leave blank unless you want smaller queries.
Max GB scanned per queryA hard ceiling. BigQuery refuses a query it estimates would scan more, instead of billing you for it.

Tables

You get one table per export family, not one per day:

TablePresent whenSync modes
eventsAlwaysIncremental or full refresh
events_event_params, events_items, events_user_propertiesAlwaysIncremental or full refresh
events_intraday (and its child tables)The streaming export is onFull refresh only
users, pseudonymous_users (and their child tables)The user-data export is onIncremental or full refresh

Nested records are flattened to one column per field, so device.category becomes device_category. Each repeated field, such as event_params, becomes a table of its own with one row per element. It keeps its parent's key columns so you can join back to the event.

This is event-level data, not GA4's reports. There are no pre-computed sessions or channel groupings, so you compute them in SQL. The agent knows the export's schema and can write those queries for you.

The settling window

GA4 keeps adding events to a day's table for up to 72 hours after the day ends. An incremental sync waits until a day has settled before reading it, and then never reads that day again. Data lands a few days late, but it lands once and complete. With the default of 3 days, the table for the 1st is read on the 6th. The extra two days allow for the property's timezone.

A full refresh doesn't wait, because it replaces the whole table each time.

Keeping BigQuery costs down

BigQuery bills for the bytes a query scans:

  • Columns you don't sync aren't scanned, so they aren't billed.
  • Syncs are filtered by day, so BigQuery skips whole days that aren't needed.
  • Max GB scanned per query caps any one query.

Trying it without a GA4 property

Google publishes an export of its merchandise store as a public dataset. You can use it to try the connector:

FieldValue
Google Cloud projectbigquery-public-data
Billing projectAny project of yours with BigQuery enabled. A free BigQuery sandbox project works.
Export datasetga4_obfuscated_sample_ecommerce
Sync data from2020-11-01

The data ends in early 2021, so you have to set Sync data from. With the default of one year ago, nothing is found.

Something missing or wrong on this page? Tell us