Promotional Planning
Lift modeling · Budget allocation
A category manager must choose which SKUs to promote, at what discount depth, in which week, under a fixed promotional budget — while accounting for cross-product cannibalisation and category halo. The exact problem is a 0-1 knapsack on (SKU × week × depth) triples with a budget constraint and concurrent-promo limits. Foundational papers: Blattberg, Briesch & Fox (1995); Cooper et al. (1999) PromoCast; van Heerde, Leeflang & Wittink (2004); Macé & Neslin (2004).
Why it matters
Scale of promotion in retail · documented optimization lift
Where the decision sits
Trade-promotion calendar · weekly ad · loyalty offer planning
Promotional planning sits between forecasting and execution. Forecasts give base demand; lift functions quantify how that demand responds to discount depth; the planner decides the SKU/week/depth grid; downstream execution sets prices in POS systems and triggers replenishment. The hard part is not depth alone but the portfolio: too many concurrent promotions cannibalise each other, blow the budget, and shift demand forward without growing the category. End-of-life pricing on promoted SKUs handed off to markdown downstream.
Problem & formulation
Multi-period, multi-SKU 0-1 knapsack with budget and page constraints
Sets and indices
| Symbol | Meaning | Domain |
|---|---|---|
| \(i \in N\) | SKU in the category | discrete |
| \(t \in T\) | Week in the planning horizon | discrete |
| \(d \in D\) | Discount depth (e.g., 0%, 10%, 20%, 30%) | discrete, ordered |
Parameters
| Symbol | Meaning | Unit |
|---|---|---|
| \(\text{base}_{i,t}\) | Baseline weekly demand for SKU \(i\) in week \(t\) | units / week |
| \(p_i\) | List price of SKU \(i\) | $ / unit |
| \(m_i\) | Unit margin of SKU \(i\) at full price | $ / unit |
| \(\alpha_i, \beta_i\) | Lift coefficients for SKU \(i\) (linear, quadratic in depth) | — |
| \(\gamma_{i,j}\) | Cannibalisation coefficient: substitution from \(j\) when \(i\) is promoted | \(\in [0,1]\) |
| \(B\) | Total promotional budget for the horizon | $ |
| \(M_t\) | Maximum number of SKUs promoted in week \(t\) (page constraint) | integer |
Decision variable
| Symbol | Meaning | Domain |
|---|---|---|
| \(x_{i,t,d}\) | 1 if SKU \(i\) is promoted at depth \(d\) in week \(t\), else 0 | \(\in \{0, 1\}\) |
Lift function (own-SKU response)
A standard parametric form is concave in depth above a threshold — doubling the depth less than doubles the unit lift:
With \(\alpha_i > 0\) and \(\beta_i < 0\) the curve is concave. Calibrated from historic promo-vs-non-promo weeks.
Cross-product cannibalisation
A fraction of SKU \(i\)’s lift is stolen from substitute SKU \(j\):
Net incremental margin
Margin earned from incremental lift on SKU \(i\) minus margin lost to substitutes:
Objective
Constraints
One depth per SKU per week; total promo cost within budget; at most \(M_t\) SKUs promoted per week (circular page / display capacity):
Real-world → OR mapping
How a category manager’s vocabulary translates to the IP
| On the planning desk | In the IP |
|---|---|
| Category SKU range | \(N\) |
| Promotional calendar (weeks ahead) | \(T\) |
| Available discount tiers (15% off, 30% off, BOGO) | \(D\) |
| Baseline forecast at full price | \(\text{base}_{i,t}\) |
| Depth-response curve from past promos | \(\alpha_i, \beta_i\) |
| Substitution between SKUs in same need-state | \(\gamma_{i,j}\) |
| Trade-promotion budget | \(B\) |
| Slots on weekly circular / endcap count | \(M_t\) |
Interactive solver
Greedy by margin-per-budget-dollar with budget & page checks; re-solves in browser
| SKU | Price ($) | Base demand (units/wk) | Lift α |
|---|
Under the hood
We enumerate all (SKU, week, depth>0) triples and compute their net incremental margin and promo-dollar cost. Triples are sorted by margin per dollar and inserted greedily, skipping any that would violate the SKU-per-week constraint, the per-week SKU cap \(M_t\), or push the cumulative cost above \(B\). Cannibalisation is approximated as a flat \(\gamma\) of the chosen SKU’s own lift, multiplied by the average margin of substitutes. The baseline is a uniform-rotation policy that promotes \(M_t\) SKUs per week at the cheapest depth that fits the budget. Runtime is \(\mathcal{O}(|N| \cdot |T| \cdot |D| \log(\cdot))\) — sub-millisecond at this scale.
Reading the solution
What a category manager actually does with the optimal plan
Three patterns to watch for
- High-base SKUs at shallow depth. Heavy sellers maximise margin-per-dollar at 15-20% off — the curve is steep enough that you don’t need to discount deeper. Deep depths are reserved for SKUs that genuinely need the depth to move.
- Concentration on low-cannibalisation SKUs. When \(\gamma\) is high, the planner avoids promoting close substitutes in the same week — promoting one already steals from the others. This shows up as a sparser plan when \(\gamma\) rises.
- Budget binds before page capacity. In small-budget runs the plan stops well before \(M_t\) slots are full each week. Raising \(B\) by 50% typically buys 70-80% more incremental margin (roughly linear) until page constraints bind.
Sensitivity questions the model answers instantly
- Add a 50% depth tier? — rarely chosen unless lift coefficients are unusually steep; flags overly aggressive depth menus.
- Cut budget by 30%? — concentrates the plan on the most efficient (high-base, low-cannibalisation) SKUs first.
- Raise \(\gamma\) from 0.20 to 0.40? — incremental margin drops sharply; planner spreads promos across weeks rather than across SKUs.
Model extensions
From single-category baseline to retail-OR variants that matter
Stochastic baseline demand
Replace deterministic \(\text{base}_{i,t}\) with a forecast distribution; objective becomes expected incremental margin under chance constraints on stockouts.
Dynamic budget rebalancing
Re-optimise the remaining budget mid-season after observing promo response; rolling-horizon implementation common in retail planning systems.
Joint markdown + promo
End-of-life promo decisions interact with seasonal markdown; jointly decide both to avoid double-discounting and inventory mismatch.
Markdown →Vendor-funded promo
Trade allowances reduce effective cost of depth from the retailer’s side; objective shifts toward maximising trade-fund pull-through.
Category cross-effects
Halo (lift in adjacent categories) and pantry-loading effects cross category boundaries; requires cross-category lift coefficients.
Omnichannel promo
Online and in-store have different lift coefficients and budget pools; channel-specific decision variables and budget constraints.
Personalised promo
Customer-specific offers via loyalty programs; per-customer lift functions and budget per segment.
Personalised promo →ML lift estimation
Uplift modelling with double-machine-learning or causal-forest estimators for \(\alpha_i, \beta_i\) and \(\gamma_{i,j}\) at scale.
Key references
Foundational promotion-response and planning literature
Back to the retail domain
Promotional planning sits in the Promotion × Tactical cell of the 4P decision matrix — the lever that drives ~30% of grocery and ~25% of mass-merchant revenue.
Open Retail Landing