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.
| Layer | What drifts | Where to check | What it breaks |
|---|---|---|---|
| Mapped metrics | The Revenue slot points at a native order metric in one account and a re-implemented custom metric in another | Analytics > Metrics > Edit mapped metrics | Benchmarks, predictive analytics, A/B results, CLV dashboards, product analysis |
| Metric identity | Same display name, different metric ID; or two near-duplicate metrics left behind by a re-platform | GET /api/metrics | Every API report and every segment built on the wrong twin |
| Event properties | A monetary value present in one account and absent in another, item arrays named differently, currency omitted | A raw event payload, not the metric summary | Dynamic blocks, conditional splits, any revenue sum |
| Attribution window | Channel defaults versus whatever the last owner set | Email, SMS and push settings pages | Every cross-brand revenue comparison |
| Currency | Account currency versus the currency chosen for the portfolio report | Portfolio report settings | Any absolute revenue figure shown to finance |
| Object naming | Flow, segment and list names that do not sort into the same order in two accounts | Flow, list and segment indexes | Human error during audits and QA |
| Sending identity | Shared sending domain in one account, branded in another, and no split by traffic type | Domain settings per account | Deliverability, 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.nameand acceptsvalue,value_currency,unique_idandtimeon the event. Make all four mandatory in your contract.unique_idis what stops a retried webhook from counting the same order twice, because a repeat of the sameunique_idfor the same profile and metric records only the first event. - A sort-stable prefix convention. Flows as
LC-01 WelcomeandLC-02 Browse Abandon, segments asSEG-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.
- Call
GET /api/metricsin each account and storeid,name,integrationandcreated. The endpoint returns up to 200 results per page and filters only onintegration.nameorintegration.category, so there is no name filter. Pull everything and match names in your own code. - Diff each account's metric names against the schema. A new name is the alert, and
createdtells you when it appeared and therefore which release introduced it. - For every canonical metric, query the metric aggregates endpoint. It requires
metric_id,measurementsandfilter. Usesum_valuefor revenue andcountoruniquefor volume, group withbyon$flowor$message, setintervaltoday, and pintimezoneto one IANA value for every account rather than accepting the UTC default in some places and a local setting in others. - 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.
- 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
- Klaviyo Help Center: Getting started with portfolios
- Klaviyo Help Center: Understanding portfolio reporting
- Klaviyo Help Center: How to use account-level mapped metrics
- Klaviyo Help Center: Understanding message conversion tracking
- Klaviyo Help Center: How to clone forms, flows, segments, campaigns, and templates
- Klaviyo Help Center: Cross-brand identity resolution
- Klaviyo Help Center: Understanding branded vs. shared sending domains
- Klaviyo Developers: Get Metrics
- Klaviyo Developers: Query Metric Aggregates
- Klaviyo Developers: Create Event
- Google: Email sender guidelines