Home Blog Resume Contact Ask AI About Me
Home/Blog/Multi-Brand Klaviyo: Why Rollup Reports Never…
ArticleKlaviyoKlaviyoMulti-AccountReporting

Multi-Brand Klaviyo: Why Rollup Reports Never Line Up

12 min readBy Miloš Mitrović

If you run more than one Klaviyo account, the single number your CFO asks for, total email and SMS revenue across the portfolio, is the one number Klaviyo will not hand you without work. Every account keeps its own metrics, its own attribution window, its own currency and its own idea of what a revenue event is. Add those together and you get a figure that is internally inconsistent and indefensible the moment someone asks how it was calculated. The fix is not a better dashboard. It is a schema that every account is held to, and a reconciliation job that proves it is holding.

Key takeaways

  • Klaviyo's portfolio Home tab shows nothing until you create portfolio-level metrics and map an account metric for each linked account, one at a time.
  • Attribution windows are account settings. Klaviyo's defaults for accounts created after 9 October 2024 are 5 days for email, 5 days for SMS and 24 hours for push, so two brands can report different revenue from an identical flow.
  • Metric IDs are scoped to an account. Any API-driven rollup has to resolve canonical metric names to IDs separately in every account before it can query aggregates.
  • Cloning a flow into another account drops references to metrics, lists and channels that do not exist there, so the copy needs manual reassignment and then drifts on its own.
  • Klaviyo's mapped metrics have seven fixed slots, and benchmarks, predictive analytics, A/B results and CLV dashboards all read from them.
  • A portfolio metric can silently exclude an account. That toggle is the most common reason a rollup undercounts.

Why does the same flow report different revenue in two accounts?

Because the attribution window is an account setting rather than a flow setting, and almost nobody checks it after handover.

Klaviyo credits a conversion when a recipient opens or clicks a message and then converts inside that message's window. An Apple Mail Privacy Protection open counts. Across channels the credit goes to whichever message was opened or clicked most recently, as long as the conversion still falls inside that message's own window. Klaviyo's own worked example: an email open on day one, a push open on day two, a purchase on day three credits push, but a purchase on day four credits the email, because the 24-hour push window has closed while the 5-day email window is still open.

Now put two brands side by side. Brand A runs the 5-day email default. Brand B was set to a longer window by a previous agency that wanted a better-looking flow report. Brand B's share of revenue attributed to Klaviyo is structurally higher, and both numbers look plausible enough that no one questions either.

Record the window per channel per account in the schema document, set them identically, and treat the change date as a break in the series rather than a fact you can quietly forget. Any month that straddles the change is not comparable to the months on either side of it.

Why is the portfolio dashboard blank?

Because a portfolio inherits accounts, not metrics. You create each portfolio metric yourself and map it to an account-level metric in every linked account.

Klaviyo states it plainly: until you create a portfolio-level metric, the portfolio Home tab shows no data. Each portfolio metric is typed as Monetary Value or Event Count, and for any account without a compatible metric you set Include in metric? to Exclude. That exclusion is invisible in the resulting total. A five-brand rollup that quietly reports four brands is the failure I see most often, and it always reads as a soft month rather than a mapping gap.

Currency is the second trap. If linked accounts use different currencies, Klaviyo converts them into the currency you select for the report, and that selection does not change anything inside the linked accounts. So the portfolio figure carries a foreign-exchange conversion that none of the individual account figures do, and it will not tie back to a local finance report line for line.

Worth knowing before you plan the work: creating a portfolio needs Owner or Admin rights in a paid account, and Owner or Admin rights in every account you add. Portfolio users then see data from every account without needing a seat in each one, which is convenient and also the reason access review matters here more than in a single account.

What actually differs between two accounts that look identical?

Seven layers, and only one of them is visible on a dashboard. This is the checklist I run before writing a schema for a portfolio.

