ClearStock is live on the Shopify App Store.Install free →

← All blogs

Reorder Math11 min read

Finding baseline demand when promos distort your history

Promo weeks inflate the velocity behind your reorder points: a worked example that flags promo weeks, extracts baseline demand, and plans promos apart.

InventoryX is in development and not available today. ClearStock is the live Shopify app.

An eight-week promotion can leave your velocity running at nearly twice its true rate, and the distortion doesn't leave when the sale ends. It rides along inside every trailing average for months, making reorders fire early and oversized while the excess piles up as inventory nobody is buying at baseline rates.

The fix is mechanical. Keep a promo calendar alongside your sales data, mark the weeks promotions ran, then either exclude those weeks or divide them by the promo's lift ratio. That leaves you holding two numbers — baseline demand for ordinary weeks, plus a separate promo-scenario rate you apply only when a promo is actually running — instead of one contaminated average. Worked example below, arithmetic shown.

Why promo weeks poison trailing velocity

Velocity in reorder math is just trailing sales divided by weeks. A discount code, an email launch, a paid push — any of these can lift units per week 2–4× for the promo's duration, and the trailing average carries the spike until the promo weeks fall out of the window. The arithmetic is unforgiving: three promo weeks at triple baseline inside a 12-week window leave the average inflated by 50% even after the sale is over (9 × 28 + 3 × 84 = 504; 504 ÷ 12 = 42, against a true 28).

A second distortion works the other direction. A good promo doesn't only create demand — it moves it. Buyers who would have purchased in the weeks after the sale bought early instead, so the first weeks after a promo run below baseline: the pull-forward trough. Correct by ignoring promo weeks but keep those depressed weeks in the average, and you now underestimate demand.

Both failures come from reading contaminated data as if it were baseline. Velocity contamination has several sources — promo weeks are one, ad-spend changes are another, and recalibrating reorder points when ad spend changes is covered in scaling reorder points to your ad spend. This article carries the promo case: extracting a clean baseline from history that's already distorted. And once you've extracted it, measuring forecast error with MAPE is how you find out whether the corrected number actually lands — a baseline is a hypothesis until you've scored it.

Build a promo calendar column first

You think you'll remember which weeks ran promos. You won't — not six weeks later, not across 300 SKUs. So the calendar is a permanent column, not a memory exercise. One spreadsheet, one row per week:

Week start Promo / event Channels Notes
2026-08-03 — — —
2026-08-10 Anniversary sale, 20% off Email + code + paid Ends 2026-10-04

Fill it from sources you already have:

  • Discount codes. Each code in your Shopify admin maps to the weeks it was live, and order exports carry the code used per order (Shopify Help Center, accessed November 2026).
  • Email sends. Campaign reports from your email platform list send dates and follow-up windows (Klaviyo Help Center, accessed November 2026).
  • Paid campaigns. Meta Ads Manager and Google Ads report by day, so campaign date ranges line up cleanly with calendar weeks (Meta Business Help Center and Google Ads Help, both accessed November 2026).
  • Calendar events. BFCM, anniversary sales, influencer pushes, gift-with-purchase weeks. If a promotion ran, the week gets a row. BOGO weeks too — a paired free unit moves roughly twice the units a discount code does (the BOGO math), which is why it earns its own row rather than a footnote.

Marking rule of thumb: a promo running at least half the week contaminates the whole week. For shorter touches, note the days covered and prorate — a code live 2 of 7 days makes the week roughly 2/7 promo-weighted. Keep 52 weeks of calendar; promo patterns repeat annually, and last year's lift is your best starting estimate for next year's edition.

Exclude or down-weight: the two extraction methods

Two ways to clean the average, and the choice matters less than doing either:

  • Exclusion. Drop promo weeks entirely and average the rest: baseline = sum of ordinary-week units ÷ count of ordinary weeks. Simplest to run and audit. Best when promos are rare for the SKU or the lift was extreme.
  • Down-weighting. Keep promo weeks but divide their units by the lift ratio before averaging: lift = promo-week average ÷ ordinary-week average. Better when promos are frequent — excluding half the year leaves thin data — or lift is moderate, because every week still contributes.

Forecasting practice treats these as separate regimes rather than garbage rows: you mark the intervention, then model around it (Hyndman & Athanasopoulos, Forecasting: Principles and Practice, accessed November 2026). In spreadsheet terms, keep the promo weeks visible in the ledger — just don't let them define the baseline.

One constraint: ordinary weeks have to be representative. If your uncontaminated weeks happen to fall in a seasonal trough, you've extracted a baseline that's wrong for peak season — that case gets its own section below.

Worked example: an enamel pin with an 8-week promo window

Setup: SKU PIN-EN-053, a single enamel pin design, $12 retail and $2.40 unit cost (both illustrative). Domestic pin maker, 21-day lead time measured from your own PO history. Twelve weeks of weekly sales, with an 8-week promo window (weeks 3–10) built on a 20%-off code, an email launch, and a small always-on paid push.

Week Units sold Promo? Handling Baseline-equivalent units
1 32 — keep 32
2 28 — keep 28
3 45 yes ÷ 2.4 18.8
4 71 yes ÷ 2.4 29.6
5 88 yes ÷ 2.4 36.7
6 92 yes ÷ 2.4 38.3
7 74 yes ÷ 2.4 30.8
8 66 yes ÷ 2.4 27.5
9 58 yes ÷ 2.4 24.2
10 49 yes ÷ 2.4 20.4
11 22 post-promo trough keep 22
12 30 — keep 30

