InfiniSynapse Methods Guide

Google Analytics with BigQuery in 2026: Data Analysis Capabilities

Google Analytics + BigQuery data analysis in 2026 — what the export unlocks, schema basics, ten worked questions, dialect quirks, and where AI data agents fit.

Author / credentialsBy the InfiniSynapse Data Team. Named accountability: cofounder William Zhu (GitHub @allwefantasy). Desk experience: shipping and reviewing SQL on production GA4 BigQuery export datasets for SaaS and ecommerce teams. About: editorial standards · About InfiniSynapse.
Published2026-06-28 · Last verified 2026-07-29 · Next review 2026-10-29
Disclosure / COI: InfiniSynapse publishes this guide and sells an AI data analyst that can connect to BigQuery including GA4 BigQuery export datasets. Methods below are vendor-neutral; desk composites are labeled and are not customer SLAs. Peer review: Data Team technical pass before publish. Corrections: corrections policy.

First-person desk note: When I first wired a live GA4 BigQuery export, the schema looked simple until every useful metric hid inside event_params. The ten SQL patterns below are the ones we keep rewriting in reviews — not theory.

TL;DR

Direct answer: what the GA4 BigQuery export unlocks

The GA4 BigQuery export lands one row per event in a partitioned table — full event-level data the GA4 UI hides. Most queries UNNEST event_params and user_properties to reach values. Ten patterns cover most work; BigQuery cost depends on partition scanning. AI data agents speed up ad-hoc work on top.
GA4 BigQuery export flow — events table, unnesting steps, ten worked questions, with AI data agent overlay for ad-hoc analysis.

Desk quantitative notes (composite)

These figures come from anonymized desk replays on sample GA4 BigQuery export datasets — useful for planning, not InfiniSynapse product SLAs or customer win rates.

~18 min
Median time to first correct UNNEST query (manual desk)
~12×
Bytes billed without _TABLE_SUFFIX vs a 28-day window
7 / 10
Agent-drafted UNNEST queries almost-correct after human review
Desk composite metrics for GA4 BigQuery export work: 18 min, 12x scan, 7/10 agent drafts

The GA4 BigQuery event table schema

Each GA4 property linked to BigQuery creates a GA4 BigQuery export dataset named analytics_PROPERTY_ID. Inside it, daily tables named events_YYYYMMDD hold one row per event. Streaming export (intraday) lands in events_intraday_YYYYMMDD. Field types match the official GA4 BigQuery export schema documentation.

GA4 BigQuery export schema: analytics_PROPERTY_ID, events tables, UNNEST fields
FieldTypeNotes
event_dateSTRINGFormat YYYYMMDD
event_timestampINT64Microseconds since epoch
event_nameSTRINGpage_view, purchase, custom_event_name, etc.
event_paramsARRAY<STRUCT>Key-value pairs — needs UNNEST to read
user_pseudo_idSTRINGAnonymous client identifier
user_propertiesARRAY<STRUCT>Set via setUserProperties — needs UNNEST
device, geo, traffic_sourceSTRUCTNested structs, accessed by dot notation
ecommerce, itemsSTRUCT, ARRAYPurchase event details

The UNNEST pattern every GA4 BigQuery export query uses

GA4 BigQuery export UNNEST pattern diagram

Nearly every useful query on a GA4 BigQuery export uses this extraction shape. Official event names and parameters are listed in the GA4 events reference.

-- Extract a parameter value from event_params
SELECT
  event_date,
  event_name,
  (SELECT value.string_value FROM UNNEST(event_params)
   WHERE key = 'page_location') AS page_location,
  (SELECT value.int_value FROM UNNEST(event_params)
   WHERE key = 'engagement_time_msec') AS engagement_ms