LayerWhat driftsWhere to checkWhat it breaks
Mapped metricsThe Revenue slot points at a native order metric in one account and a re-implemented custom metric in anotherAnalytics > Metrics > Edit mapped metricsBenchmarks, predictive analytics, A/B results, CLV dashboards, product analysis
Metric identitySame display name, different metric ID; or two near-duplicate metrics left behind by a re-platformGET /api/metricsEvery API report and every segment built on the wrong twin
Event propertiesA monetary value present in one account and absent in another, item arrays named differently, currency omittedA raw event payload, not the metric summaryDynamic blocks, conditional splits, any revenue sum
Attribution windowChannel defaults versus whatever the last owner setEmail, SMS and push settings pagesEvery cross-brand revenue comparison
CurrencyAccount currency versus the currency chosen for the portfolio reportPortfolio report settingsAny absolute revenue figure shown to finance
Object namingFlow, segment and list names that do not sort into the same order in two accountsFlow, list and segment indexesHuman error during audits and QA
Sending identityShared sending domain in one account, branded in another, and no split by traffic typeDomain settings per accountDeliverability, and reputation bleeding between brands

Audit this from raw settings and raw payloads, never from a summary screen. I approach it the same way I build a sourced marketing automation audit out of a single discovery call: pull the underlying configuration, quote it, and let the findings be checkable by the client.

Can you just clone the flow into the other accounts?

You can clone into as many as 100 accounts at once, and the clone will arrive incomplete on purpose.

Klaviyo's own guidance is that information may be left out of a cross-account clone because the two accounts have different channels, metrics and list names, and that you reassign those during the cloning process. So a clone is a starting point that a human finishes. That is fine once. It is not fine as an operating model, because cloning is a one-time event: edit the original next week and the copies do not move. Six accounts times a dozen flows is seventy-two objects drifting independently inside a quarter.

Keep one account as the reference build and clone only from it. Version the flow logic in a document that names the trigger metric, the filters, the delays, the conversion metric and the exit conditions. The document is the source of truth and the accounts are renderings of it. Then reconcile on a fixed cadence instead of when someone notices a number looks wrong.

Event property naming is where clones fail quietly. Anything personalised off cart or catalogue data assumes a property shape, so abandoned cart emails that rebuild each shopper's actual cart only survive a clone if the item array is named identically in the destination account.

What does a shared schema actually specify?

Naming, identity, and the handful of fields any cross-account report depends on. Everything else stays local to the brand.

  • Canonical metric names for the seven mapped slots, written exactly as they must appear: Revenue, Ordered Product, Cancelled Sales, Refunded Sales, Added to Cart, Started Checkout, Viewed Product, plus any custom conversion metric.
  • The event payload contract. Klaviyo's events API takes the metric name at data.attributes.metric.data.attributes.name and accepts value, value_currency, unique_id and time on the event. Make all four mandatory in your contract. unique_id is what stops a retried webhook from counting the same order twice, because a repeat of the same unique_id for the same profile and metric records only the first event.
  • A sort-stable prefix convention. Flows as LC-01 Welcome and LC-02 Browse Abandon, segments as SEG-ENG-90D. Trivial, and it removes a whole class of mistakes when someone works across six tabs.
  • The attribution window per channel, identical in every account, with the date it was last changed.
  • The conversion metric each report runs against, since that selector is chosen per report rather than inherited.
  • Sending domain per brand and per traffic type.
  • Who may create a metric. This is the clause that keeps the schema alive. One developer shipping a new event name is how a portfolio loses comparability, and it never shows up as an error.

Rebuilding six accounts onto one schema, the flows were the easy part. The argument that took real time was agreeing what the revenue event meant when one brand sold subscriptions, one sold wholesale through the same store, and refunds were handled differently in each.

How do you verify the schema is holding without opening six accounts?

A scheduled job against the Klaviyo API, landing in a table you control. Five steps, and none of them need a paid tool.

  1. Call GET /api/metrics in each account and store id, name, integration and created. The endpoint returns up to 200 results per page and filters only on integration.name or integration.category, so there is no name filter. Pull everything and match names in your own code.
  2. Diff each account's metric names against the schema. A new name is the alert, and created tells you when it appeared and therefore which release introduced it.
  3. For every canonical metric, query the metric aggregates endpoint. It requires metric_id, measurements and filter. Use sum_value for revenue and count or unique for volume, group with by on $flow or $message, set interval to day, and pin timezone to one IANA value for every account rather than accepting the UTC default in some places and a local setting in others.
  4. Respect the limits. That endpoint allows 3 requests per second in burst and 60 per minute steady, and returns 500 rows per page by default. A daily incremental across six accounts fits easily. A two-year backfill does not, so page it and sleep.
  5. Write the result to a warehouse table keyed by account, metric and date, and report from that table instead of from the portfolio dashboard.

