If you run one brand across several Klaviyo accounts, the thing that breaks cross-account reporting is not the data, it is the identifiers. A metric called Placed Order has a different metric_id in every account, so a report or a cloned flow that references an ID in account A means nothing in account B. The one-line answer: standardize the names of metrics and properties across every account, keep a per-account name to ID lookup, and query each account by name, not by a hard-coded ID.
Key takeaways
- The short answer: build a canonical naming registry for metrics, event properties and profile properties, then resolve each account's
metric_idat report time from the metric name. - Metric IDs are account-specific. The Get Metrics endpoint returns each metric's
id,nameandintegration, and those IDs never match between accounts. - Cloning a flow, segment or template into another account drops any reference that does not exist there, because the destination account has its own IDs.
- A custom profile property that shares a name with a default Klaviyo property cannot be used in segmentation, so your naming convention has to avoid reserved names.
- Custom event properties must sit at the root of the event payload, or they will not appear in the segment builder or flow filters in any account.
- Reconcile names once, enforce them on every new account before a single flow is built, and version the registry.
What you need
- Owner or Admin access to every Klaviyo account in the group, or at least an API key per account with read access to metrics and profiles.
- A private API key per account (created under Settings, API keys) to call the REST API with the
revisionheader. - A place to hold the registry and the rollup: a warehouse table, a Google Sheet, or a small script. No specific plan tier is required.
- Agreement from whoever builds flows in each account that they will follow the naming convention. This is a governance problem before it is a technical one.
Standardize the schema so one query answers across every account
- Inventory the metrics in each account. Call the Get Metrics endpoint once per account. The response gives you each metric's
id,nameandintegration, which is the raw material for your registry, as documented in the Klaviyo Metrics API overview.
Repeat with each account's key and keep the full list. You will find the same event carries different IDs and, often, slightly different names.curl -s https://a.klaviyo.com/api/metrics/ \ -H "Authorization: Klaviyo-API-Key pk_ACCOUNT_A_KEY" \ -H "revision: 2024-10-15" \ -H "accept: application/json" - Freeze a canonical name registry. Create a table with one row per concept and columns for the canonical metric name, the source integration, and the exact
metric_idin each account. Names are case sensitive, soPlaced Orderandplaced orderare two different metrics. Decide the exact casing once.concept | canonical_name | integration | id_acct_A | id_acct_B placed_order | Placed Order | Shopify | UMBpTr | RxQ92K started_checkout | Started Checkout | Shopify | VnT4aa | Lp88de submitted_quiz | Submitted Quiz | API | Wq10zz | Yz44mm - Reconcile custom metric names. Native integration metrics like
Placed Orderalready match when every account uses the same integration. Custom events are where drift lives: one account sendsQuiz Completed, another sendssubmitted_quiz. Pick one canonical name and change the sending code in every account so the event name is byte-for-byte identical. - Fix event properties at the root of the payload. Klaviyo only surfaces properties that sit at the top level of the event, so a value nested inside a
productobject will not appear in segments or flow filters. Klaviyo's custom integration FAQs spell this out. Send flat keys with a consistent convention across all accounts.{ "data": { "type": "event", "attributes": { "metric": { "data": { "type": "metric", "attributes": { "name": "Submitted Quiz" } } }, "properties": { "quiz_result_skin_type": "combination", "quiz_variant": "v3" }, "profile": { "data": { "type": "profile", "attributes": { "email": "[email protected]" } } } } } } - Define custom profile properties that do not collide with reserved names. A custom property that shares a name with a default Klaviyo property cannot be segmented on, per the Klaviyo profile properties reference. Avoid names like
First Name,Title,Sourceor anything with a$prefix such as$timezone. Prefix your own with a namespace, for exampleattr_loyalty_tier, and use identical casing everywhere. - Resolve IDs at report time, never hard-code them. To pull one metric across accounts, look the name up in each account's live metric list, then query that account's ID. The Query Metric Aggregates endpoint takes one
metric_idper call and can group by flow, campaign or list.
Run this per account with that account's resolved ID, then union the results keyed by the canonical name.POST https://a.klaviyo.com/api/metric-aggregates/ { "data": { "type": "metric-aggregate", "attributes": { "metric_id": "RxQ92K", "measurements": ["sum_value", "count"], "interval": "month", "filter": ["greater-or-equal(datetime,2026-07-01T00:00:00)", "less-than(datetime,2026-08-01T00:00:00)"], "timezone": "UTC" } } } - Enforce the registry on every new account. Before any flow is built in a new account, load the canonical custom metric names and property keys. Treating this as a checklist step is what keeps the group reportable a year later.
Why names are the only thing that travels
Every Klaviyo object you reference by ID is minted inside a single account. Copy work between accounts and those references have nothing to point at. This is why Klaviyo's own guidance on cloning flows, segments and templates notes that details are left out of the transfer when the destination account has different metrics, lists or channels. The clone keeps the structure and loses the wiring.
The identifiers behave differently, so your registry has to standardize the portable field and resolve the non-portable one on the fly.
| Object | Identifier the API uses | Portable across accounts | What to standardize |
|---|---|---|---|
| Metric | metric_id | No | The metric name and casing |
| Event property | Property key | Yes, if you name it the same | Flat root-level key, one convention |
| Profile property | Property key | Yes, if you name it the same | Namespaced key, no reserved collisions |
| List or segment | list_id / segment id | No | A naming pattern plus a per-account ID map |
| Flow or template | Flow / template id | No | Rebuild and re-map triggers after cloning |
If you also run separate sending infrastructure per brand, the same discipline applies to the reputation layer, which is covered in sending domain models for multi-brand Klaviyo. And when the group-level numbers still refuse to add up after you standardize names, the usual causes are laid out in why multi-brand rollup reports never line up.
Troubleshooting
- A metric shows zero in one account. Almost always a name or casing mismatch. Pull Get Metrics for that account and compare the exact string, including trailing spaces, against your canonical name.
- A segment is empty with no error. The custom property it filters on probably collides with a reserved Klaviyo property, or the casing of the property value drifted between accounts. Check the property in the segment builder and confirm it is your namespaced key.
- A cloned flow will not turn on. Its trigger metric does not exist in the destination account. Re-select the metric from that account's list. You cannot change the trigger type during a clone, only which metric of the same type fires it.
- A rollup double counts. One account has two metrics with the same display name from two integrations, so both resolve to that canonical name. Keep the integration in your registry key, not just the name.
How to verify it worked
Three checks prove the schema holds, and vendors rarely tell you to run them.
- For one canonical metric, resolve the ID in every account and run Query Metric Aggregates for the same date window. Every account that should have activity returns a non-zero
count. A zero where you expect volume means the name did not reconcile. - Call Get Metrics per account and confirm exactly one metric matches each canonical name. Two matches means a duplicate integration is inflating the rollup.
- Build the same segment definition in two accounts and confirm both return a non-zero membership count. A zero on one side flags a property name or casing collision before it reaches a live send.