Insights
Analytics
Four tiles, a chart of any one metric, a discount type filter and a By day table, plus what the storefront pixel collects and where the exact revenue is.
Opening the Analytics page
Open the app
Open xDiscount from Apps in your Shopify admin.
Go to Analytics
Click Analytics in the app’s sidebar.
Pick a range
Use the date button at the top. It is labelled with the range you are looking at, Last 7 days when the page first opens, and clicking it lists Today, Last 7 days, Last 30 days and Last 90 days, with a custom range below the divider.
Narrow the metrics if you want to
Beside the date button, the All metrics chip narrows what the chart can plot and which columns the By day table shows. Click it for a small card of three choices: All metrics, Storefront metrics (approximate) for product views, added to cart and checkouts seen, or Shopify metrics (exact) for discounted orders and revenue. The four tiles never narrow, and your choice is remembered on this browser.
To set a custom range, type a From and a To date as YYYY-MM-DD and click Apply. Cancel, or Escape, discards dates you typed but did not apply, so the button never labels a range that was not actually fetched. Reversed dates are swapped, not rejected. Days are UTC calendar days, the same way they are counted everywhere else in the app.
The range lives in the page address, so a reload or a shared link lands on the same numbers, and it is the same range the Performance strip on Home uses. Moving between the two screens does not change it. The date button is greyed out while numbers are loading, and picking a range re-reads everything on the page together, so tiles, chart and table always cover the same window. While a new range loads, what is already on screen stays put and dims slightly, with a small spinner beside the date button.
There is no per-discount breakdown. What you get is four tiles, a chart of any one of them and a day-by-day table.
The Analytics page, the storefront pixel and the campaign order field are included on every plan, Free included. Nothing on this screen is held back for an upgrade.
How far back the history goes
History reaches back 250 days at most. If a custom range starts earlier than that, the page shows what it has and an information banner says where the range really starts: “History goes back 250 days, so this range starts on …”
The four tiles
The first row of the page is four plain cards, always in this order: the metric’s name, and the figure under it. Money first, then orders, then the two ratios.
| Tile | What it counts | Where it comes from | Exact? |
|---|---|---|---|
| Revenue | The checkout total of discounted checkouts the pixel saw, in your store’s currency | Storefront pixel | Approximate |
| Discounted orders | Orders where xDiscount actually reduced the price | Shopify’s own order webhook | Exact |
| Average order value | Revenue divided by discounted orders | Derived from the two above | Not applicable |
| Conversion rate | Discounted orders divided by product views | Derived | Not applicable |
The shopper’s journey, Product views, Added to cart, Checkouts started and Checkouts seen, is on the page too, as the chart’s metric choices and as columns of the By day table below. A few things are worth knowing about how those are counted:
- Added to cart counts units. A shopper adding three of the same item adds 3 to the number, not 1.
- Checkouts started carries no money. Nothing has been charged at that point, so counting a total there would be counting a sale that may never happen. The gap between Checkouts started and Discounted orders is your checkout abandonment, and it is the one number on this page Shopify’s own discount reports cannot give you.
- Product views and Added to cart are not filtered to discounted products. They count activity across your product pages, so they are a traffic baseline to read the later steps against, not a count of shoppers who saw an offer. That is why the chart says Product views, not “offer views”, and why Conversion rate is orders over all product views, a store-wide rate rather than an offer’s.
The Revenue tile has one honest exception. If Shopify counted discounted orders in the range but the pixel saw none of those checkouts, the tile does not print 0.00. It shows a dash, and hovering it, or reading it with a screen reader, says “Not captured. The storefront pixel saw none of these checkouts.” A zero would claim nobody paid. The truth is that the figure was never recorded.
Within a range that has activity, a real zero is shown as a zero. A range with no activity at all is a different case, covered in The other states this page can show below.
The chart
Under the tiles is a line chart of one metric at a time. Its heading is the metric’s name, and the Chart metric dropdown in the top-right corner switches between Product views, Added to cart, Cart viewed, Checkouts started, Checkouts seen, Discounted orders and Revenue. The dates the chart covers are printed beneath it.
- One point per day, zero days included. Quiet days are drawn as zeros, never skipped.
- Hover along the plot and a crosshair snaps to the nearest day, with a readout of that day’s date and value. The same readout works from the keyboard: focus the chart, then use Left and Right to walk day by day, Escape to clear.
- Only the latest point carries a printed value. Every other day is in the readout and in the By day table below.
- A metric with nothing to draw in this range shows a sentence instead of an empty axis, for example “No product views between Sep 9, 2026 and Sep 15, 2026.”
The chart is a viewing preference. Switching it changes nothing about the page address or the data, only which line you are looking at.
Why “Checkouts seen” and “Discounted orders” disagree
They will differ, and that is expected:
“Checkouts seen” comes from the storefront and is approximate: ad blockers and shoppers who decline analytics are not counted. “Discounted orders” comes from Shopify itself and is exact.
Checkouts seen is a storefront signal, and so is Checkouts started. Both are missed whenever a shopper runs an ad blocker, declines analytics tracking in your store’s privacy settings, or closes the tab before the beacon leaves. Nothing is retried.
The two are different moments. Checkouts started is reaching the checkout, and Checkouts seen is the pixel witnessing it completed. A shopper who abandons is counted in the first and not the second.
Discounted orders arrives on a Shopify-signed order webhook. An order is counted only when the order carries an xDiscount discount and your store has at least one discount registered with Shopify. That is the same test your billing uses when it counts an order against your plan’s included orders, so the two are counting the same orders.
Which number to trust
Treat Discounted orders as the number of record. Use the three pixel steps for shape and trend, not for accounting.
Filtering by discount type
Beside the date range is a filter chip. It starts on All and offers your four discount types:
| Choice | What the page then shows |
|---|---|
| All | Everything your storefront recorded, plus every discounted order |
| Percentage | Only activity on products covered by a percentage discount |
| Fixed amount | Only activity on products covered by a fixed-amount discount |
| Buy X get Y | Only activity on products covered by a Buy X get Y discount |
| Free shipping | Only activity on products covered by a free-shipping discount |
Every number on the page follows the chip: the tiles, the chart and the By day table.
How an event gets its type. A product belongs to one discount, so a product page view, an add to cart, or a checkout resolves to exactly one kind. A product no discount covers counts under All and under no type, which is why the four types will not account for all of your product views. That is your untargeted catalogue, and it is meant to be there as a baseline.
The four types add up to more than All
That is correct, not a rounding error. One checkout can contain a percentage product and a Buy X get Y product. It is one checkout under All, and it is honestly counted under both types, because “checkouts that contained a percentage discount” is the question the filter asks. All is measured in its own right, never added up from the four.
Archiving frees a product. An archived discount no longer covers its products, so activity on them stops appearing under that type, exactly as the discount form stops reserving them.
After you change a discount’s type, new events follow the new type within about a minute. Nothing already recorded is rewritten. A day that happened under the old type stays where it was, because it is what happened.
The By day table
Below the chart, By day lists one row per day with eight columns:
| Day | Product views | Added to cart | Cart viewed | Checkouts started | Checkouts seen | Discounted orders | Revenue |
|---|
- Newest day first.
- Days with nothing on them are shown as zeroes rather than skipped, so a quiet week looks quiet instead of being squeezed out of the list.
- Days are whole calendar days (UTC) recorded on our side, not on the shopper’s device clock, so a shopper with a badly set clock cannot land in yesterday’s row. If your store runs on a different timezone, a day here will not line up exactly with the same day in Shopify’s own reports.
- Every number the chart draws is in this table, so nothing on the page depends on colour or hover.
How the storefront pixel contributes
xDiscount installs a Shopify web pixel for you when the app is installed. You do not add it, configure it or maintain it, and there is no setting for it in the app.
It subscribes to exactly five storefront events and nothing else:
| Event | What is sent |
|---|---|
| Product viewed | The product ID and variant ID |
| Product added to cart | The product ID, variant ID and quantity |
| Cart viewed | The product IDs in the cart — no quantities, no money |
| Checkout started | The product IDs in the checkout — no money, since nothing has been charged yet |
| Checkout completed | The currency code, the order total, and the title and type of each discount applied |
Everything is folded into one daily total per store as it arrives. Nothing is kept as an individual shopper’s event trail.
It is fire-and-forget. A beacon that fails is dropped, never retried. A queue of pending telemetry inside a storefront is not worth what it would cost your shoppers in page speed. This is why the storefront counts are honestly labelled approximate.
Very busy stores
A very busy store can send more events in a minute than we accept from one store, and the excess is dropped rather than queued. This only ever nudges the pixel-sourced numbers downward. Discounted orders is untouched by it.
Privacy: what xDiscount never collects
The pixel declares itself as analytics only. In your store’s customer privacy settings that means:
| Purpose | Declared |
|---|---|
| Analytics | Yes |
| Marketing | No |
| Preferences | No |
| Sale of data | Disabled |
Shopify only runs the pixel for visitors who have consented to every purpose it declares. Declaring marketing would have quietly dropped the pixel for every shopper who allowed analytics but declined marketing, so it is declared false. The pixel does no advertising, no retargeting, no sharing and no selling.
The pixel never collects, and cannot collect:
- No shopper identity, so no name, email, phone number or customer record.
- No IP address, no device identifier, no browser fingerprint input.
- No per-visitor tracking ID, so one shopper’s views cannot be stitched into a session or followed across visits.
- No page URLs, no referrers, no search terms.
- No cookies or browser storage of its own.
What actually leaves the storefront is the short list in the table above: product and variant IDs, a quantity, an order total and currency, and discount titles. They are treated as opaque text on arrival, nothing is ever looked up from them, no pricing and no entitlement, and they are not kept. What is written down is the day’s running totals for your store, and nothing else.
If a customer asks what the app tracks
Product and cart activity in totals per day, and no information about who they are.
Where the revenue numbers are
The Revenue tile, the Revenue option in the Chart metric dropdown and the Revenue column in the By day table are all the storefront’s figure: the checkout totals the pixel saw on discounted checkouts. It is labelled approximate everywhere it appears, and the tile says why in its own words, “Storefront figure from discounted checkouts (approximate). Your Shopify reports have the exact number.” It misses the same checkouts Checkouts seen misses, so it will read low, and it is never used for billing.
The number of record is in Shopify. Shopify already reports discount revenue natively and does the money arithmetic on its own records, and a figure from us that differed by a cent would just read as a bug and cost you an afternoon reconciling it. So xDiscount tags the orders it discounts, and you slice your own Shopify reports by them.
How it works:
- When xDiscount reduces the price on an order, that order is stamped with the name of the discount that did it.
- The stamp lands on an order field called xDiscount campaign, which is set up in your store when the app is installed.
- In Shopify Analytics, group or filter a sales report by
order.metafields.xdiscount.campaign.
The field name is exactly order.metafields.xdiscount.campaign. The Analytics page no longer repeats it, so keep this page to hand when you build the report.
Points to be aware of:
- Only orders xDiscount actually discounted are stamped. Orders it did not touch stay blank rather than being lumped into a misleading bucket.
- Your own manual discounts are never stamped into this field, even if they were on the same order.
- Discount names longer than 120 characters are shortened in the stamp. A report dimension with thousands of near-identical values is unusable, so the value is kept short. The full name stays on the discount itself.
- The field is read-only in the admin. It is written by the app, and an edit would be overwritten.
- Shopify can decline to make the field groupable in reports on a given store. If that happens the field is still created, the stamp is still written and still visible on the order, it just cannot be used as a report dimension there.
The other states this page can show
| State | What you see | What it means |
|---|---|---|
| Loading | Four placeholder tiles and a blank chart-sized block | The first read of the page is in flight. Later range switches keep the old numbers on screen and dim them instead |
| No activity | No activity in this range, naming the dates, with an Open settings button | Nothing at all has been recorded in the selected range. No tiles, chart or table are drawn, because a wall of zeros would be indistinguishable from a broken pipeline |
| Read failed | A red banner headed Couldn’t load your analytics with a Try again button | We could not read your numbers |
The failure banner reads: “Your discounts are unaffected, this page only reads what has already been recorded.” That is the important part. This page only reads, so a failure here never stops a discount from applying at checkout.
The empty state explains itself, “Nothing was recorded between … and …. Numbers appear once shoppers see your discounts, the offer card has to be added to your theme for views and cart activity to be counted.”, and points you at Settings, where the Storefront offer card section has an Add to theme button. The offer card is what shows shoppers a discount on the product page, before they reach checkout, and it is included on every plan, Free included.
Reading the page well
- Compare like ranges. Switch between Last 7 days, Last 30 days and Last 90 days rather than reading one window in isolation, and use a custom range to line up with a specific promotion.
- Compare the storefront counts with Discounted orders. The counts move with your traffic. The ratio between them moves with your offer.
- Judge performance on Discounted orders. It is the exact number, and the one counted against your plan’s included orders.
- Expect the storefront counts to miss some shoppers. Ad blockers and declined consent are normal, and they only ever undercount.
- Go to Shopify Analytics for money questions, grouped by
order.metafields.xdiscount.campaign. The Revenue tile is for trend, not for accounting.