The point of the table is that you can show your working. That is the same discipline behind a pipeline that traced every closed deal back to the call that started it: define the rule once, compute it where you can inspect it, and let the platform dashboards be a convenience rather than the record.

Where does deliverability break when brands share infrastructure?

At the sending domain, and at the list hygiene you inherit during consolidation.

A shared sending domain means your reputation is entangled with other senders on the same infrastructure. A branded sending domain means you are the only sender affecting it. Klaviyo lets you run separate branded domains for marketing, transactional and service traffic in the same account so each builds its own reputation, with one active domain per send type, and it expects a domain to have been registered for at least 30 days before it is used.

Google's requirements for senders of 5,000 or more messages a day to personal Gmail accounts have applied since 1 February 2024: SPF and DKIM, DMARC on the sending domain, a From header aligned with the SPF or DKIM domain, TLS in transit, valid forward and reverse DNS, and one-click unsubscribe on marketing and subscribed mail. Google's stated target is a spam rate below 0.10% in Postmaster Tools, and it tells senders never to reach 0.30%. In a portfolio those thresholds are measured against the domain, so one brand's aggressive acquisition can degrade placement for a sibling brand sharing the root domain.

Consolidation also means importing lists nobody has validated, often years old and gathered under different consent standards. Before any of it enters a warmed account, validate it. When I worked through verifying a one-million-contact database in-house, the useful finding was how much of a modern list SMTP-level checking simply cannot resolve, which changes how you tier risk instead of pretending you have a clean yes or no per address.

What should you refuse to standardise, and what should you watch?

Standardise identity and measurement. Leave judgement with the people closest to the market.

Creative direction, send cadence, promotional calendars and local compliance language belong to the regional team. Centralising those buys you consistency you cannot spend and loses you performance you can measure. What travels well is the schema underneath: metric names, event contracts, naming, windows, domains.

Do not attempt the migration mid-quarter. Freeze the schema, migrate account by account, then re-baseline reporting from the first full period after the last account lands. A half-migrated portfolio produces numbers that are wrong in a new way each week.

Three things to keep watching after launch. First, the Include in metric? exclusions, because every new account added to a portfolio metric is an opportunity to leave one out. Second, duplicate metrics after a re-platform, since a reinstall or a headless rebuild can create a second order-style metric while existing segments keep pointing at the retired one. Third, the metric creation clause, which decays the moment a developer ships without reading it.

On cross-brand identity resolution: it links profiles across accounts using deterministic matching that starts with email, assigns an organisation-level identifier, keeps brand profiles, events and catalogue data isolated rather than copying them between accounts, refreshes matches on a target of roughly 24 hours, and gives you audit logs, manual unlinking and opt-out at individual or organisation level. It is genuinely useful for understanding who shops more than one brand. It does not make two accounts' metrics comparable, and Klaviyo positions it at enterprise and multi-brand customers, so treat it as a layer on top of a working schema and never as a substitute for one.

If I had to pick one principle: I would rather run one slightly imperfect revenue definition applied identically in every account than seven precise definitions that cannot be added together. Comparability beats accuracy in a portfolio, because you can correct a known bias in a single place and you cannot correct seven unknown ones.

Sources

M
Miloš Mitrović
Revenue Operations & AI Automation

Have a question or a project?

Whether it is about this post or a system you want built, I'm happy to talk.

Get in touch

404

Post not found. It may have been moved or the link is incorrect.

← Back to the blog
Ask AI About Me
Clicking an assistant copies the prompt and opens it: ready to run in ChatGPT, Perplexity, and Grok; in Claude, Gemini, or Copilot press Ctrl+V (Cmd+V on Mac) to paste. Use Copy prompt for any other AI. The assistant reads my site, so it needs web access.
Summarize with AI
ChatGPT, Perplexity, and Grok open with the prompt ready to run. Claude, Gemini, and Copilot open a chat with the prompt copied; press Ctrl+V (Cmd+V on Mac) to paste. The full text is included, so it works even without web access.