Home Blog Resume Contact Ask AI About Me
Home/Blog/How to Reconcile Klaviyo Revenue With Shopify…
How toKlaviyoKlaviyoShopifyAttribution

How to Reconcile Klaviyo Revenue With Shopify Numbers

8 min readBy Miloš Mitrović

When Klaviyo and Shopify report different revenue for the same period, neither tool is broken. They are counting different things, in different time zones, in different currencies, with different rules for refunds and attribution. The one-line answer: stop comparing Klaviyo's attributed revenue to Shopify total sales, put both tools on the same date range, time zone and currency, then walk Klaviyo's Placed Order total down to Shopify net sales by subtracting the items Klaviyo never nets out. This guide gives you the exact reconciliation table and the settings to check so the gap becomes explainable line by line instead of a mystery.

Key takeaways

  • Short answer: reconcile by comparing Klaviyo's Placed Order metric total (all orders) against Shopify net sales for the identical window, then subtract Klaviyo's Refunded Order and Cancelled Order values, because Klaviyo does not remove them and Shopify does.
  • The most common error is comparing Klaviyo attributed revenue (credit given to emails and SMS) against Shopify total sales (every order). Those two numbers should never match.
  • Klaviyo uses last-touch attribution with a 5 day email window by default, so channel-level revenue shifts when you change that window, but the Placed Order total does not.
  • Klaviyo does not convert currency in standard reports, so a multi-currency store sums presentment-currency values as if they were one currency.
  • Klaviyo reports in the account time zone and Shopify in the store time zone; a mismatch moves orders across the day boundary at the start and end of the range.

What you need

  • Klaviyo access with the analytics permission, plus the ability to view Settings > Attribution and the account time zone and currency.
  • Shopify admin access to Analytics > Reports > Finances (the Finances summary and the Sales report). On Shopify, finance reports need the Reports permission.
  • The Shopify integration already installed in Klaviyo, sending the Placed Order, Refunded Order and Cancelled Order metrics.
  • A spreadsheet for the reconciliation table, and one agreed date range to test against (a closed calendar month is easiest).

Build the reconciliation table that settles the disagreement

  1. Pick the comparable Klaviyo number first. In Klaviyo, open Analytics > Metrics > Placed Order and read the summed value for your date range. This is every order that reached Klaviyo, not the smaller "attributed revenue" figure on the dashboard. Comparing attributed revenue to any Shopify sales total is the single most frequent cause of a phantom gap.
  2. Pull the matching Shopify number. In Shopify, open Analytics > Reports > Finances and record Net sales, Gross sales, Discounts, Returns, Shipping and Taxes for the same dates. Note which Shopify figure you are targeting, because the definitions differ sharply.
    Shopify Gross sales = product price x quantity (no discounts, tax, shipping, returns)
    Shopify Net sales   = gross sales - discounts - returns   (no tax, no shipping)
    Shopify Total sales = gross sales - discounts - returns + taxes + shipping + fees
  3. Align the time zone and the date range. Confirm the Klaviyo account time zone under Settings and the Shopify store time zone under Settings > General. If they differ, either match them or shift one report's boundaries so both cover the same wall-clock window. Orders near midnight on the first and last day are the ones that move.
  4. Confirm the currency. If the store sells in more than one currency, Klaviyo's standard reports do not convert; every Placed Order value is summed as a raw number under the account currency symbol. Rebuild the Klaviyo figure filtered to a single currency, or reconcile one currency at a time.
  5. Write the waterfall. Start from the Klaviyo Placed Order total and subtract the items Klaviyo carries that Shopify has already removed. Klaviyo's Placed Order value is (sub-total + shipping) - discounts, so it excludes tax and never nets out returns or cancellations.
    Klaviyo Placed Order total (metric sum, account TZ, single currency)
      - Klaviyo Refunded Order value      # Klaviyo keeps these in; Shopify removes them
      - Klaviyo Cancelled Order value     # same treatment
      - shipping                          # if your target is Net sales, which excludes shipping
      ~= Shopify Net sales (same range, store TZ, same currency)
  6. Read the residual. Whatever is left after those subtractions is your real discrepancy. If it is under roughly one percent of revenue it is almost always timing and partial refunds; if it is larger, work the causes table below in order.

If you prefer to pull the Klaviyo figure programmatically rather than from the dashboard, the Query Metric Aggregates endpoint returns the summed Placed Order value for a window, which is useful when you want an exact time zone and currency filter that the UI does not expose:

POST https://a.klaviyo.com/api/metric-aggregates/
# body (representative): sum of $value for the Placed Order metric_id,
# interval "day", an explicit "timezone", and a datetime >= / < filter
# so the API window matches the Shopify report window exactly.

The six causes, in the order they move the number

