Skip to content

Revenue accounting

Kreel and Shopify can show different revenue numbers for the same period, even from the same store data. This page explains why, walks through a worked example, and covers the settings that change what counts as revenue.

Kreel’s revenue is state-based. It reads each order’s current total, the same number you’d see if you opened that order in Shopify admin today. That total already reflects any refund or edit applied to the order, no matter when the refund happened.

Shopify’s own “Total Sales” report is event-based (cash-flow). It recognizes revenue on the day an order was placed, and recognizes a refund separately, on the day the refund happened.

The two approaches agree almost all the time. They diverge in exactly one situation: a refund that lands inside the period you’re looking at, for an order that was created before that period started. Kreel calls this a cross-period refund, and it’s the single most common reason a Kreel revenue number won’t match Shopify’s at first glance.

Say a brand has two orders:

  • Order A: created March 30, total €50. Fully refunded April 3.
  • Order B: created April 10, total €80. Not refunded.

If you ask “what was our revenue for April” and only count orders created in April, you get €80 (Order B). That misses Order A entirely, even though something real happened to it in April: a €50 refund.

Shopify’s Total Sales report for April recognizes that refund as its own event: +€80 (Order B) minus €50 (Order A’s refund) = €30.

Kreel arrives at the same €30 a different way. It takes the gross total of orders created in April (€80) and subtracts cross-period refunds that landed in April on orders created before April (€50), for a net of €30. An implementation that only summed “orders created in the window” would have reported €80 for April, overstating revenue by the full refund. This exact correction has closed real discrepancies of several thousand currency units a month for brands with a steady stream of returns.

Kreel’s headline revenue and order counts include voided and cancelled orders, matching Shopify’s own Total Sales report. A voided order’s current total is already close to zero, so it adds almost nothing to revenue, but it still needs to appear in your order count for that count to match Shopify’s.

Trend charts and cohorts use a different, gross number

Section titled “Trend charts and cohorts use a different, gross number”

Kreel’s headline revenue, and the number MCP tools return, is always the refund-correct net figure above, computed by one shared module and reused everywhere. The tables behind fast trend charts and cohort views store gross Shopify revenue instead, without the cross-period refund correction, and they exclude voided and cancelled orders (the headline includes them).

This is intentional, not a bug. The cross-period correction depends on where a reporting window starts, which isn’t known when a per-day chart row is written, so it can’t be baked into a daily number and summed later without double-subtracting refunds. These cached tables exist for fast trend and cohort answers, not for reconciling digit-for-digit against Shopify’s own reports.

If you’re reconciling against Shopify, use the headline revenue number: dashboard Revenue overview, the MCP get_performance tool, or the REST revenue endpoints. Don’t expect a value read off a trend chart to match it exactly.

Not every brand means the same thing by “revenue.” Some think in tax-inclusive terms, some don’t; some count shipping charged to the customer as revenue, some don’t. Kreel makes this explicit with a per-brand Revenue basis setting, on the Settings page: two checkboxes, Include tax and Include shipping.

The default is both included, matching “whatever the customer paid” and Shopify’s own Total Sales figure.

Revenue basis is a lens, not a stored value. The underlying data keeps tax, shipping, merchandise, and refunds as separate components; every surface (dashboard, REST API, MCP, query DSL) composes the basis you’ve chosen at read time. That means changing the setting restates every historical number, on every surface, immediately. It also means any breakdown you look at, by country or by product, always adds back up to the headline, whichever basis you’ve chosen.

Revenue on individual products and line items is net of discounts: the amount actually paid for that line, not its list price. Kreel also tracks the pre-discount gross revenue (quantity times list price) and the discount amount (gross minus net) separately, so you can see your discount rate without losing the underlying list-price figure.

This matters most for free items and gifts-with-purchase. A line that’s fully discounted, so €0 was paid for it, shows €0 net revenue, correctly, even though it still has a nonzero gross revenue and still counts as a unit shipped. If a product’s net revenue looks lower than you’d expect from its list price, check whether it’s carrying more discount than usual before assuming something’s wrong with the sync.

Two more per-brand settings reshape revenue figures without anything changing in Shopify itself:

  • The Sales channels setting on the Settings page decides which of your store’s sales channels (Online Store, Point of Sale, Draft Orders, and any others Shopify reports) count toward Shopify revenue figures. The default includes every channel, matching Shopify admin totals.
  • Every “last N days” window is a whole calendar-day span in your brand’s reporting timezone, ending yesterday, never including today’s partial data. See Dates and comparisons for how date windows and period-over-period comparisons work.

For metric formulas like ROAS, MER, and AOV, see the metrics glossary.

If a number still doesn’t reconcile after checking revenue basis, sales channel filters, and voided orders, email support@kreel.ai with the brand, the date range, and the number you’re comparing against.