Sooner or later, every serious GA4 user hits a wall. An exploration shows a sampling warning. A year-on-year comparison is impossible because event data was only retained for fourteen months. A stakeholder wants conversion paths joined to CRM revenue, or a custom attribution rule the interface doesn't offer. The GA4 interface is a reporting tool, and it was never designed to answer every question.
The BigQuery export is Google's answer: a raw, event-by-event copy of your GA4 data in Google's cloud data warehouse, which you can query with SQL, keep for as long as you like and join to anything. It's free to switch on for standard properties, and for many small and mid-sized businesses the ongoing cost is close to zero if you set it up sensibly.
This guide explains what the export contains, when you genuinely need it, how to set it up and keep costs under control, the first queries worth saving, how to connect it to Data Studio (the renamed Looker Studio), and how to add Search Console's bulk export alongside it. The most important practical advice comes first: the export is not retroactive, so the best time to turn it on is before you need it.
What lands in BigQuery when you link GA4
Once linked, GA4 creates a dataset in your Google Cloud project named analytics_ followed by your property ID. Inside it, data arrives as one table per day. Every event your site or app sends (each page_view, scroll, generate_lead, purchase) becomes a row, with its parameters stored in nested, repeated fields.
| Table | What it contains | When it appears |
|---|---|---|
events_YYYYMMDD | All events for one day, with event parameters, user properties, device, geography, app/web info, ecommerce items and traffic source fields | Daily export, typically the following day |
events_intraday_YYYYMMDD | Today's events, updated continuously through the day | Only if streaming export is enabled |
pseudonymous_users_YYYYMMDD | User-level attributes for users identified by device or cookie, such as audiences and lifetime values | If user data export is enabled |
users_YYYYMMDD | The same for users identified by your own user ID | If you send a user ID and enable user data export |
Some things in the interface are not in the export as you see them in reports. There are no pre-calculated sessions, engagement rates or channel groupings; you calculate them from events. Modelled data (such as conversions modelled for users who declined consent) and Google signals demographics are not included. And reporting features you configure in the admin, like custom channel groups, don't flow through: Google's help page on custom channel groups lists the BigQuery export schema among the places they can't be used. Expect your BigQuery numbers to differ slightly from the interface, and decide which source is authoritative for which purpose.
Traffic source data deserves a specific mention. The export contains several traffic source records: one describing how the user was first acquired, an event-level record of collected campaign parameters, and, in newer exports, a session-level last-click record that lines up more closely with session reports. Check which fields your export includes before writing attribution queries, because older tutorials often use the user-level first-touch field by mistake.
Signs the GA4 interface is no longer enough
Not every business needs the export. If your questions are answered by standard reports and explorations, it's optional insurance. These are the situations where it becomes necessary:
| Limitation in the GA4 interface | What BigQuery gives you |
|---|---|
| Explorations sample data on large date ranges or busy properties | Every event, unsampled |
| Event-level data retention of 2 or 14 months for explorations | Data kept as long as you store it |
| Data thresholds hide rows with small user counts | Raw rows without thresholding (see our GA4 data thresholds guide) |
| "(other)" rows in high-cardinality reports | Every page path, query string and parameter value |
| No way to join GA4 to CRM, ad cost or offline sales data | SQL joins on user ID, transaction ID or click IDs |
| Fixed attribution and session definitions | Custom attribution, session and funnel logic |
| Changing channel rules can't be audited after the fact | Your own versioned channel logic in SQL |
A quick self-test: if in the past six months you've abandoned a question because of sampling, thresholds, retention or a missing join, turn the export on now. Even if you don't query it for a year, you'll have the history when you need it.
Linking GA4 to BigQuery in under an hour
You need Editor access on the GA4 property and Owner access on a Google Cloud project. If you don't have a project, create one first.
- In the Google Cloud console, create or select a project and make sure the BigQuery API is enabled.
- Decide whether to start in the BigQuery sandbox (no billing account, but tables expire automatically) or attach a billing account. For a permanent export, attach billing and set a budget alert immediately; it costs nothing to have one.
- In GA4, go to Admin → Product links → BigQuery links and click Link.
- Choose your Cloud project and a data location. Pick the region where you'll keep other data you want to join (for example, the EU if you're bound by EU data residency policies). You can't change it later without re-linking.
- Select which data streams to export, and optionally exclude noisy events (some sites exclude high-volume events they never analyse to stay within limits).
- Choose the export frequency: Daily, Streaming, or both. Optionally enable user data export.
- Review and submit. The first daily table usually appears within a day or so.
| Export type | Timing | Cost and limits | Good for |
|---|---|---|---|
| Daily | Once per day for the previous day | No GA4 charge; standard properties have a daily event export limit (historically 1 million events per day) | Almost everyone |
| Streaming | Within minutes into intraday tables | Billed by BigQuery for streaming ingestion; no daily limit | Near-real-time monitoring, large sites |
| Fresh daily (360 only) | Earlier and more frequent daily updates | Part of Analytics 360 | Enterprises with SLAs |
If a standard property regularly exceeds the daily event limit, Google may pause the daily export, so busy sites should check event volumes first and either exclude events they don't need or use streaming. Verify the current limits in the GA4 help centre when you link, as they have changed over time.
Because the export only starts on the day you link it, there is no backfill of earlier data. That alone is why many analysts link it on day one of any new property, as part of a GA4 audit checklist.
Keeping BigQuery costs close to zero
BigQuery charges separately for storage and for the data each query scans. Google's free tier includes a monthly allowance of both, and a small site's GA4 export often stays within it. The habit that matters most is scanning less data per query.
- Always filter by date with
_TABLE_SUFFIX. Queryingevents_*without a date filter scans every day you've ever exported. - Never use
SELECT *. BigQuery is columnar, so you pay for the columns you read. Name only the fields you need. - Check the estimate before running. The query editor shows how many bytes a query will process; treat anything unexpectedly large as a bug.
- Use table preview instead of queries to look at sample rows; previewing doesn't scan data.
- Build small summary tables. A scheduled query that writes daily sessions, key events and revenue by page and channel into a compact table lets dashboards read megabytes instead of gigabytes.
- Set budget alerts and query quotas in Google Cloud so a runaway dashboard can't surprise you.
- Grant read access deliberately. Every person with query rights can spend money; give most users access to summary tables or dashboards instead.
Hypothetical example: a lead generation site sends about 400,000 events a month. Its export grows by a fraction of a gigabyte a month, so even after two years the dataset is a few gigabytes, and storage cost is negligible. Query cost depends on habits: an analyst who runs date-filtered queries on a handful of columns scans tiny amounts, while a dashboard that runs SELECT * across all tables on every page load can scan the whole dataset dozens of times a day. Same data, very different bill.
Starter queries for sessions, key events and pages
Replace your-project.analytics_123456789 with your own project and dataset. These use standard SQL and filter to September 2026 as an example.
Users and sessions by day
SELECT
event_date,
COUNT(DISTINCT user_pseudo_id) AS users,
COUNT(DISTINCT CONCAT(user_pseudo_id, CAST(
(SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS STRING))) AS sessions
FROM `your-project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260901' AND '20260930'
GROUP BY event_date
ORDER BY event_date;
Sessions are identified by combining the user's pseudonymous ID with the ga_session_id parameter. Expect small differences from the interface, which uses estimation for some counts.
Key events by name
SELECT event_name, COUNT(*) AS events, COUNT(DISTINCT user_pseudo_id) AS users
FROM `your-project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260901' AND '20260930'
AND event_name IN ('generate_lead', 'purchase', 'sign_up')
GROUP BY event_name;
Landing pages with sessions and leads
WITH sessions AS (
SELECT
CONCAT(user_pseudo_id, CAST((SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS STRING)) AS session_key,
MAX(IF((SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'entrances') = 1,
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location'), NULL)) AS landing_page,
COUNTIF(event_name = 'generate_lead') AS leads
FROM `your-project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260901' AND '20260930'
GROUP BY session_key
)
SELECT REGEXP_REPLACE(landing_page, r'[?#].*$', '') AS landing_page,
COUNT(*) AS sessions, SUM(leads) AS leads
FROM sessions
GROUP BY landing_page
ORDER BY sessions DESC
LIMIT 50;
Notice the query strips query strings from the landing page, something the GA4 interface makes awkward. The same trick is useful when joining to Search Console data.
Purchases with transaction details
SELECT event_date, ecommerce.transaction_id, ecommerce.purchase_revenue
FROM `your-project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260901' AND '20260930'
AND event_name = 'purchase';
Transaction IDs are what let you join GA4 purchases to your order system or CRM, which is the basis for measuring true revenue by channel and for metrics like CAC payback period.
A practical tip: when a query works, save it with a clear name and a comment describing what it counts. A shared library of a dozen trusted queries is worth more than a hundred ad hoc ones. If a query depends on events your developers send, document those events in your data layer specification so the SQL and the tracking stay in step.
Connecting BigQuery to Data Studio without a surprise bill
Data Studio (Google renamed Looker Studio in April 2026) has a native BigQuery connector. You can point it at a table or write a custom query. The mistake to avoid is connecting a dashboard directly to the raw events_* tables: every chart, filter change and date change can trigger a new query over large amounts of data.
- Create a scheduled query that aggregates yesterday's data into a summary table, for example one row per date, landing page, channel and device with sessions, leads and revenue.
- Connect Data Studio to the summary table, not the raw export.
- If you must use a custom query, use the connector's date parameters so it only scans the selected date range.
- Turn on data freshness settings appropriate to the data (daily data doesn't need refreshing every 15 minutes).
- Recreate channel groupings in SQL with a
CASEstatement that mirrors your GA4 rules, and document it so it doesn't drift.
Our guides to building an SEO dashboard and a broader marketing dashboard cover layout; this approach just changes where the data comes from. Smaller teams can also bring aggregated query results into Sheets using Connected Sheets; see our Google Sheets for marketers guide.
Adding Search Console bulk export alongside GA4
Search Console offers its own BigQuery export, which removes the row limits of the interface and API and keeps query-level data beyond the interface's 16 months.
“You can configure an export in Search Console to get a daily data dump into your BigQuery project.”
— Google Search Central Blog, Bulk data export: a new and powerful way to access your Search Console data
The export creates a searchconsole dataset with site-level and URL-level impression tables plus an export log. Like the GA4 export, it starts from the day you set it up and is not backfilled. Put it in the same Cloud project and region as your GA4 export so you can join them.
Joining the two is where the value is. Search Console tells you which queries and pages earn impressions and clicks; GA4 tells you what those visitors did. Normalise URLs on both sides (strip protocol, host and query strings), aggregate each to page and date, then join. The result is a page-level table of impressions, clicks, average position, sessions, leads and revenue: the core of a genuinely useful SEO report.
Search Console's tables can be large on big sites, so the same cost rules apply. Google published a follow-up specifically on that subject:
“we discuss tips to help you take advantage of the Search Console bulk data exports without incurring significant cost in BigQuery”
— Google Search Central Blog, BigQuery efficiency tips for Search Console bulk data exports
For most sites, filtering by date and selecting only the columns you need keeps the cost negligible. If you are new to the underlying data, our guide to the Search Console performance report explains the metrics before you start querying them.
Questions teams ask before turning on the GA4 BigQuery export
Is the GA4 BigQuery export free?
Linking is free for standard properties and GA4 doesn't charge for the daily export. You pay BigQuery for storage and queries beyond Google Cloud's free tier, and for streaming ingestion if you enable streaming. Many small sites stay within the free tier with sensible query habits.
Can I export historical GA4 data to BigQuery?
No. The export starts from the day you link it and does not backfill. That is the main reason to link it early, even if you will not query it for months.
Why do my BigQuery numbers not match the GA4 interface?
The interface uses estimation for some counts, applies thresholds, can include modelled data and uses configured settings such as channel groups. The export is raw events. Small differences are normal; document which source you use for which report.
Do I need to know SQL to use the export?
Someone on the team does, at least to build a few trusted queries and summary tables. Once those exist, most people can use the results through Data Studio or Sheets without writing SQL.
Should I use the BigQuery sandbox?
It is fine for learning and testing, but sandbox tables expire automatically, so it is not suitable for a permanent export. Attach billing with a budget alert for anything you want to keep.
Turning the export on before you need it
Create a Cloud project, attach billing with a budget alert, link GA4 with daily export in the right region, and do the same for Search Console. Save the starter queries, build one summary table, and point a single Data Studio page at it. That's a day's work that protects years of data.
If you'd like help setting up the export, building reliable summary tables or joining GA4 and Search Console for SEO reporting, our SEO and enterprise SEO teams work with BigQuery every day. Get a quote to discuss your analytics set-up.
Further reading on GA4 BigQuery export
- GA4 Data Thresholds and Sampling: Why Your Numbers Look Off
- GA4 Custom Channel Groups: Fix '(Unassigned)' and Misattributed Traffic
- Statistical Significance for Marketers: Sample Sizes and A/B Test Results
Sources for this GA4 BigQuery export guide
- Google Search Central Blog: Bulk data export – a new and powerful way to access your Search Console data (February 2023)
- Google Search Central Blog: BigQuery efficiency tips for Search Console bulk data exports (June 2023)
- Google Analytics Help: Custom channel groups
- Google Analytics Help: Default channel group
- Google Analytics Help: What's new in Google Analytics (2026)




