Skip to main content
Lifetime license included with every purchase
n8n workflowsGA4 reportinganalytics automationmarketing reports

n8n GA4 Reporting Workflow: A Decision-Ready Digest, Not a Metrics Dump

Build an n8n GA4 reporting workflow that sends a color-coded week-over-week digest, not a raw metrics dump — with the OAuth and dimension gotchas spelled out.

Nn8n Marketplace Team·July 21, 2026·Updated July 21, 2026·8 min read

A standard GA4 export reads like a phone book: rows of sessions, users, and pageviews broken down by channel, all in neutral black text. The recipient scans it, finds nothing flagged, and closes the tab. The data was there. The decision wasn't.

An n8n GA4 reporting workflow worth building does the opposite. It pulls the same GA4 numbers, computes what changed since last week, and renders a digest where a 30% drop in conversions is red and impossible to miss. The job isn't moving GA4 data into an email. It's turning GA4 data into something someone acts on before the next standup.

Most GA4 templates stop at the export. The gap, and the reason this post exists, is everything after runReport returns: the week-over-week math, the color coding, and the OAuth and dimension traps that make GA4's API quietly return nothing.

What You Can Automate With GA4

The GA4 reporting jobs that fit cleanly into a workflow:

  • Pulling sessions, users, and conversions on a schedule via runReport
  • Breaking metrics down by channel, device, or landing page dimension
  • Computing week-over-week and month-over-month deltas automatically
  • Flagging high bounce rates and zero-conversion channels
  • Rendering a color-coded HTML digest instead of a raw table
  • Emailing the digest to stakeholders before the Monday meeting
  • Logging each run's snapshot so trends are visible beyond GA4's own retention

The delta computation and the flagging are what separate a report someone reads from a report someone archives unread.

The GA4 Reporting Pipeline

The structure every GA4 digest follows:

Schedule → runReport (current + prior period) → Compute deltas → Flag → Render → Send

A concrete weekly run:

Schedule Trigger v1.2 (cron: 0 8 * * 1)
  → HTTP Request v4.2: runReport (this week)   property=properties/123456789
  → HTTP Request v4.2: runReport (last week)
  → Merge v3: align metrics by dimension
  → Code v2 (jsCode): compute WoW %, flag bounce > threshold, conversions == 0
  → Code v2 (jsCode): build color-coded HTML
  → Gmail v2: send digest
  → Google Sheets v4: append weekly snapshot

The two runReport calls (this week and last week) are deliberate. GA4's API won't hand you a delta; it gives you a period's numbers and nothing else. You fetch both periods and compute the change yourself in a Code node. The properties/123456789 path uses the numeric GA4 property Id, not a view Id from old Universal Analytics — mixing those up is the single most common reason the call returns zero rows.

The property Id trap

GA4 property Ids are numeric (123456789) and prefix as properties/123456789 in the API. The old Universal Analytics view Ids look different and are dead. If your runReport returns an empty rows array with a 200 status, check the property Id before anything else — a wrong Id doesn't error, it just returns nothing, which sends people down a debugging rabbit hole that has nothing to do with their query.

Step-by-Step Breakdown

1. Authenticate with the right scope

The Google OAuth2 credential needs the analytics.readonly scope. Without it the API returns a 403, or worse, an empty result that looks like a data problem. Add the scope when you create the credential, not after.

2. Call runReport for both periods

One call for the current week, one for the prior week, same metrics and dimensions. Specify metrics like sessions and conversions, dimensions like sessionDefaultChannelGroup. Keep the two calls identical except for the date range.

3. Align and compute deltas

A Merge node lines up the two periods by dimension value, then a Code node computes the percentage change per metric. A channel that vanished this week (present last week, absent now) needs explicit handling — it won't appear in this week's rows at all.

4. Flag what matters

The same Code node marks bounce rates over a threshold and channels with zero conversions. These flags are the report's reason to exist. A number nobody flagged is a number nobody reads.

5. Render and send

A second Code node builds the HTML with inline CSS so increases are green and drops are red, then the Gmail node sends it. A Google Sheets append stores the snapshot so you have history past GA4's default retention window.

Implementation Patterns That Hold Up

Pattern 1 — Two periods, one delta. GA4 gives you periods, never deltas. Always fetch current and prior, then subtract.

Code v2 (jsCode):
  const wow = (cur, prev) =>
    prev === 0 ? null : Math.round(((cur - prev) / prev) * 100);
  return rows.map(r => ({
    json: { channel: r.channel, sessions: r.sessions,
            sessionsWoW: wow(r.sessions, r.prevSessions) }
  }));

The prev === 0 guard matters: a channel that had zero sessions last week and some this week produces a division-by-zero that renders as Infinity% in the email if you don't catch it.

Pattern 2 — Dimension discipline. GA4 caps the metric-and-dimension combinations a single runReport allows, and incompatible pairings return an error rather than a partial result. Request only the dimensions the report actually shows. Asking for sessionDefaultChannelGroup plus landingPagePlusQueryString plus device in one call is the kind of over-fetch that trips GA4's compatibility rules.

