Polynomial distributed lags: how long does marketing keep working?
Most marketing does not work on the day you do it. An email is read on Tuesday, forwarded on Wednesday and acted on the following Sunday; a catalogue sits on a kitchen table for a fortnight; a trade ad is remembered when the budget meeting finally happens. If you only count the effect in the week it happened, you will undervalue every slow channel and overvalue every fast one, and your budget will drift towards paid search whether or not that is where the money is. This chapter is about the distributed lag model, which estimates how much of an action's effect arrives in each of the following weeks, and about the Almon polynomial restriction that makes it estimable on ordinary business data. I use Werkbank, a Rails SaaS for craft businesses, and 78 weeks of newsletter sends and trials to show how the lag curve is estimated, how to read its peak, decay and total, how to validate it on holdout weeks, and how it turned into a concrete decision to move from monthly to three weekly sends. This is part 5 of 21 of the Marketing Analytics series.
The newsletter that keeps working after you have forgotten it
Werkbank sends one newsletter a month to about 30,000 craft businesses: joiners, electricians, tilers, the people who run a van and a spreadsheet. Every send is followed by a bump in trial signups, and the founder, quite reasonably, looks at the trials on send day and the day after, divides by emails sent, and calls that the email conversion rate. It came to 0.2 percent. Not exciting. She was about to cut the newsletter to once a quarter to save the writer's time.
The problem is that the bump on send day is only the first instalment. A tiler reads the mail on Tuesday and forwards it to his partner who does the books; she opens a trial a week later, on a Sunday evening when the invoices are being done. Some of the effect arrives in week two, some in week three. Measured properly, the newsletter was worth about four trials per 1,000 emails, not two, and most of that arrived after the day the founder stopped counting. That is what a distributed lag model does: it tells you how much of a marketing action's effect arrives now, how much arrives later, and when it has finished arriving. Once you know that, you know when to send the next one.
Where this sits in the series
This is chapter 5 of 21 and we are in part two, dependent variable techniques, where a business outcome (trials, orders, bookings) is explained by things you control. The previous chapter on demand and price elasticity used ordinary regression where cause and effect happen in the same period. This chapter adds time: the cause happens in week 10 and the effect dribbles out over weeks 10 to 15. The next chapter on Poisson regression deals with a different problem, outcomes that are counts and cannot go negative. Later, in chapter 16 on media mix modelling and adstock, the lag idea comes back in a different costume.
One number for the email effect is the wrong shape
When you regress weekly trials on weekly emails sent, you get one coefficient: trials per 1,000 emails, in the same week. Every trial that happens in a later week because of that email is credited to whatever else happened in that later week, or to the intercept, or to noise. The coefficient is too small and your decision is wrong in a predictable direction: you underinvest in anything with a slow effect and overinvest in anything with a fast one.
The fix is not a smarter single number. The fix is to admit the effect is a curve over time, estimate the curve, and then summarise it with the numbers that matter: where it peaks, when it has died, and what it adds up to.
The distributed lag model
Write trials in week as and emails sent (in thousands) in week as . A distributed lag model says this week's trials depend on this week's emails and on the emails of the previous weeks, each with its own weight:
Here is the outcome in week , is the baseline (trials that would happen with no email at all), is the effect of 1,000 emails sent weeks ago on trials this week, is the lag length (how many weeks back you allow the effect to reach), is a set of control variables such as paid search spend, holiday weeks and a trend, with their coefficients , and is the error. The set of weights is the lag curve. It is the whole point of the exercise.
Three summaries of the curve do most of the work:
The total effect is the sum of the weights: how many trials 1,000 emails eventually produce, across all the weeks in which they produce anything. The peak lag is the with the largest . And the mean lag,
is the average delay between sending and effect, weighted by how much effect arrives in each week. For Werkbank it comes out at about a week and a half.
Why unrestricted lags fall apart
The obvious approach is to put into an ordinary regression and read off the coefficients. I have done this on Werkbank's 78 weeks and I show the result below because it is instructive. The numbers throughout are illustrative, but the pattern is exactly what you will see on real data.
| Lag | Unrestricted | Std. error | Reads as |
|---|---|---|---|
| 0 | 1.31 | 0.62 | plausible |
| 1 | 0.42 | 0.88 | too low, noisy |
| 2 | 2.05 | 0.91 | too high |
| 3 | minus 0.66 | 0.87 | emails destroy trials? |
| 4 | 1.17 | 0.83 | a second peak? |
| 5 | minus 0.08 | 0.61 | zero, probably |
| Total | 4.21 | 1.38 | fine, oddly |
Two things went wrong. First, there are too many parameters: six lag weights plus controls from 73 usable weeks (78 minus the 5 lost to lags). Second, and worse, the lagged variables are nearly copies of each other. Werkbank sends on a fixed monthly rhythm, so a week with a big is followed with great regularity by a big or four or five weeks later, and lags 0 and 4 become almost indistinguishable to the regression. That is collinearity, and its symptom is exactly this: individual coefficients that swing wildly and change sign, wide standard errors, and a total that is oddly stable because the errors cancel. The total is right and every individual number is useless.
There is an irony here I point out to every client with a rigid send calendar: a perfectly regular cadence is easy to run and almost impossible to measure. A little irregularity in the send dates is a gift to whoever has to analyse them.
The Almon trick: make the weights follow a curve
Shirley Almon's idea from the 1960s is simple and still the cleanest fix I know. Instead of estimating six free weights, assume the weights lie on a smooth low order polynomial in the lag:
Here is the lag in weeks, is the degree of the polynomial (2 or 3 in practice) and the are the polynomial's coefficients. Instead of weights you estimate coefficients, and the weights are recovered from them. A quadratic can describe a hump; a cubic can describe a quick rise, a hump and a long tail, which is the shape most marketing effects have.
The clever part is that this is still ordinary least squares. Substitute the polynomial into the lag model and swap the order of the sums:
Each is a new constructed variable: is the plain sum of the last weeks of emails, is the same sum with each week weighted by its lag, weighted by the lag squared, and so on. You build these four columns in a spreadsheet or three lines of code, regress on them and the controls, and the fall out. Then for each is just the polynomial evaluated at .
What you have bought is stability: the six weights now share four parameters, so they cannot flip sign from one lag to the next. What you have paid is an assumption: that the true curve is smooth. For emails, catalogues and most advertising that is a very good assumption. For a flash sale with a hard deadline it is not, and I say so in the pitfalls.
Choosing the lag length and the degree
Two decisions, and neither should be made by staring at p values alone.
Lag length . Start generous. If you think the effect is gone in four weeks, fit with eight. Look at the tail weights: if are indistinguishable from zero and the curve has flattened, cut back to where it has died and refit. Compare the fits with an information criterion such as AIC or BIC, which reward fit but penalise parameters; pick the shortest that is not clearly worse. Too short an is the expensive mistake: the late effect is silently pushed into the intercept and the total is understated.
Degree . Fit degree 2 and degree 3 and compare. If the cubic's is significant and the curve has a visibly different shape, keep it. If not, the quadratic is fine. I very rarely go above 3 with weekly marketing data; a quartic on 78 weeks is fitting noise. Also test the restriction itself: the Almon model imposes linear restrictions on the unrestricted lags, so an F test between the two tells you whether the polynomial is too rigid. If it rejects at the one percent level, look at the residuals before believing either model.
Endpoint restrictions (forcing or ) are available and sometimes sensible. I use the far endpoint when the tail is clearly zero; I never force the near end, because an instant effect is real for email.
Werkbank's lag curve, week by week
Same 78 weeks, same controls, and , chosen by the recipe above. The estimated polynomial coefficients were , , and . Evaluating the cubic at each lag gives the curve:
| Lag (weeks after send) | Almon (trials per 1,000 emails) | Std. error | Cumulative | Share of total |
|---|---|---|---|---|
| 0 | 0.92 | 0.21 | 0.92 | 21% |
| 1 | 1.34 | 0.19 | 2.26 | 53% |
| 2 | 1.14 | 0.17 | 3.40 | 79% |
| 3 | 0.65 | 0.16 | 4.05 | 94% |
| 4 | 0.18 | 0.15 | 4.23 | 98% |
| 5 | 0.07 | 0.19 | 4.30 | 100% |
| Total | 4.30 | 0.54 |
Reading it line by line. Lag 0: in the week of the send, 1,000 emails produce 0.92 extra trials, about a fifth of everything they will ever produce. This is the number the founder was measuring, and she was measuring it correctly; it was just the wrong number. Lag 1: the following week is the peak, 1.34 trials per 1,000. Half of the total effect has arrived by the end of week 1. Lag 2 is still strong at 1.14; by the end of it four fifths of the effect is in. Lag 3 at 0.65 is the last week that matters commercially. Lags 4 and 5 are small, and their standard errors are about as large as the estimates, so I read them as "close to zero, could be nothing". The total is 4.30 trials per 1,000 emails, with a standard error of 0.54, so a 95 percent interval of roughly 3.2 to 5.4. On a 30,000 email send that is about 129 trials per campaign, give or take 30.
Compare the unrestricted table: same total within noise, but now the shape is readable. Peak at one week, commercially dead after three, nothing after five.
The Almon lag curve for the Werkbank newsletter. Lag 0 is the send week; the peak is one week later; effectively nothing arrives after week 4.
And the cumulative view, which is the one that drives the cadence decision:
By the end of week 3, 94 percent of a send's effect has arrived. Weeks 4 and 5 add the last 6 percent.
One warning about totals and averages. 4.30 per 1,000 is the average effect at the volumes and frequencies Werkbank has actually run. It is not a promise about the 18th send of the year if you move to a higher cadence. That is a marginal question, and marginal ROI is not average ROI; I come back to it below.
From lag curve to send cadence
Now the decision the founder actually faced. Under the monthly calendar a send lands every four to five weeks. The curve says the effect is 94 percent delivered after three weeks and 98 percent after four. So in a five week month, the list sits for one to two weeks producing essentially nothing from email. That is the gap.
Move to a three week cadence and each new send lands just as the previous one has spent 94 percent of its effect. There is very little overlap, so you are not stacking a fresh message on top of one the reader has not finished responding to, and there is no idle fortnight. Twelve sends a year become about seventeen. If each send kept its full effect of roughly 129 trials, email would deliver about 2,200 trials a year instead of 1,550, an extra 650.
I do not believe the full 650, and I told her so. The model was estimated on monthly sends and knows nothing about what happens to open rates and unsubscribes at a higher frequency. Werkbank did have two sends spaced two weeks apart for a product launch in weeks 22 and 24, and the unsubscribe rate on the second was roughly double the usual. That is one observation, not evidence, but it is a warning. So the memo said: expected gain 260 to 650 trials a year, the low end assuming each extra send delivers only 60 percent of the current effect, with the risk on the unsubscribe side. And it said how to find out: split the list at random, half on three weekly, half on monthly, run it for twelve weeks and compare trials, unsubscribes and revenue. The split test is the correct tool for the part the model cannot see, and I have written a complete guide to marketing testing methods if you want the design details.
Why not fortnightly? Because at two weeks the previous send is only 79 percent through, the overlap is meaningful, and the one piece of frequency evidence we had pointed the wrong way. Three weeks is where the curve, the evidence and the writer's calendar agreed.
Where adstock fits in
If you have met adstock in media mix modelling, you have met a distributed lag with a very strict shape. Adstock assumes the effect decays geometrically: with a single retention rate between 0 and 1. The effect is largest immediately and shrinks by the same proportion every week. One parameter for the whole curve is wonderfully economical with twelve channels and 156 weeks, and wrong whenever the peak is not at lag 0. Werkbank's peak is at lag 1; a geometric decay cannot produce that hump and would put too much weight on the send week and too little on the following two. The Almon polynomial is the more flexible cousin: a few parameters, any smooth shape.
How to run it yourself
Data you need: one row per week, at least 60 weeks and preferably 100 or more, with the outcome (trials, orders, enquiries), the marketing action in a sensible unit (thousands of emails, catalogue copies, pounds of spend), and the controls that also move the outcome: paid search spend, price changes, holiday and school break flags, a linear trend, perhaps a launch dummy. Weekly is the right grain for email; daily is too noisy and monthly hides the curve entirely.
The steps, as I run them:
The estimation loop. Most of the time goes into the weekly table and the controls, not the regression.
In Python with statsmodels it is short:
import numpy as np, pandas as pd, statsmodels.api as sm
L, p = 5, 3 # lag length, polynomial degree
x = df["emails_k"] # emails sent per week, in thousands
for j in range(p + 1): # Almon columns w_j = sum_k k^j x_{t-k}
df[f"w{j}"] = sum((k ** j) * x.shift(k) for k in range(L + 1))
cols = [f"w{j}" for j in range(p + 1)] + ["paid_search", "holiday", "trend"]
X = sm.add_constant(df[cols])
fit = sm.OLS(df["trials"], X, missing="drop").fit(cov_type="HAC", cov_kwds={"maxlags": 4})
a = fit.params[[f"w{j}" for j in range(p + 1)]].to_numpy()
beta = np.array([sum(a[j] * k ** j for j in range(p + 1)) for k in range(L + 1)])
print(np.round(beta, 2), "total:", round(beta.sum(), 2))
The HAC standard errors matter: weekly residuals are autocorrelated, and plain OLS standard errors will flatter you. Check the residual autocorrelation; if it is strong, add a lagged outcome or model the errors, and treat the total's interval with more suspicion.
Before you trust it, hold out. Fit on the first 66 weeks, forecast the last 12, compare:
| Week | Emails (000s) | Actual trials | Forecast | Error |
|---|---|---|---|---|
| 67 | 31 | 101 | 95 | 6% |
| 68 | 0 | 98 | 104 | 6% |
| 69 | 0 | 91 | 94 | 3% |
| 70 | 0 | 86 | 80 | 7% |
| 71 | 0 | 64 | 68 | 6% |
| 72 | 29 | 97 | 92 | 5% |
| 73 | 0 | 93 | 100 | 8% |
| 74 | 0 | 99 | 93 | 6% |
| 75 | 0 | 72 | 77 | 7% |
| 76 | 30 | 90 | 95 | 6% |
| 77 | 0 | 108 | 103 | 5% |
| 78 | 0 | 89 | 94 | 6% |
Mean absolute percentage error about 6 percent, against 14 percent for a seasonal baseline that ignores email. More importantly, look at the shape: weeks 68 and 73, one week after a send, are the high weeks in both actual and forecast, and week 71, four weeks after, is the trough in both. The model has the timing right, which is the thing you are going to act on.
How long does this take? With a clean weekly table, an afternoon. Building the weekly table from a mail platform export, an analytics export and a finance sheet, and agreeing what counts as a trial, is a week.
Pitfalls
Regular cadence, collinear lags. I said it above and I will say it again because it is the most common reason the unrestricted model fails and the Almon model is silently misspecified: if you always send on the first Tuesday, lag 0 and lag 4 or 5 are nearly the same variable. Vary the send date by a week now and then.
Smoothness is an assumption. The polynomial cannot draw a cliff. A flash sale that ends on Sunday has an effect that is large for six days and exactly zero on Monday; a cubic will smear that into the following week and invent a tail that is not there. For hard deadline promotions, use short unrestricted lags at daily grain, or model the deadline explicitly.
Something else changed that week. Werkbank's biggest trial week in the sample was not an email week; it was the week a trade magazine ran a review. If that is not in the controls, the model will try to explain it with whatever email was nearby and the lag curve gets a phantom bump. Keep a log of everything that happened, and put the big ones in as dummies.
Reverse timing. Marketers send when they expect demand: before the busy season, after a product launch. If sends are timed to anticipated trials, the lag model will credit email with trials that were coming anyway. Controls for seasonality help; an honest holdout helps more; a randomised send timing test settles it.
Weekly boundaries. A Thursday send puts three days of lag 0 in the send week and four in the following week, so the "peak at lag 1" is partly a calendar artefact. If you send on a fixed weekday, define your analysis weeks to start on that weekday. It sounds pedantic; it moves the peak.
How I do this for clients
The deliverable is a lag curve you can act on, not a regression printout. I need a weekly export from your email or campaign tool (sends, opens, unsubscribes), the outcome from your product or shop database (trials, orders, enquiries) and whatever else you spent money on week by week, plus a calendar of launches, price changes and anything unusual. Sixty weeks is the floor; if you have less, I will say so and we will talk about what can honestly be learned from it.
It starts with a free workshop where we agree the question (for Werkbank it was "how often should we send?"), the outcome that counts, and where the data lives. Then I do two weeks of real work at my own risk: the weekly table, the model, the holdout, and a first draft of the curve. If the data cannot support the answer, you hear that at the end of the two weeks and owe nothing.
What you get is a one page decision memo with a number and a risk (for Werkbank: 4.3 trials per 1,000 emails with its interval, the three weekly recommendation, the expected gain and the unsubscribe risk), the fitted model as a notebook you own and can rerun each quarter, and a small dashboard that answers one question: how much of last month's trials did email deliver, and when. If you want the split test run and read as well, that is part of my performance marketing work; the modelling itself sits under data science. Pricing is on the pricing page in plain terms: a fixed fee for the modelling, and for ongoing growth work a commission based option where I earn when the trials turn into revenue.
Questions to ask whoever measures your marketing
- How many weeks after a send do you keep counting its effect, and why that number?
- Can you show me the lag curve, not just a conversion rate, for our last twelve campaigns?
- What controls are in the model, and is the trade press review from March in there?
- Did you hold out the last quarter and forecast it before telling me the model works?
- What is the confidence interval on the total effect, and would the decision change at the low end?
- Is our send calendar so regular that the lags cannot be separated, and should we vary it?
- Does the cadence recommendation account for fatigue and unsubscribes, or only for the curve?
This series is inspired by Mike Grigsby's Marketing Analytics (Kogan Page). The explanations, examples and numbers here are my own.