Guide

Cross-platform ad reporting: one source of truth across Meta, Google, TikTok and Snap

A practical, no-fluff guide for performance teams and agencies.

Cross-platform reporting fails at a vocabulary level before it fails anywhere else: "conversions," "results" and even "spend date" mean different things on each platform. One source of truth isn't a bigger export — it's a normalization layer: an explicit mapping from each platform's dialect to your columns, applied identically every period. This guide builds that layer.

Why naive combination lies

Sum the platforms' claimed conversions and you double-count (each claims the overlapping user). Compare CACs computed under different attribution settings and the "winner" is a settings artifact. Mix account timezones and the week's edges smear. None of these are exotic — they're the default outcome of pasting four exports side by side.

The normalization map

One table, owned like code:

Your column Meta Google TikTok Snap Source of truth
Spend spend cost_micros ÷ 1e6 spend spend platform
Results MMP event, deduplicated
Platform conv. actions[purchase], 7dc/1dv conversions (action-scoped) conversions swipe + view (labeled) platform (claim)
CPM/CPC computed computed computed computed derived

Two rules carry most of the value: Results come from the MMP (one referee, no double-counting), and platform conversions survive as labeled claims for reconciliation — never summed, never silently substituted.

Period and currency discipline

One period definition — last full ISO week — resolved per source in its timezone (Meta's ad account, AppsFlyer's app) and landed in the report's. One FX source for multi-currency accounts, applied at pull time, noted in the header. Trailing windows re-pulled so Meta's impression-date credit and Google's modeled restatements converge instead of haunting WoW deltas.

The one-block output

Per period, one normalized block — channel rows, identical columns — appended under the current month:

Channel Spend Results CAC ROAS Platform conv. Var.
Meta $13,900 1,012 $13.74 1.9 1,388 +37%
Google $17,800 998 $17.84 1.6 1,205 +21%
TikTok $9,400 571 $16.46 1.7 833 +46%
Snap $7,100 376 $18.88 1.4 512 +36%

The test of the layer: a new analyst reads any row without asking which platform's dialect it's in.

Adding a channel later

A good normalization layer makes channel five a map extension, not a report redesign: add the column mappings, add the pull, the block format doesn't change. (This is also the argument against per-platform tabs — every new channel forks the truth again.)

QA checklist

  • ✓ The map reviewed by someone who didn't write it
  • ✓ Spend tied out per platform against its UI, same range, same timezone
  • ✓ One CAC recomputed by hand from the row's inputs
  • ✓ Variance within each channel's baseline (a jump is a finding, not noise)

When not to normalize

Single-channel accounts. The layer earns its keep the day channels start competing for budget on these numbers.

How Opera runs it

Cross-platform ad reporting stores your map once and applies it every run: pinned pulls, MMP-denominated results, labeled claims, reconciliation, one appended block. The multi-platform integration is the wiring.

"Build this week's cross-channel report: spend, results, CAC and ROAS by platform — reconciled against AppsFlyer."

See this running on your own reports.A 45-minute workflow audit maps your current process and shows exactly what Opera automates — step by step.

Frequently asked questions

Can't a BI tool do the normalization?
It can display normalized data someone modeled. The map still has to exist, the pulls still need pinned settings, and the client-facing Sheet still needs maintaining — the layer is the work, wherever it runs.
Which platform's attribution setting should the comparison use?
None of them for outcomes — that's the MMP's job. Pin each platform's setting for its *claims* column so the variance series is stable.
How do we handle a platform with no MMP coverage?
Label its results column as platform-claimed, exclude it from blended CAC's denominator or footnote it, and reconcile what you can. Honest labels beat false precision.

Watch Opera run a real workflow, end to end.

Three minutes: a plain-language request, a Sheet schema read, an AppsFlyer pull, a previewed append, a Slack summary — then a paused campaign launch.