Pattern 3 — Color-coded, flag-first layout. The digest leads with what changed, not with a full table. The App Analytics Dashboard template builds exactly this: it fetches GA4 data daily, breaks sessions, users, and conversions down by channel and device, and flags high bounce rates and zero-conversion channels at the top, so the reader sees the problems before the totals.

n8n Nodes You'll Use Most

NodePurpose
n8n-nodes-base.httpRequestGA4 runReport calls with the OAuth2 credential
n8n-nodes-base.googleAnalyticsNative GA4 reporting for common metric pulls
n8n-nodes-base.scheduleTriggerWeekly Monday-morning digest run
n8n-nodes-base.mergeAlign current and prior period by dimension
n8n-nodes-base.codeDelta math, flagging, color-coded HTML render
n8n-nodes-base.gmailSend the finished digest
n8n-nodes-base.googleSheetsSnapshot log for long-term trend history

The native Google Analytics node handles straightforward pulls fine. Reach for the HTTP Request node (v4.2) when you need precise control over the runReport body — custom date ranges, metric filters, or ordering the node doesn't expose. Both authenticate with the same Google OAuth2 credential. The GA4 Data API runReport reference documents every metric and dimension name.

Getting Started

  1. Create the Google OAuth2 credential with analytics.readonly. Confirm the scope is present. This is the most common silent failure.
  2. Find the numeric GA4 property Id. It's in GA4 admin under property settings. Not a Universal Analytics view Id.
  3. Get one runReport returning rows. Sessions by channel, last 7 days. See real numbers in the execution output before building anything on top.
  4. Add the prior-period call and the delta math. Verify the percentages against a manual check in the GA4 UI.
  5. Build the color-coded HTML. Inline the CSS — email clients strip <style> blocks. Test against a real inbox.
  6. Schedule, flag, and log. Monday 8am, bounce and zero-conversion flags on, snapshot to a sheet every run.
Browse the analytics templates
Skip the build

The App Analytics Dashboard template ships this GA4 digest end-to-end: a daily Schedule Trigger fetches Google Analytics 4 data, a Code node breaks sessions, users, and conversions down by channel and device, and the report flags high bounce rates and zero-conversion channels automatically — the decision-ready layout, already wired. It's part of The Complete n8n Templates Bundle, a one-time lifetime license to the whole catalog (plus every template added later) if you run more than one of these analytics automations.

Get the App Analytics Dashboard

A caveat worth pinning down before you schedule anything: GA4 processes some metrics with a 24-to-48-hour lag, so a report fired at midnight for "yesterday" can show numbers that shift by Monday afternoon. Either run the digest for a period that's safely closed, or label the report as preliminary. Reporting a number that later changes erodes trust in the whole workflow.

For the multi-client version of this, where GA4 is one of several sources feeding a per-client report, see the guide to automating client reporting with n8n. The broader metric-collection patterns live in the n8n analytics automation guide.

Get one runReport returning real rows first. Everything after that — the deltas, the colors, the flags — is Code-node work you fully control.

See more reporting templates
FAQ

Common questions

How does an n8n GA4 reporting workflow pull data from Google Analytics 4?
It calls the GA4 Data API runReport method, either through the Google Analytics node or an HTTP Request node with a Google OAuth2 credential. You specify a property Id, a date range, the metrics (like sessions, conversions), and the dimensions (like sessionDefaultChannelGroup). The API returns rows of metric values broken down by dimension, which a Code node then formats into a digest.
Why does my GA4 report in n8n return zero rows?
Almost always one of three things: the OAuth2 scope is missing analytics.readonly, the property Id is wrong (using the Universal Analytics view Id instead of the GA4 numeric property Id), or the date range has no data because GA4 processing lags by 24 to 48 hours for some metrics. Check the scope first, then confirm the property Id is the numeric GA4 one, then widen the date range.
Can n8n send a color-coded GA4 report by email?
Yes. After runReport returns the numbers, a Code node computes the week-over-week delta per metric and builds an HTML email where increases render green and drops render red. The HTML goes into the Gmail or SMTP node body. The App Analytics Dashboard template ships this decision-ready layout for GA4 data, including bounce-rate and zero-conversion flags.
Stop reading. Start running.

Get the workflow templates this guide is built on

Import-ready n8n JSON, step-by-step setup, and tested end-to-end. One-time payment, own it forever.

Free — $40 value

Get 3 tested n8n templates, free

The full customer package for three real catalog templates — workflow JSON, step-by-step setup guide, credential checklist. Built through the same live-instance release process as everything we sell. Plus new templates and automation guides in your inbox. No spam, unsubscribe anytime.

  • 01Smart To-Do List ManagerPre-built n8n workflow template that automates productivity with OpenAI. Live in about 10 minutes.$14
  • 02Email Follow-Up AutomatorPre-built n8n workflow template that automates crm with OpenAI. Live in about 15 minutes.$12
  • 03Market Trend AnalyzerPre-built n8n workflow template that automates data processing with OpenAI. Live in about 10 minutes.$14