The derivation, in order:

The naive number, to see the damage. Total units = 655 (112 ordinary + 543 promo). 655 ÷ 12 = 54.6 units/week — nearly double the truth.

Ordinary-week average. Weeks 1, 2, 11, 12: 32 + 28 + 22 + 30 = 112; 112 ÷ 4 = 28 units/week. (Week 11 runs light because the promo borrowed its demand. Drop it and you get 30/week; either reading is close, and for reorder math the lower one is the safe one.)

Promo-week average and lift. Weeks 3–10: 45 + 71 + 88 + 92 + 74 + 66 + 58 + 49 = 543; 543 ÷ 8 = 67.9 units/week. Lift = 67.9 ÷ 28 = 2.4.

Baseline-equivalents. Divide each promo week by 2.4 (45 ÷ 2.4 = 18.8, and so on down the column). Corrected total = 112 + 226.3 = 338.3; 338.3 ÷ 12 = 28.2 units/week.

Cross-check by exclusion. 112 ÷ 4 = 28 units/week — the same answer. When the lift ratio is stable across a promo, exclusion and down-weighting converge; pick whichever your spreadsheet habits prefer and write the choice down.

Baseline demand for PIN-EN-053 is 28 units a week. Not 54.6.

What the corrected baseline changes in your reorder point

Input Contaminated average Corrected baseline
Weekly velocity 54.6 28
Lead time 21 days (3 weeks) 21 days (3 weeks)
Buffer 1 week of demand (deliberately simple, illustrative) 1 week of demand
Reorder point 54.6 × 3 + 55 ≈ 219 units 28 × 3 + 28 = 112 units
Order quantity at "8 weeks of cover" 8 × 54.6 ≈ 437 units 8 × 28 = 224 units

The contaminated plan holds 107 more units at the reorder trigger — nearly four weeks of baseline demand earlier than necessary, every cycle — and buys about 213 extra units per order, roughly $510 estimated parked per cycle at this SKU's cost. On one SKU. Multiply by everything else you promoted this year before deciding the distortion is cosmetic.

The correction also buys you a second number worth having: the promo-scenario rate. You now know this SKU runs at roughly 68 units/week during a promo of this shape (67.9 measured, so call it ~68). When the calendar says a promo is coming and your 21-day lead time will overlap it, size that one cycle's reorder point on the promo rate — deliberately, from the calendar — then drop straight back to 112 the week it ends. Next year's edition of the same promotion starts from this year's measured lift instead of a guess. And the corrected baseline only pays off if something executes it weekly — the calendar that turns it into sent POs is the replenishment schedule guide.

When the promo window overlaps a seasonal peak

If the promo weeks sit inside a seasonal ramp — a BFCM sale, a December gift push — exclusion alone conflates two effects: some of those units were season, not promo. Extract in two passes: adjust each week by its seasonal index first, then compute the lift against seasonally adjusted ordinary weeks from the same part of the year. Skip the first pass and your baseline gets set by off-season weeks, which makes every Q4 look like a permanent promo — overstocking you in the quiet months or leaving you short at peak, depending on which wrong number you trust. And the promo weekend's date itself moves between years, which is its own comparison trap — the anchor-alignment fix is covered in the year-over-year calendar alignment guide.

What software catches, and what it doesn't

Promo weeks inflate velocity; weeks you were out of stock deflate it — the mirror-image distortion. InventoryX (in development) handles the second one: its velocity counts only the days a SKU was actually sellable, so dark days don't drag the average down (the mechanics are in correcting velocity for out-of-stock days). What it doesn't do, yet, is detect promo weeks on its own — the calendar column and the lift division stay manual, and we'd rather say that than imply the app cleans your history for you. Two distortions, two corrections: run both, or your velocity is wrong in one direction or the other.

Common questions

What is baseline demand? The rate a SKU sells in ordinary weeks — no discounts, events, or ad pushes — and it's the number your reorder points should be built on. Estimate it by averaging only uncontaminated weeks, or by dividing promo-week units by the promo's lift ratio before averaging.

Should promo weeks be excluded or down-weighted? Either works, and on stable data both give the same answer. Exclusion drops promo weeks and averages the rest — simplest, best for rare promos. Down-weighting divides promo weeks by the lift ratio and keeps every week — better when promos are frequent or lift is moderate, because no data is discarded.

How do I calculate a promo lift ratio? Divide average units per week during the promo by average units per week in ordinary weeks from the same period. In the worked example: 67.9 ÷ 28 ≈ 2.4. Then divide each promo week's units by 2.4 to convert them to baseline-equivalent units before averaging.

Why do sales drop after a promotion ends? Pull-forward: the promo moved future demand into the promo window instead of creating it. Buyers who would have purchased in the following weeks bought early at the discount, so the first one or two weeks after the promo run below baseline. Mark them as contaminated too, or your baseline skews low.

How should I plan inventory for a known upcoming promo? Keep two numbers: baseline velocity for ordinary reorder points, and the promo-scenario rate from your last comparable promo. For any reorder cycle whose lead time overlaps the planned promo, size the reorder point on the promo rate, then return to baseline immediately after — deliberately, from the calendar, not via a permanently inflated average.

Next step

How much of your velocity number is promo echo? Open your order history for your fastest-moving SKU, mark the last 12 weeks with a promo column (codes, sends, paid pushes), and compute the baseline both ways. Compare it with the velocity number currently feeding your reorder points; if the gap is over about 20%, rebuild those reorder points on the corrected figure, then score the new number against reality on your next ordinary cycle using the forecast error measurement method.