FROM `project.analytics_PROPERTY_ID.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260628'
  AND event_name = 'page_view';

Three things to remember: _TABLE_SUFFIX is how you partition the date range, (SELECT ... FROM UNNEST(...)) is the canonical extraction shape, and choosing the right value.* field type (string_value, int_value, double_value, float_value) matters for each parameter.

Ten worked questions on GA4 BigQuery export

Copy-paste starters for the weekly questions we see most often on a GA4 BigQuery export. Replace project.analytics_PROPERTY_ID and date bounds before running. Dialect notes follow the BigQuery SQL reference.

Funnel HowTo steps on GA4 BigQuery export

1. DAU / WAU / MAU

SELECT
  PARSE_DATE('%Y%m%d', event_date) AS day,
  COUNT(DISTINCT user_pseudo_id) AS dau
FROM `project.analytics_PROPERTY_ID.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260628'
GROUP BY day
ORDER BY day;

2. Retention curve by signup cohort

WITH first_seen AS (
  SELECT user_pseudo_id, MIN(PARSE_DATE('%Y%m%d', event_date)) AS cohort_day
  FROM `project.analytics_PROPERTY_ID.events_*`
  WHERE _TABLE_SUFFIX BETWEEN '20260401' AND '20260628'
  GROUP BY 1
),
activity AS (
  SELECT DISTINCT user_pseudo_id, PARSE_DATE('%Y%m%d', event_date) AS act_day
  FROM `project.analytics_PROPERTY_ID.events_*`
  WHERE _TABLE_SUFFIX BETWEEN '20260401' AND '20260628'
)
SELECT
  f.cohort_day,
  DATE_DIFF(a.act_day, f.cohort_day, WEEK) AS week_n,
  COUNT(DISTINCT a.user_pseudo_id) AS users
FROM first_seen f
JOIN activity a USING (user_pseudo_id)
GROUP BY 1, 2
ORDER BY 1, 2;

3. Funnel analysis (view → add_to_cart → purchase)

WITH steps AS (
  SELECT
    user_pseudo_id,
    event_timestamp,
    event_name,
    ROW_NUMBER() OVER (
      PARTITION BY user_pseudo_id ORDER BY event_timestamp
    ) AS step_seq
  FROM `project.analytics_PROPERTY_ID.events_*`
  WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260628'
    AND event_name IN ('page_view', 'add_to_cart', 'purchase')
),
ordered AS (
  SELECT
    user_pseudo_id,
    MAX(IF(event_name = 'page_view', event_timestamp, NULL)) AS t_view,
    MAX(IF(event_name = 'add_to_cart', event_timestamp, NULL)) AS t_cart,
    MAX(IF(event_name = 'purchase', event_timestamp, NULL)) AS t_purchase
  FROM steps
  GROUP BY 1
)
SELECT
  COUNTIF(t_view IS NOT NULL) AS step1_users,
  COUNTIF(t_cart IS NOT NULL AND t_cart >= t_view) AS step2_users,
  COUNTIF(t_purchase IS NOT NULL AND t_purchase >= t_cart) AS step3_users
FROM ordered;

This is the HowTo shape for funnel work on a GA4 BigQuery export: project → sequence → step join → optionally materialize.

4. Attribution audit (first touch vs converting session)

WITH sessions AS (
  SELECT
    user_pseudo_id,
    event_timestamp,
    traffic_source.source AS source,
    traffic_source.medium AS medium,
    event_name
  FROM `project.analytics_PROPERTY_ID.events_*`
  WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260628'
),
first_touch AS (
  SELECT AS VALUE ARRAY_AGG(s ORDER BY event_timestamp LIMIT 1)[OFFSET(0)]
  FROM sessions s
  GROUP BY user_pseudo_id
),
converters AS (
  SELECT AS VALUE ARRAY_AGG(s ORDER BY event_timestamp DESC LIMIT 1)[OFFSET(0)]
  FROM sessions s
  WHERE event_name = 'purchase'
  GROUP BY user_pseudo_id
)
SELECT
  f.source AS first_source,
  c.source AS convert_source,
  COUNT(*) AS users
