Company
Company headline
Sales, orders, AOV and repeat order share for the chosen Window, read from the production dataset. Every ratio divides Sales (shopify_total_sales), the house numerator, so headline Sales ÷ orders is the AOV tile by construction — and the change against the prior period is shown only where that comparison is honest.
Headline
Every tile below recomputes for the Window above, and prints the days it covers. The change against the prior period — the same number of days immediately before the window — is shown only where the whole of that prior period sits inside trading history.
Window: Last 30 · 6 Jul 2026 → 4 Aug 2026 — 28 of 30 days carried orders, from analytics.orders.
Each tile resolves through components/presentationState.js, the one place that decides
whether a figure renders normally, marked, suppressed with a reason, or too early. The
rule the tiles are following: a delta renders when the whole prior period sits inside
trading history, and is withheld the moment it reaches back past the first date
analytics.orders carries. Which windows that bites is a fact about the data, not a
property of the presets — it moves as history accumulates, and a window suppressed today
starts comparing on its own once enough days sit behind it. So each tile prints its own
reason, computed with the figure, rather than this paragraph naming windows it would go on
to contradict (ADR 0007). A suppressed comparison is a different statement from one
that was never configured, which is why the reason is rendered instead of the pill
silently disappearing. AOV and repeat order share also pass their denominator, so small-n
marking fires on its own the moment a window narrows the order count below the five-order
bar. The four states are exercised end to end on the component gallery.
The counts the ratios above rest on, for the same window. Repeat order share is repeat orders ÷ orders — 33 ÷ 139 = 23.7% — and it is repeat_order_share from the canonical metric registry, not repeat_customer_rate, which is a registry name already taken by a different measure.
Customers is deliberately not on this page any more. It is a distinct count, so it is not additive across dates: summing the daily figure over a window over-counts everyone who ordered on two days, and there is no arithmetic over daily rows that recovers the right answer. Rather than print a number that quietly overstates, the tile is dropped from the windowed set until a source at window grain earns its place. The source header records the choice and the reasoning.
Where to look next
Flags: a card per rule that crossed its threshold, most urgent first, across all four sections — headline, acquisition, website and retention. Each one is computed in SQL from the same marts as the section it points at, over this page's Window, and each states a fact rather than what to do about it. A drill-down runs the same rule over its own Window, whose bounds are its mart's rather than the order dates, so a card there can carry a wider count than the card here and say so.
SERIOUS 2
WARNING 7
Every bar is provisional, and each card states the one it crossed on its own detail
line — read out of the fence's bars block, the only place this page writes any of the
nine numbers, so this paragraph cannot end up quoting a threshold the rules no longer use.
Each drill-down declares its own section's bars in its own fence, because Evidence cannot
share a fence between pages: a bar that moves has to move in both, and until they are
settled that is a cost worth naming rather than hiding. They are confirmed at PRD044
sign-off (#80) rather than settled by having shipped, because a threshold quietly becomes
the shared vocabulary for what "bad" means and that is hard to reverse once it is trusted.
Four of the ten rules are Window-exempt, and the section tag on the card is how to
tell: a retention card is computed over calendar months and the whole of trading
history, because subscriber churn is a calendar-month rate and a subscription bridge is a
billing-month one — cutting either to an arbitrary thirty days would answer a question
neither measure asks. Retention states its own basis on
/company/retention rather than taking one from the control above,
and the flags follow the section they point at. Everything tagged headline,
acquisition or website moves with the Window.
A flag states a fact and stops. The detail line names the counts the rule divided
and the bar it crossed; it never says what to do about it, and there is no generated
prose anywhere on this page (ADR 0007). What replaces the reference dashboard's essays is
this: a rule evaluated in SQL against the same rows as the section it points at, rebuilt
with the data, so it cannot drift out of agreement with them. The cost is the
cross-sectional reasoning a model does well — a rule can say the unattributed share is
above the bar, not that it is concentrated in one discount code.
Each drill-down carries its own section's cards and nothing else, filtered from the same rules to the same words: acquisition, website and retention each show the flags that point at them, and this page is the only one that shows all four sections at once. Every card is reachable from the page that can act on it, and no page carries a card about a section it does not show.
Narrow the Window and the windowed cards recompute with the tiles, because both read
daily rows through the same filter — a rule that no longer trips loses its card entirely,
and one that starts tripping gains one. The thresholds are the only thing that stays put,
and the retention cards, which are exempt, stay put with them.
components/FlagCards.svelte is deliberately ignorant of all of it: it groups by severity,
orders SERIOUS above WARNING and tags each card with its section, and it is driven through
both branches — cards, and the empty state — against a hard-coded fixture rowset on the
component gallery, so the rendering is exercised independently of the data. The
two rules that cannot fire on today's data — a channel spending with no order at all, and
the cancellation reconciliation break — are driven from fixtures of their own on
the flag-rule QA page, so a rule that has never fired is not a rule
nobody has seen fire.
Monthly pacing
Month-to-date Sales for the month in flight, read against the same month-day range of the prior month and against that month's full total — both labelled, because a bare 'vs last month' setting three days beside thirty-one is the exact dishonesty this panel exists to avoid. The full-month projection is withheld until the month has enough days behind it to carry a rate.
Two comparisons, both spelled out, because they answer different questions. The tile above compares 1–4 August 2026 against 1–4 July 2026 — the same month-day range, so it is a like-for-like read on whether the month has started better or worse. The share on the right compares month-to-date against July 2026 in full, which is a progress read and not a growth read: it is expected to be well under 100% for most of a month. A bare "vs last month" would be neither, and is what this panel exists to avoid.
The projection rule lives in components/monthlyPacing.js, once: month-to-date Sales ÷
elapsed days × days in the month, published only from day 7. Below that bar a run-rate
rests on so few trading days that scaling it to a whole month is arithmetic wearing a
forecast's clothes — one strong Tuesday triples it — so it resolves to the suppressed
state from components/presentationState.js and prints why, rather than the tile quietly
disappearing. That is the same discipline the tiles above follow and the same one
CONTEXT.md sets: a thin figure is marked, a misleading one is withheld, and the
difference is always stated.
Both halves of that rule are live on this panel right now. The projection is withheld —
day 3 of 31 cannot carry a rate. The like-for-like comparison is marked and kept: cutting
July back to its first three days makes the comparison fair, but it leaves a basis of
4 orders, under the house 5-order bar, and that thin basis — not August tripling — is
what produces the +829.6% on the MTD Sales tile. So the tile names what the percentage
rests on and says to read its direction rather than its size, and the strip carries the
prior-range order count with a † beside it. Suppressing it instead would be the wrong
call: a like-for-like comparison that states its own basis is thin, not misleading.
What would be suppressed is a like-for-like range reaching back before trading began on 16 June 2026 — a structural zero rather than a low number, and no percentage against it means anything. That is the same rule the headline tiles above apply, decided in the fence off the same first trading date, so the two can never disagree. It does not fire today (1 July clears 16 June), and it is not left unseen for that: the gallery drives it from a fixture alongside the projection's published branch.
The published branch cannot be seen on live data until a month reaches its seventh day, so it is not taken on trust: the component gallery drives the same component through the same rule with a fixture month at day 9, and both branches render there side by side.
How Sales is made up
The composition behind the headline, for the same Window, read left to right. Every cell is measured independently, including the Sales total at the end, so a broken source shows up here as an arithmetic that stops closing rather than as a plausible wrong number — and the page says so in words when it does.
Window: Last 30 · 6 Jul 2026 → 4 Aug 2026 — every cell below is measured over those days.
The discount gap is the load-bearing number on this page. Discounts are £1,719.35 of £4,048.42 gross product sales — 42.5% — so more than a third of everything ordered is never charged for in the first place. That is discounting at the point of sale, not returns, which are the separate and far smaller £182.90 beside it. Nothing else in the composition is close to that size.
Three things the row is stating on purpose:
- Net sales is a diagnostic beside Sales, never a ratio numerator. It is what Sales would be with shipping and tax stripped out. Every ratio on this page divides Sales (ADR 0008), which is why the two figures sit on one row rather than on two tiles that a reader might pick between.
- Returns is
refund_product_amount, notrefund_amount_gbp. The two differ (£151.92 against £137.94 on data through 2026-08-03) becauserefund_amount_gbpnets the shipping refund off the product refund, and only the product figure makesgross − discounts − returns = net salesclose. The figures in this bullet are a worked example on the all-time window, not live values; the row above is the live one. - Tax reads £0.00 by construction, and that is the one caveat on Sales. dbt gates the
Shopify tax lines off (dbt ADR-0009,
taxes_included = true), so Sales is VAT-free today and every ratio built on it is sound. When VAT-bearing orders flow and the gate opens, VAT is extracted from the tax-inclusive price rather than added on top: Sales holds steady, net sales steps down about a sixth, and every efficiency figure silently overstates by that sixth until aSales, net of VATvariant exists in the marts.
The deployed site is static with no runtime connection to BigQuery, so this rebuild is the data refresh, and the stamp above is the only on-page evidence that the numbers moved. A refresh that fails after Cloudflare accepts the deploy hook leaves the previous deployment live with a green workflow run, and the stamp is what makes that visible.