Each cause pushes the gap in a predictable direction. The reason two tools that see the same orders still disagree is that revenue is a set of choices, and the two platforms made different ones. HubSpot and Google Ads produce the same class of standoff, which is why the discipline of reconciling attribution across two systems that count differently transfers directly.

CauseEffect on the gapWhere to checkHow to correct it in the table
Attributed revenue vs Placed Order totalKlaviyo looks far lower than ShopifyKlaviyo dashboard "attributed" tile vs the Placed Order metric sumCompare the Placed Order total, never the attributed figure, to a Shopify sales number
Refunds and cancellationsKlaviyo higher than ShopifyKlaviyo Refunded Order and Cancelled Order metrics; Shopify ReturnsSubtract Klaviyo Refunded and Cancelled order values from the Placed Order total
Attribution window and modelShifts channel revenue only, not the totalKlaviyo Settings > AttributionIgnore for the total; matters when reconciling per-channel attributed revenue
Currency not convertedEither direction, often largeShopify Markets currencies; Klaviyo currency handlingReconcile one currency at a time or rebuild in shop currency
Time zone mismatchSmall, at the edges of the rangeKlaviyo account time zone vs Shopify store time zoneAlign both, or shift one report's day boundaries
Test and draft ordersUsually inflates one sideShopify test (Bogus Gateway) and draft ordersExclude test orders; count draft orders only once completed

Why attribution settings move channel revenue but not the total

Klaviyo attributes a conversion when a recipient interacts with a message and then places an order inside the lookback window. Per Klaviyo's guide to message attribution and its default windows, new accounts use last-touch attribution with a 5 day window for email opens and clicks, and 5 day clicks with a 1 day open window for SMS. Widening or narrowing that window under the Attribution settings, where the Compare model tool previews the change before you apply it, moves how much revenue each channel is credited with, and Klaviyo recomputes historically within about 36 hours. It does not change how many orders exist, so your Placed Order total and your Shopify sales figure are untouched. This is why attribution debates belong in the channel report, not in the store-total reconciliation.

Why refunds create a persistent one-directional gap

Shopify's reports remove returns: net sales equals gross sales minus discounts and returns. Klaviyo does the opposite. According to the Klaviyo Shopify data reference, Shopify subtracts cancelled and refunded orders from revenue while Klaviyo does not, and Klaviyo only receives an event for fully refunded orders, not partial ones. So Klaviyo's Placed Order total runs structurally higher than Shopify net sales, by the value of refunds and cancellations, and partial refunds never appear in Klaviyo at all. That last point is the usual source of a residual that will not close: a store with many partial refunds cannot fully reconcile from Klaviyo metrics alone and must take the partial-refund total from Shopify.

Why multi-currency and time zone quietly break the match

Klaviyo does not convert currency in standard analytics; the revenue value arrives as a plain number and the currency symbol is set at the account level, so a store selling in USD, EUR and GBP has all three summed together with no exchange applied. Benchmarks convert to USD, but your day-to-day reports do not. Time zone is smaller but real: Klaviyo reports in the account time zone you set in Klaviyo, message attribution stamps interactions to the send date in that zone, and Shopify reports in the store time zone. When they differ, orders around midnight shift into the neighbouring day, which shows up as a gap that appears and disappears as you move the range by one day.

Troubleshooting: what a residual is telling you

  • Klaviyo far below Shopify. You are almost certainly reading attributed revenue, not the Placed Order metric total. Switch to the metric.
  • Klaviyo above Shopify by a stable amount. Refunds and cancellations. Subtract the Klaviyo Refunded and Cancelled Order values, then check for partial refunds that only exist in Shopify.
  • Gap changes when you nudge the date range by a day. Time zone mismatch between the two accounts.
  • Gap is a strange multiple or is wildly off. Multiple currencies summed without conversion. Reconcile one currency at a time.
  • A handful of orders exist in one tool only. Test orders, draft orders, or events lost in the sync. Missing Placed Order events are their own failure mode; see the blind spots in the Shopify to Klaviyo event sync when orders reach Shopify but never reach Klaviyo.

How to verify it worked

The reconciliation is correct when the residual is explained, not when it is zero. Confirm three things. First, your adjusted Klaviyo figure (Placed Order total minus Refunded Order value minus Cancelled Order value, minus shipping if you targeted net sales) lands within about one percent of Shopify net sales for the same window, single currency, matched time zone. Second, the remaining difference has a named source you can point to, most often partial refunds that live only in Shopify. Third, the relationship holds on a second, independent month; a match that only works for one period is usually a coincidence of offsetting errors. Once a closed month reconciles to a documented residual, the same table works every month, and any month that suddenly fails to reconcile is a real signal that the integration, a currency, or the time zone changed.

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.