FROM first_touch f
JOIN converters c USING (user_pseudo_id)
GROUP BY 1, 2
ORDER BY users DESC;

5. Channel performance

SELECT
  traffic_source.medium AS medium,
  COUNTIF(event_name = 'purchase') AS purchases,
  SUM(IF(event_name = 'purchase', ecommerce.purchase_revenue, 0)) AS revenue
FROM `project.analytics_PROPERTY_ID.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260628'
GROUP BY medium
ORDER BY revenue DESC;

6. Custom event rates

SELECT
  COUNTIF(event_name = 'generate_lead') AS custom_events,
  COUNTIF(event_name = 'page_view') AS page_views,
  SAFE_DIVIDE(
    COUNTIF(event_name = 'generate_lead'),
    COUNTIF(event_name = 'page_view')
  ) AS custom_per_pageview
FROM `project.analytics_PROPERTY_ID.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260628';

7. Page-level engagement

SELECT
  (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page,
  AVG((SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'engagement_time_msec')) AS avg_engagement_ms
FROM `project.analytics_PROPERTY_ID.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260628'
  AND event_name = 'page_view'
GROUP BY page
ORDER BY avg_engagement_ms DESC
LIMIT 50;

8. Scroll depth analysis

SELECT
  (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page,
  (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'percent_scrolled') AS pct,
  COUNT(*) AS events
FROM `project.analytics_PROPERTY_ID.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260628'
  AND event_name = 'scroll'
GROUP BY page, pct
ORDER BY page, pct;

9. Search query analysis

SELECT
  (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'search_term') AS query,
  COUNT(*) AS searches
FROM `project.analytics_PROPERTY_ID.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260628'
  AND event_name = 'view_search_results'
GROUP BY query
ORDER BY searches DESC
LIMIT 100;

10. Revenue by source

SELECT
  traffic_source.source AS source,
  SUM(ecommerce.purchase_revenue) AS revenue,
  COUNT(*) AS purchase_events
FROM `project.analytics_PROPERTY_ID.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260601' AND '20260628'
  AND event_name = 'purchase'
GROUP BY source
ORDER BY revenue DESC;

These ten cover the majority of weekly analyst work on a GA4 BigQuery export dataset. The companion marketing data analysis playbook explains how these feed business-level KPIs.

BigQuery cost notes for GA4 BigQuery export work

Partition scan cost compare for GA4 BigQuery export

Cost accidents on a GA4 BigQuery export almost always come from scanning every daily shard. Treat partition filters as mandatory.

The BigQuery best practices documentation spells out the cost model.

Where AI data agents fit on top of GA4 BigQuery export

Three patterns where an AI data analyst earns the seat on a GA4 BigQuery export dataset:

See the AI database query pillar guide for the connection pattern and database + knowledge base binding for how to seed GA4 event definitions as bound context.

A GA4 BigQuery export hands you full event-level data — the UNNEST boilerplate is the friction. AI agents remove the friction without removing the analyst.

Ask GA4-shaped questions across your BigQuery export

Connect your GA4 BigQuery export dataset read-only. Seed a small knowledge base of event definitions — what counts as engagement, which custom events drive conversion. Then ask one open-ended question and read the plan, UNNEST SQL, and verification step before deciding.

Try InfiniSynapse online

FAQ

What does the GA4 BigQuery export contain?
The GA4 BigQuery export lands one row per event in a daily partitioned table named events_YYYYMMDD inside a dataset called analytics_PROPERTY_ID. Each row contains the event date, event name, event timestamp in microseconds, the user pseudo identifier, a nested event_params array, a nested user_properties array, and structs for device, geo, traffic source, and ecommerce details. Streaming export to events_intraday_YYYYMMDD is also available.
Why do GA4 BigQuery queries always use UNNEST?
The event_params and user_properties fields are arrays of key-value structs in BigQuery, which means a single event row holds multiple parameters at once. To read a specific parameter like page_location or engagement_time_msec, you UNNEST the array and filter by key, returning the value of the matching field type — string_value, int_value, double_value, or float_value. The pattern repeats in nearly every GA4 BigQuery query.
How do I control BigQuery cost on GA4 datasets?
Four habits cover most cost control: always restrict the partition scan with _TABLE_SUFFIX BETWEEN dates in WHERE so BigQuery scans only the relevant days, project only the columns you actually need rather than SELECT *, materialize repeatedly-used daily aggregates into a separate table you query instead, and configure BI tool connectors for incremental refresh rather than full reload on each dashboard view.
What questions does GA4 BigQuery export answer that the GA4 UI does not?
Three classes: event-level analysis that the UI aggregates away (per-user event sequences, custom funnel definitions with arbitrary steps); long retention windows beyond the GA4 UI thresholds; and cross-source joins where GA4 data sits next to CRM, payment, or other warehouse tables in BigQuery. The UI is for standing reports; the BigQuery export is for the analytical questions outside that envelope.
How do I do funnel analysis in GA4 BigQuery?
Project the events you care about per user, use ROW_NUMBER OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) to sequence them, and self-join or use LAG to find users who hit step N and then step N+1 within a time window. The shape repeats for each funnel step. Materializing per-user event sequences once and reusing them across funnel queries cuts the cost.
How does an AI data agent help with GA4 BigQuery analysis?
Three patterns: drafting the UNNEST boilerplate from a plain-English question so the analyst reviews rather than types it, handling cross-property analysis when a team has three GA4 properties and wants the same question across all of them with UNION and renaming, and ad-hoc anomaly investigation where the agent picks the right segment splits and returns a chart with the SQL and a verification step.
What is the GA4 BigQuery export schema?
The events table has event_date as a string in YYYYMMDD format, event_timestamp as INT64 microseconds since epoch, event_name as the event identifier including custom events, event_params as ARRAY STRUCT of key-value pairs, user_pseudo_id as the anonymous client identifier, user_properties as another ARRAY STRUCT, and nested STRUCTs for device, geo, traffic source, and ecommerce. Item-level purchase details sit in ARRAY items inside the ecommerce struct.

