Web analytics
Connect Google Analytics 4 to Excel, Sheets and AI
GA4 event and traffic data as SQL. Pair it with Search Console and your product database without a BigQuery export round-trip.
One connection, every surface
Where your GA4 data can go
Connect GA4 once and the same read-only connection feeds all of these — no second setup, no second copy of the data. 8 of 11 have a step-by-step guide.
GA4 to Excel
Microsoft Excel · Excel add-in
Pull live GA4 results straight into a worksheet and refresh them on demand — desktop Excel, Excel Online, Microsoft 365.
Read the guideGA4 to Google Sheets
Sheets add-on
Run a saved GA4 query from the sidebar and drop the rows into the sheet. Shared collaborators can refresh it themselves.
Read the guideGA4 MCP server
Claude, Cursor and MCP clients
Give an AI assistant read-only access to GA4 with the schema it needs to write correct SQL — no credentials in the chat.
Read the guideGA4 REST API
HTTP endpoint
Publish a GA4 query as an authenticated JSON endpoint any application can call, with an OpenAPI 3.1 spec and ready-made Postman, Insomnia and Hoppscotch collections. No database port is opened.
How REST API works no GA4 walkthrough written yetGA4 to Airtable
Automation platform
Sync GA4 rows into an Airtable base on a schedule, or fetch them inside an Airtable automation script.
Read the guideGA4 to Baserow
Automation platform
Feed a Baserow table from GA4 over the REST endpoint — self-hosted or Baserow cloud.
Read the guideGA4 to SeaTable
Automation platform
Keep a SeaTable base current with GA4 data without exporting a file or exposing the database.
Read the guideGA4 to Smartsheet
Automation platform
Push GA4 results into a Smartsheet grid so plans and reports read from the source system, not last week's export.
Read the guideGA4 to Anvil
Anvil Works · App platform
Back an Anvil Python app with GA4 through the REST endpoint instead of embedding database credentials in the app.
Read the guideGA4 to Power BI
Power Query M
Paste the generated Power Query M into the Power BI Advanced Editor and the report reads live GA4 results over HTTPS — no ODBC driver, no database port opened.
How Power BI works no GA4 walkthrough written yetGA4 alerts and reports
Slack · Discord · Email · Webhook
Put a GA4 query on a schedule and have the rows delivered to Slack, Discord, email or a signed webhook — or hold the message until a row count, threshold or percentage change crosses the line you set.
How alerts and reports work no GA4 walkthrough written yetHow it works
5 steps, no inbound firewall change
Create a Google service account and grant it read access to the GA4 property.
Install the Network Agent and give it the service account key and the numeric property id. The key stays on the agent.
Choose which of the 9 tables to sync. Traffic overview, traffic sources, page views and events are on by default.
Write ordinary SQL against ga4.traffic_sources, ga4.page_views and the rest — or let Nova write it.
Read it from Excel, Sheets, Power BI, MCP or REST, joined to whatever holds your signups and revenue.
Feature deep-dive
What GA4 gives you
Without the BigQuery detour
The usual way to get GA4 into SQL is to link a BigQuery project, wait for the export to start, pay for storage and then query a nested event table. This skips all of it.
- Data comes from GA4's own reporting API, so there is no export to configure and nothing to wait for.
- It reads back to GA4's launch in October 2020 on first sync, so the history is there rather than starting from the day you set it up.
- Rows arrive as day-grain aggregates with named columns — date, source, medium, campaign, channel, sessions, users, engagement rate — rather than as nested event blobs you have to unnest.
- The complete API response is kept alongside in a raw_data JSON column.
The 9 tables
- Traffic — traffic_overview, traffic_sources, page_views, user_engagement.
- Audience — geographic_data, events.
- Commerce — ecommerce_overview, transactions.
- Now — realtime_active_users.
Two clocks, and which table runs on which
GA4 has a batch side and a realtime side, and they behave differently. Being clear about it is the difference between a report you trust and one you argue with.
- The eight batch tables run to yesterday. GA4 does not finalise a day's figures for a day or two, so each incremental pass re-reads the previous three days and lets the numbers settle rather than freezing the first version it saw.
- realtime_active_users is genuinely live — a rolling thirty-minute window, refreshed on demand when a query touches it, with a thirty-second freshness window.
- That table is a snapshot, not a history: it answers who is on the site now, not who was on it at four o'clock yesterday.
Shared by every API connector
How every API connector works
- Your account becomes tables — endpoints are mapped to typed SQL tables with primary keys and indexes, so you write SELECT, JOIN and GROUP BY instead of paging through JSON.
- You choose what syncs, and how often — each table has its own interval, or none at all. Where the vendor's API supports it, only records that changed since the last run are fetched.
- The copy is yours — it lives in an AES-256-GCM encrypted DuckDB file next to the agent, on your machine. Not in our cloud.
- The vendor only ever hears from you — the agent calls the API directly from your own network, so your token is not needed by Query Streams to answer a query.
Good to know
- It is a synced copy, not a live proxy — a query reads what has already been fetched, so it returns at SQL speed and never spends your API rate limit. Selected tables can additionally refresh a stale row as you read it.
- Rate limits are respected for you — each connector paces itself well inside the vendor's published limits, so a report cannot get your account throttled for everything else that uses it.
- Nothing is thrown away — fields the table does not name are kept in a raw_data JSON column you can still query.
- Join it to your databases — an API table and a SQL Server table in the same statement is an ordinary query here, not an integration project.
Cross-source SQL
Join GA4 to the rest of your data
GA4 knows which source the session came from and nothing about what it was worth. Your database knows the account and your payment processor knows the money. One statement can put the three side by side. Each source runs only the part it can, streams the result back, and the join happens centrally — the sources never talk to each other and nothing is copied anywhere.
3 connections · 3 agents
One statement
-- sessions from GA4, the account from your database, revenue from Stripe
SELECT g.session_source, SUM(g.sessions) AS sessions, SUM(i.amount_due) AS invoiced
FROM ga4_site.ga4.traffic_sources1 g
JOIN pg_crm.public.customers2 c ON c.utm_source = g.session_source
JOIN billing.stripe.invoices3 i ON i.customer = c.stripe_id
GROUP BY g.session_source
ORDER BY invoiced DESC;
The three parts are connection, schema and table — and the connection name is whatever you called it. Illustrative columns; your tables will be your tables. Batch GA4 tables run to yesterday, so the newest day in a report like this is the day before today — that is GA4’s own finalisation window, not a sync delay. Read-only applies to every piece: SELECT, WITH and EXPLAIN only, with a ceiling on how much any one source may hand over for a single query. How federated queries work
Connection details
What GA4 needs
- Authentication
- A Google service account key with read access to the property, held on the agent. Read-only scope
- Property
- The numeric GA4 property id
- Reached over
- HTTPS from your network to the GA4 Data API. Nothing inbound
- Schema
- ga4 — so ga4.traffic_sources, ga4.page_views
- Tables
- 9, of which four are on by default: traffic_overview, traffic_sources, page_views, events
- Freshness
- Batch tables run to yesterday, with the previous three days re-read each pass as GA4 finalises them
- History
- Back to 2020-10-01 on first sync
- Live refresh
- realtime_active_users only — a rolling 30-minute window with a 30-second freshness window
- Local copy
- An AES-256-GCM encrypted DuckDB file beside the agent, on your machine
The realtime table is capped at the top few hundred combinations Google returns in a snapshot, which is a limit of the realtime API rather than of this connector. For a complete picture of a day, use the batch tables.
In a cross-source query the middle part of a three-part reference is ga4. A connection called ga4_site reading traffic sources is written ga4_site.ga4.traffic_sources.
Vendor documentation: marketingplatform.google.com
FAQ
Questions about Google Analytics 4
Which tools can read Google Analytics 4 data through Query Streams?
All of them, from one connection: Excel, Google Sheets, MCP, REST API, Airtable, Baserow, SeaTable, Smartsheet, Anvil, Power BI, scheduled alerts and reports. Connect the account once and every surface reads the same read-only connection — there is no per-tool setup and no second copy of the data.
Do I have to open a firewall port to my Google Analytics 4 account?
No. The Query Streams Network Agent runs inside your network and opens a single outbound encrypted connection. Nothing listens for inbound traffic, no VPN is required, and the account keeps its existing firewall rules.
Can Query Streams change data in Google Analytics 4?
No. The agent enforces read-only at the point of execution — one statement at a time, SELECT and friends only. Credentials stay on the agent and are never sent to Query Streams.
What does Query Streams need to connect to Google Analytics 4?
A reachable host, a role and its password — the agent carries the driver, so nothing is installed on the account. Authentication: A Google service account key with read access to the property, held on the agent. Read-only scope. Property: The numeric GA4 property id. Reached over: HTTPS from your network to the GA4 Data API. Nothing inbound. Schema: ga4 — so ga4.traffic_sources, ga4.page_views.
Can I join Google Analytics 4 to another database in the same query?
Yes — that is a federated query. One statement can reference Google Analytics 4 and your other connections at once, written as connection.schema.table. Each source runs only the part it can and streams the result back; the join happens centrally, so the sources never connect to each other and nothing is copied or scheduled. Read-only applies to every piece — SELECT, WITH and EXPLAIN only — and there is a ceiling on how much any one source may hand over for a single query. Federated queries are a plan feature; the federated queries page carries the current source and size limits.
Put GA4 where the work happens
Install the agent, point it at your account, and pick a destination.
Read-only Outbound only Credentials stay on the agent

