Why your Analytics totals differ from Shopify reports
A line-by-line reconciliation of Llama Analytics against Shopify reports — what each number measures and why they will never match exactly.
If you put the Llama Analytics page next to a Shopify sales report and expect the numbers to match, they won't — and that is by design. They are not measuring the same thing. Llama measures the revenue your offers generated; Shopify measures your whole store. This page walks through every reason the two differ, with concrete examples, so you can reconcile any figure with confidence instead of opening a support ticket.
The short version: Total sales in Llama counts only the items shoppers bought through your offers, recorded at the moment the order is created or edited, in each order's own currency, bucketed by your shop timezone, and never reduced by refunds. A Shopify report counts whole orders, in your report currency, net of returns. Different scope, different timing, different basis — so different numbers.
1. Scope: Llama counts offered items, Shopify counts whole orders
Llama only attributes the specific line items a shopper added through one of your offers. Everything else in the cart — the products the shopper found on their own — is invisible to Total sales.
Because Llama's revenue is always a subset of the order, Total sales will always be less than or equal to Shopify's net sales for the same period. If they were equal, it would mean every single product sold in your store came from an offer.
Example. A shopper buys a $80 jacket on their own, then accepts a $20 beanie from your upsell. Shopify counts $100 of product. Llama's Total sales counts only the $20 beanie.
2. Only attributed orders appear — so order counts differ
An order is stored by Llama only if it contains at least one offered item. When an order arrives with no Llama-tagged line, it is discarded and never appears in Analytics, the orders list, or any chart.
That means Llama's order count is the count of orders that took an offer, not the count of all orders. Comparing "orders" in Llama to "orders" in a Shopify report is comparing two different populations.
Example. You had 500 orders yesterday; 90 of them included an upsell. Shopify reports 500 orders. The Llama orders list shows 90. Both are correct.
3. Discounts are handled differently by funnel
How an offered item is priced in Analytics depends on which funnel it came from. This is the single most common source of "Llama shows more (or less) than my Shopify line."
| Funnel type | Price recorded | Discounts |
|---|---|---|
| At-placement offers (in-cart, product page, BOGO, gift with purchase, in-checkout) | Final paid price per line | After discounts — the discount allocated to that line is subtracted |
| Post-purchase offers (accepted after checkout) | List price × quantity | No discount subtracted — the catalog price is used |
For at-placement offers, Llama records what the shopper actually paid: the line's original price minus the discount allocated to it. That generally ties out to the discounted line in Shopify.
For post-purchase offers, Llama records the item's list price at the quantity accepted — it does not subtract any post-purchase discount. So if a post-purchase offer was sold at a discount, Llama will show a higher number than the net line in Shopify.
Post-purchase discounts make Llama read high. If your post-purchase offer sells a $40 add-on at 25% off, the shopper pays $30 and Shopify's net line shows $30. Llama records the list price, $40. Your Total sales for that order will be $10 higher than the Shopify net figure. This is expected — post-purchase revenue is measured at list price, not at the discounted price.
See Applying discounts for how discounts attach to lines, and Post-purchase offers for how accepting an offer edits the order.
4. Subtotal basis: "Order Total" is Shopify's subtotal, not the grand total
The Order Total column in the Llama orders list is Shopify's order subtotal (subtotal_price). That value excludes shipping, taxes, and tips.
So even the column literally named "Order Total" is not the amount the customer was charged at checkout. It will be lower than the order's grand total in Shopify by exactly the shipping + tax + tip the order carried.
Example. An order shows a $120 grand total in Shopify: $100 of product, $10 shipping, $10 tax. Llama's Order Total for that row reads $100 — the subtotal only.
This is why Profit conversion (Total sales ÷ combined order subtotals) is computed against subtotals, not grand totals — keeping offered revenue and order value on the same basis.
5. Refunds, returns, cancellations, and edits don't shrink the numbers
Llama computes an order's metrics once, at the moment the order is created (orders/create) or edited by a post-purchase acceptance (orders/edited). There is no refund, return, or cancellation handler. Nothing decrements the figures after the fact.
That makes every Analytics figure gross of returns. A refunded, returned, or cancelled order keeps its full contribution to Total sales, Total sold offers, and the order count.
Refunds never reduce Total sales. If a $50 upsell is sold and then fully refunded tomorrow, Shopify's net sales drop by $50 but Llama's Total sales stays the same. Most Shopify sales reports are net of returns; Llama is gross of returns. Over a period with refunds, Llama will read higher than a net Shopify report for this reason alone.
The same applies to order edits that remove an offered item afterward — the original attribution stays. (A post-purchase edit that adds an item does update the figures, because that is exactly the orders/edited event Llama listens for.)
6. Timezone bucketing uses your shop timezone, not UTC
Llama buckets orders into days and months using your shop's timezone (Shopify's timezoneOffsetMinutes, cached for 12 hours), not UTC. Each order's chart day is its creation time shifted into your local offset.
A tool that buckets by UTC will place a late-evening order on a different calendar day than Llama does, shifting the totals in day and month charts even when the underlying orders are identical.
Late-night orders can land on a different day than a UTC report. An order placed at 11:00 PM local time in a UTC+3 shop is already 2:00 AM the next day in UTC. Llama charts it on the local day; a UTC-based report charts it on the following day. Your daily totals won't line up on those two dates even though the period total is the same. Because the offset is cached for 12 hours, a recent timezone change in Shopify can also take up to half a day to be reflected.
When you compare a single day, make sure both tools are using the same timezone.
7. Currency is tracked per-currency and never converted
Llama records each order in its own currency and reports each currency separately. Amounts are never converted between currencies. If your store takes orders in USD, EUR, and GBP, Analytics keeps three independent sets of totals, and the Currency filter switches between them.
Shopify reports often roll everything up into a single presentment or base currency. So a single Shopify "total sales" number can correspond to several separate Llama totals that should never be added together as-is.
Don't sum across currencies. Adding a €1,200 EUR total to a $1,500 USD total to "match" one Shopify figure is comparing unlike units. Reconcile one currency at a time using the Currency filter.
8. Timing and freshness: persisted history plus live "today"
Analytics is built from two layers:
- Persisted daily metrics — finalized totals for past days, written once per day.
- Real-time gap-fill — for orders newer than the last finalized day (effectively "today"), Llama computes the totals live from the raw orders on every request.
A just-placed order shows up through that live computation, so you don't need to refresh or sync manually. But the figures depend on Shopify delivering the orders/create webhook first, so there is a brief lag between when an order is placed and when it appears.
If an order you just saw in Shopify isn't in Analytics yet, wait a moment and reload. It is the webhook arriving, not a missing order — the live layer will show it as soon as Llama receives it.
9. Draft orders, POS, and anything created outside the storefront
Attribution depends on a hidden marker that the app writes onto the cart line when a shopper takes an offer. Orders where that marker can't be set are never attributed, including:
- Draft orders created in the Shopify admin.
- POS / in-person sales.
- Orders created through the API or any flow that bypasses the storefront cart.
These orders may carry the same products as your offers, but without the marker Llama treats them as ordinary orders and they don't appear in Analytics. A Shopify report that includes draft and POS sales will therefore count revenue and orders that Llama deliberately does not.
Reconciliation checklist
Use this table to map a symptom to its cause and the fastest place to check.
| Symptom | Likely cause | Where to look |
|---|---|---|
| Llama Total sales is lower than Shopify net sales | Llama counts only offered items, not whole orders (Scope) | Compare Campaign Amount vs Order Total in the orders list |
| Llama order count is far lower than Shopify's | Only orders with an offer are attributed | The orders list = orders that took an offer, not all orders |
| Llama shows more than a Shopify net line on one order | Post-purchase items recorded at list price, no discount subtracted | Check whether that order's offer was post-purchase and discounted |
| "Order Total" doesn't equal the order's charged amount | "Order Total" is the subtotal — excludes shipping, tax, tips | Add shipping/tax/tips back from the Shopify order |
| Period total is higher in Llama than in a net Shopify report | Refunds/returns/cancellations don't reduce Llama figures (gross-of-returns) | Check for refunded orders inside the date range |
| A specific day's total doesn't match | Day bucketed in shop timezone, not UTC | Confirm both tools use the same timezone; check late-night orders |
| One Shopify number ≠ Llama totals on a multi-currency store | Currencies are separate and never converted | Reconcile one currency at a time with the Currency filter |
| A just-placed order is missing | Brief webhook lag before it appears | Wait a moment and reload; the live layer will catch it |
| A POS or draft order isn't counted | No offer marker can be set outside the storefront | Expected — these are never attributed |
Frequently asked questions
Related pages
Filtering analytics: date ranges, funnel, campaign, currency
A behavior-accurate guide to the four Analytics filters, every date preset, and how the filters reset and combine with one another.
Timezones, currencies, and data freshness
The three behind-the-scenes mechanics — store timezone, per-currency totals, and the daily worker — that shape every number on Analytics.