Methodology and review notes

Last updated: 2026-07-29 · Next scheduled review: 2026-10-29

This methods guide synthesizes the official GA4 BigQuery export documentation, the BigQuery SQL dialect reference, GA4 events reference, and desk experience from the InfiniSynapse Data Team with named accountability to William Zhu. Desk composites (~18 min, ~12×, 7/10) are labeled and are not product SLAs. About: editorial standards · About InfiniSynapse.

Peer review: Technical pass by a second Data Team reviewer for SQL syntax and partition-filter correctness before publish.

Conflict of interest: InfiniSynapse publishes this guide and sells an enterprise AI data analyst. To reduce bias, the page leads with the topic itself, treats InfiniSynapse as one option among many, and links to external sources for structural claims.

Update cadence: Reviewed every 90 days for accuracy and link health.

Sources and references

  1. [Vendor] Google. GA4 BigQuery export schema documentation. support.google.com/analytics/answer/7029846.
  2. [Vendor] Google. BigQuery SQL reference. cloud.google.com/bigquery/docs/reference/standard-sql.
  3. [Vendor] Google. BigQuery cost best practices. cloud.google.com/bigquery/best-practices.
  4. [Vendor] Google. GA4 events reference. developers.google.com/analytics/ga4/events.
  5. [Independent] Yao et al. ReAct paper. arxiv.org/abs/2210.03629.
  6. [Vendor] Anthropic. Building Effective Agents. anthropic.com/research/building-effective-agents.
  7. [Standard] NIST. AI Risk Management Framework. nist.gov/itl/ai-risk-management-framework.
  8. [Independent] BIRD-SQL benchmark. bird-bench.github.io.
  9. [Policy / About] InfiniSynapse — Editorial standards & author credentials. infinisynapse.com/en/editorial-standards. Company: About InfiniSynapse.

Related guides