Blog · Metrics that hold up

Blended ROAS: one honest number across Google Ads, Meta and GA4

Published August 17, 2026 · 9 min read

Add up the revenue each ad platform claims and you will get a number larger than your actual revenue. This is not a bug in anyone's reporting. Meta counts a sale it believes it influenced; Google Ads counts the same sale it also believes it influenced; neither can see the other's touchpoints. Each is answering "did my ads contribute?" — and both can honestly say yes about the same purchase.

Blended ROAS is the metric that steps around the whole argument. It doesn't ask who deserves credit. It divides all revenue by all spend, once, at the top. That makes it boring, un-gameable, and the right number to steer a budget by. This guide covers what it is, why it disagrees with your platform dashboards, and how to compute it as a standing query instead of a monthly spreadsheet.

What blended ROAS actually is

The formula is deliberately unexciting:

Blended ROAS = total revenue ÷ total ad spend, across every channel, over one period.

What makes it different from platform ROAS isn't the arithmetic — it's the scope. Platform ROAS is computed inside a walled garden, over the conversions that garden believes it caused. Blended ROAS is computed over everything, and because a sale can only appear once in your revenue total, no amount of attribution disagreement can inflate it.

The trade-off is honest and worth stating: blended ROAS tells you nothing about which channel is working. It is a thermostat, not a diagnostic. You steer total budget by it and use narrower cuts to hunt for waste inside a channel.

Why the numbers disagree so much

Four mechanisms drive most of the gap, and knowing them stops you from "reconciling" things that were never meant to match:

  • Overlapping credit. One buyer, several ad touches, multiple platforms each claiming the conversion.
  • Different attribution windows. A click-through window of one length versus another produces different conversion counts from identical behaviour.
  • View-through conversions. Some platforms count an impression that was never clicked. Your bank statement does not.
  • Different revenue definitions. A platform's "purchase value" may include tax and shipping, or count a subscription's first payment where your accounting counts the whole contract.

None of these are resolvable by staring harder at dashboards. They're resolvable by picking one definition and computing everything from it — which is the actual work.

The hard part isn't the formula

Almost nobody struggles with dividing two numbers. What breaks is everything upstream:

  1. Getting spend and revenue into the same table when each platform exports a different schema, names its columns differently, and reports on its own delay.
  2. Keeping the definition stable so this month's blended ROAS is comparable to last month's — not quietly different because someone included a channel they'd forgotten last time.
  3. Keeping it current without rebuilding the whole thing every Monday morning.

The spreadsheet approach fails all three at once. Every export is a snapshot, the column mapping lives in one person's head, and the file is stale the moment it's saved. The rest of this article is the version that doesn't rot.

Step 1: land every channel in one definition

Connect each source once through TableBI. Live sources use a browser OAuth round-trip; anything else arrives as CSV and is normalized into the same shape:

terminal
# install the CLI and teach Claude Code to drive it
npm i -g @tablebi/cli
tablebi login
tablebi install

# paid channels + the analytics view of revenue
tablebi connect google_ads
tablebi connect meta_ads
tablebi connect ga4

# channels without a connector still land in the same table
tablebi connect csv --file tiktok-ads-august.csv --platform tiktok_ads

Everything lands in a cross-channel table called facts, where the measures mean one thing regardless of origin: cost, impressions, clicks, conversions, conversion_value. They're sliceable by date, platform, account, campaign, ad_group, ad, channel and country. Underneath, the lossless per-platform raw tables stay available for when you need to see exactly what a source reported.

That normalization is the unification step. Once cost means cost everywhere, blended ROAS stops being a data-wrangling project and becomes one line of SQL.

Step 2: compute it — one query, not a pivot table

Metric definitions live as shared macros, so nobody re-derives the arithmetic per question. roas is defined as revenue over cost:

claude code → tablebi
# blended ROAS — everything, one number, last 28 days
tablebi ask "SELECT SUM(cost) AS spend,
             SUM(conversion_value) AS revenue,
             roas(SUM(conversion_value), SUM(cost)) AS blended_roas
             FROM facts
             WHERE date >= (SELECT MAX(date) FROM facts) - 27"

Note the date filter: anchor the window on MAX(date), never on today. Ad platforms and analytics tools each report on their own lag, and a window pinned to the calendar quietly includes days that haven't finished landing — which reads as a collapse in performance that never happened.

Now the comparison that makes the concept click. Same table, same period, grouped by platform:

claude code → tablebi
# per-platform ROAS — sum these and you'll overstate reality
tablebi ask "SELECT platform,
             SUM(cost) AS spend,
             SUM(conversion_value) AS revenue,
             roas(SUM(conversion_value), SUM(cost)) AS roas
             FROM facts
             WHERE date >= (SELECT MAX(date) FROM facts) - 27
             GROUP BY platform ORDER BY spend DESC"

Run both and the per-platform revenue column will typically total more than your real revenue. That gap is the double-counting, made visible. It's a genuinely useful thing to show a stakeholder who wants to know why the blended figure is lower than the one in the Meta dashboard.

Trend matters more than any single snapshot, since the level depends on your margins and your definitions:

claude code → tablebi
# weekly blended ROAS trend — is efficiency improving?
tablebi ask "SELECT DATE_TRUNC('week', date) AS wk,
             SUM(cost) AS spend,
             roas(SUM(conversion_value), SUM(cost)) AS blended_roas
             FROM facts
             WHERE date >= (SELECT MAX(date) FROM facts) - 90
             GROUP BY 1 ORDER BY 1"

The related macros are there for the same reason — cpa, cvr, aov, ctr, cpc, cpm — so a blended CPA is the same one-line move. And every answer carries a trust block with per-source freshness plus caveats, including an explicit one about GSC clicks and GA4 sessions being different populations. That's what stops an agent from confidently explaining a gap that is really just reporting lag.

A note on which revenue to use: pick one source of truth and stay with it. GA4's conversion_value is a reasonable default because it sees all traffic rather than one garden's slice. If your accounting system is the real authority, bring it in as CSV and blend against that instead — just don't switch mid-quarter and compare the results.

Step 3: pin it so it never needs rebuilding

A blended ROAS you recompute by hand each month is a blended ROAS that will eventually be skipped. Freeze it into a live dashboard instead:

claude code → tablebi
tablebi pin --title "Blended ROAS" \
  --widget "Weekly blended ROAS::line=SELECT DATE_TRUNC('week', date) AS wk, roas(SUM(conversion_value), SUM(cost)) AS roas FROM facts …" \
  --widget "Spend by platform=SELECT platform, SUM(cost) AS spend FROM facts …"
✓ published → https://dk.tablebi.com/d/dsh_…  (public, read-only, self-refreshing)

The result is a public read-only URL that recomputes as new spend and revenue sync in — the same mechanism behind this live example, which runs on real Search Console data:

How to actually use the number

Blended ROAS earns its keep in a few specific decisions, and misleads if you push it further.

  • Total budget direction. If blended ROAS holds steady while spend rises, the extra money is finding real demand. If it slides as spend rises, you've started paying more for the same customers — the clearest signal you're at the edge of your addressable audience.
  • Sanity-checking platform claims. When every platform reports a strong month and blended ROAS is flat, the platforms are competing for credit, not creating incremental revenue.
  • A target floor, not a target level. Set the floor from your own margins. There's no universal "good" blended ROAS, and any benchmark that doesn't know your gross margin doesn't know anything.

What it can't do: tell you which channel to cut. For that you need the narrower cuts — per-campaign spend with zero conversions, per-platform CPA trends — plus, ideally, a holdout test. Blended ROAS tells you the system's temperature; it doesn't name the broken part.

For the per-channel side of this work, we've covered Google Ads analysis from the CLI and Meta ads reporting separately, and the combined paid view in the PPC reporting guide. If the definitional discipline is what you're really after, define the metrics once is the piece to read next.

FAQ

What is blended ROAS?

Total revenue divided by total ad spend across every channel, computed once at the top rather than per platform. Because it never asks which ad deserves credit, it can't be inflated by two platforms claiming the same conversion.

Why don't platform ROAS figures add up to blended ROAS?

Each platform uses its own attribution model, lookback window and view-through rules, and sees only its own touchpoints. One buyer touched by two platforms can be counted twice, so summing platform-reported revenue overstates the total.

How do I calculate blended ROAS across Google Ads and Meta?

Land both in one table with a shared definition of cost and revenue, then divide the sums over the whole period rather than per platform. With TableBI it's one read-only SQL query against facts using the built-in roas macro.

Should I use blended ROAS or per-channel ROAS?

Both, for different jobs. Blended is the right number for total budget decisions. Per-channel is directional and good for finding obvious waste inside a channel — just never sum it across platforms and treat the result as truth.

Can I track blended ROAS without a spreadsheet?

Yes. Connect each platform once and it becomes a standing query instead of a monthly rebuild — then pin it as a live read-only URL that recomputes as new data syncs in.

Try it

Turn blended ROAS into a standing query — not a monthly spreadsheet.

terminal
npm i -g @tablebi/cli && tablebi install