The missing column that breaks everything
Sales history from most businesses records what sold. It rarely records why. If a third of the weeks in your history contained a promotion and nothing marks which ones, the model sees a series that jumps unpredictably and learns to average across it.
The result is a forecast that is confidently wrong in both directions: too low whenever you promote, too high in the weeks after, when demand dips because customers already stocked up.
What the model needs to know about a promotion
Feeding in a simple yes/no flag helps, but rarely enough. Promotions differ in ways that change the uplift by a large multiple.
- Discount depth - 10% off and half price are not the same event
- Mechanic - straight discount, multibuy, bundle, loyalty-only
- Visibility - end cap, homepage banner, email, or nothing but a shelf label
- Duration, and whether it spanned a payday or a bank holiday
- Whether competitors were promoting the same category at the same time
Most businesses hold some of this somewhere - in a trade plan, a marketing calendar, a spreadsheet on somebody's desktop. Getting it into one table with dates and product codes is often the single highest-value task in the whole project.
Cannibalisation and pull-forward
Two effects make promotional forecasting harder than a simple uplift. Cannibalisation is when promoting one product takes sales from a similar one rather than growing the category. Pull-forward is when a promotion brings forward purchases that would have happened later anyway.
Both mean the honest measure of a promotion is not the uplift during the promotion. It is the change in category sales across a window that includes the weeks afterwards. Judging promotions on in-period uplift alone systematically overstates how well they worked.
This matters for forecasting because a model that learns only the uplift will over-forecast the following weeks. Including the post-promotion period in how you frame the problem tends to produce a more useful forecast even when it looks less impressive.
A realistic expectation
Promotional forecasting is genuinely hard, and accuracy on promoted weeks is usually worse than on normal ones even with good data. That is not a failure of the model; promotions are high-variance events.
The practical win is usually narrowing the range rather than hitting the number. Knowing that a promotion will most likely sell between 700 and 1,100 units rather than 'somewhere between 200 and 2,000' is enough to change the buy, and that is what the forecast is for.
If nobody records what was promoted, the model is guessing - and so is everyone else.
Where to start if the data does not exist
If you have no promotion history in usable form, do not start with modelling. Start recording. A simple table of date range, product, mechanic and depth, maintained from now on, becomes valuable within a couple of trading cycles.
In the meantime, a planner's judgement plus a documented uplift assumption per mechanic is a perfectly respectable baseline, and it gives you something to beat later. Our piece on collecting data for future machine learning covers how to set this up without a large project.