Home Blog Resume Contact Ask AI About Me
Home/Blog/How to Design a Klaviyo Schema for Multi-Acco…
How toKlaviyoKlaviyoMulti-AccountReporting

How to Design a Klaviyo Schema for Multi-Account Reporting

9 min readBy Miloš Mitrović

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_id at report time from the metric name.
  • Metric IDs are account-specific. The Get Metrics endpoint returns each metric's id, name and integration, 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 revision header.
  • 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

  1. Inventory the metrics in each account. Call the Get Metrics endpoint once per account. The response gives you each metric's id, name and integration, which is the raw material for your registry, as documented in the Klaviyo Metrics API overview.
    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"
    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.
  2. 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_id in each account. Names are case sensitive, so Placed Order and placed order are 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
  3. Reconcile custom metric names. Native integration metrics like Placed Order already match when every account uses the same integration. Custom events are where drift lives: one account sends Quiz Completed, another sends submitted_quiz. Pick one canonical name and change the sending code in every account so the event name is byte-for-byte identical.
  4. 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 product object 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]" } } }
        }
      }
    }
  5. 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, Source or anything with a $ prefix such as $timezone. Prefix your own with a namespace, for example attr_loyalty_tier, and use identical casing everywhere.
  6. 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_id per call and can group by flow, campaign or list.
    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"
        }
      }
    }
    Run this per account with that account's resolved ID, then union the results keyed by the canonical name.
  7. 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.

ObjectIdentifier the API usesPortable across accountsWhat to standardize
Metricmetric_idNoThe metric name and casing
Event propertyProperty keyYes, if you name it the sameFlat root-level key, one convention
Profile propertyProperty keyYes, if you name it the sameNamespaced key, no reserved collisions
List or segmentlist_id / segment idNoA naming pattern plus a per-account ID map
Flow or templateFlow / template idNoRebuild 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.

  1. 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.
  2. Call Get Metrics per account and confirm exactly one metric matches each canonical name. Two matches means a duplicate integration is inflating the rollup.
  3. 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.

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.