Simultaneous equations: when marketing causes sales and sales cause marketing
Most small companies set next month's advertising budget from this month's sales, and then ask a regression what the advertising did for sales. The regression answers confidently and wrongly, because the two variables cause each other and a single equation cannot tell the directions apart. This chapter opens the interrelationship part of the series with simultaneous equations: why the feedback loop biases ordinary least squares in a direction you can predict, what unbiased, consistent and efficient really mean when you have to choose between them, how the reduced form and two stage least squares recover the true effect, and how to tell whether your data can identify it at all. The worked example is Werkbank, a SaaS for craft businesses whose founder pays for ads out of last month's invoices; the single equation overstates her ad effect by about 40 percent. There is a practical guide to finding instruments in ordinary marketing data, working code, and the checks I run before I trust the number. This is part 11 of 21 of the Marketing Analytics series.
The founder who paid for her ads out of last month's invoices
Miriam runs Werkbank, a Rails SaaS that gives plumbers, joiners and electricians one place for their calendar, their quotes and their invoices. Plans start at €29 a month, a new customer is worth roughly €600 in first year revenue, and she signs between 20 and 45 of them a month. Her advertising budget rule is simple and, on the face of it, sensible: next month's Google and Meta spend is 25 percent of this month's new bookings. Good month, more ads. Slow month, tighten the belt. Halfway through each month she looks at the dashboard and either tops the campaigns up or pauses them for a week.
After three years of this she asked me a fair question: what does one euro of advertising actually bring back? Her agency had regressed monthly new bookings on ad spend and reported €2.10 of new business per euro spent, with a t statistic you could hang a coat on. Then they proposed doubling the budget. I did not doubt their arithmetic. I doubted the model, because in Miriam's business ad spend does not simply cause bookings. Bookings cause ad spend; it is her rule, written down in a spreadsheet. When two variables cause each other, a single regression line is quietly wrong, in a direction you can predict. In her case it flatters the ads by about 40 percent. The numbers in this article are illustrative; the mechanism is not.
Where this sits in the series
This is chapter 11 of 21 and the opening of part three, the interrelationship techniques (chapters 11 to 14). In part two we always had one dependent variable on the left and a list of causes on the right; the last of those chapters was Forecasting demand: autocorrelation, seasonality and honest error bands, and its lesson about shocks that linger from one month into the next matters again here. From now on the variables relate to each other rather than lining up in one direction. Next comes Principal components and factor analysis for marketers, where many variables move together without any one being the outcome. This chapter is the bridge: two outcomes, each also a cause.
Budget rules build feedback loops, and marketing is full of them
Simultaneity is the polite term for two variables determining each other within the same period. Marketing produces it constantly, almost always through perfectly reasonable management decisions. Budget as a share of revenue is the most common: sales set the spend, the spend moves sales. Price and quantity is the oldest: a shop lowers prices when stock is slow, demand rises when prices are lower, and observed over time the two are a jumble of both effects, which is why naive price elasticities so often come out too small or with the wrong sign. Automated bidding is the newest: a target ROAS strategy raises bids where conversions are likely, conversions rise where bids are higher, and the platform builds the loop for you at auction speed.
Here is Miriam's loop drawn out. The dangerous arrow is the one from the unobserved shock, because it reaches ad spend through bookings.
The Werkbank system: bookings and ad spend point at each other, and whatever pushes bookings this month pushes spend too.
You might object that a strict version of Miriam's rule uses last month's bookings, already in the books when this month's budget is set, so the loop should be broken within any single month. In principle, yes. Two things spoil it. First, she reacts mid month, so this month's bookings do feed this month's spend. Second, the unobserved things that push bookings up (a competitor's outage, a mention in a trade magazine, a wholesaler recommending the product) tend to last longer than a month, so last month's shock is still alive this month and also sitting inside last month's bookings. The autocorrelation from the previous chapter is precisely the reason a lag alone does not save you.
Why the single regression is biased, first in words, then in symbols
Write the system down honestly. Two equations, one for each variable that is both cause and effect:
In the first equation, is new bookings in euros in month , is ad spend in the same month, is the number of organic signups arriving from the software directory listing and word of mouth, is a January indicator (craft businesses reorganise in January, every year) and is everything else that moved bookings that month. The number we want is : euros of new bookings per euro of ads. In the second equation, is Miriam's mid month reaction, is the 25 percent rule applied to last month's bookings , is the cash balance at the start of the month (she does not top up when the account is thin) and is her mood, her holidays and whatever else nudges the budget.
Now suppose a trade magazine mentions Werkbank in March. That is a positive : bookings are higher than ads and signups would predict. Miriam sees a strong month and tops up the campaigns, so rises as well. The regression sees a high and a high in the same row and hands the credit to the ads, and under her rule it does this every month. Formally, ordinary least squares converges to
The second term is the simultaneity bias. is the covariance between spend and the booking shock, positive whenever because the shock travels into spend through the reaction, and is the variance of spend. The bias grows with and with the size of the shocks, and shrinks as spend varies more for its own reasons. Notice what is missing: the sample size. Thirty six months or three hundred and sixty, the same wrong answer with an ever tighter standard error around it. More data makes a biased estimator more confidently wrong.
Three words statisticians use about estimators, and the one you should care about
An estimator is unbiased if, across many repeated samples, it lands on the true value on average. It is consistent if it converges to the true value as the sample grows. It is efficient if, among estimators of its class, it has the smallest variance. A kitchen scale that always reads 200 grams heavy is precise and biased. A scale that wobbles but averages right is unbiased and inefficient. You would rather have the second one, and so would your accountant.
Under simultaneity, OLS is neither unbiased nor consistent. It is very efficient at estimating the wrong thing. Two stage least squares, which we are about to build, is consistent but not unbiased in small samples, and less efficient than OLS: the standard errors are wider, sometimes a lot wider. That is the trade, a precise wrong number for a fuzzy right one, and in marketing you take it every time, because "1.50, plausibly between 0.5 and 2.5" is a better basis for a budget decision than "2.10 plus or minus 0.6" around a centre that is not there. I have written before about how correlation dresses up as causation; simultaneity is that problem with the arrow pointing both ways.
The reduced form: what the exogenous variables alone can tell you
Substitute the spend equation into the booking equation and the other way around, then collect terms. Both endogenous variables end up expressed only through the things decided outside the system:
This is the reduced form. Each is a knot of structural coefficients, for instance and , and the terms are mixtures of and . The right hand sides contain only exogenous variables, so each reduced form equation can be estimated by ordinary least squares without embarrassment. Now look at the ratio: . The effect of last month's bookings on this month's bookings, divided by its effect on this month's spend, is the effect of spend on bookings. The budget rule moves spend for a reason that has nothing to do with this month's shock, so whatever bookings do in response is the ad effect, cleanly. That is the whole idea of an instrument. With two excluded variables, and , you get two such ratios and have to reconcile them, which is what two stage least squares does in an organised way.
Identification: can the data even tell the two directions apart?
Imagine you only had and . A cloud of points, two lines through it, and no way of knowing which line is the booking equation and which the spend equation. The system would be unidentified, and no amount of data would fix it. What identifies an equation is a variable that is excluded from it and present elsewhere in the system. The order condition says it as a count: for each equation, the number of exogenous variables excluded from it must be at least the number of endogenous variables on its right hand side. With the usual letters,
where is the number of exogenous variables in the whole system, the number of them in the equation you want to estimate, and the number of endogenous variables in that equation including the one on the left. For the booking equation: four exogenous variables in the system, two of them in the equation, so ; two endogenous variables, so . Identified, in fact overidentified, which is good news because it lets us test the instruments against each other. The spend equation excludes and and has one endogenous regressor: identified as well.
The order condition is necessary but not sufficient; a rank condition behind it says the excluded variables must actually move the endogenous variable, which in practice comes down to the first stage F statistic below. But the deeper point is not statistical at all. "Excluded" is a claim about the world. It says Miriam's opening cash balance does not itself change how many joiners buy scheduling software this month, other than through the ads it pays for. That is a statement about joiners, not about data, and you have to say it out loud. If a colleague laughs, find a different instrument.
Two stage least squares, step by step
Stage one: regress on every exogenous variable in the system, meaning , , and , and keep the fitted values . They are the part of ad spend explained by the budget rule, the cash position and the calendar, none of which knows about this month's booking shock. Stage two: regress on , and . The coefficient on is the two stage least squares estimate of . In matrix form the whole thing is one line:
Here is the vector of bookings, holds the regressors of the booking equation (a constant, , , ), holds all the exogenous variables plus the constant, and is the projection onto the space spanned by the instruments. Multiplying by replaces the spend column with its first stage fit and leaves the exogenous columns as they were, because they are already in . One practical warning: if you run the two stages by hand as two separate regressions, the standard errors printed after stage two are wrong, because they come from residuals that use instead of . Every serious package corrects this. Use one.
The procedure as I actually run it, including the two exits where you go back rather than forward.
The Werkbank numbers, line by line
Thirty six months of Miriam's data. Over the period she averaged €18,400 of new bookings a month, €4,600 of ad spend, 31 organic signups and an opening cash balance around €41,000. The booking equation, estimated both ways:
| Term | OLS estimate | OLS std error | 2SLS estimate | 2SLS std error |
|---|---|---|---|---|
| Intercept (€) | 4,120 | 1,480 | 5,860 | 1,930 |
| Ad spend (€ of bookings per € spent) | 2.10 | 0.31 | 1.50 | 0.52 |
| Organic signups (€ per signup) | 96 | 28 | 112 | 34 |
| January (€) | 2,300 | 940 | 2,410 | 1,060 |
| R squared | 0.71 | 0.64 | ||
| First stage F on the two instruments | 18.4 | |||
| Hansen J test of overidentification, p value | 0.41 |
Reading it from the top. The intercept is a month with no ads, no organic signups and no January; it is larger under 2SLS because ads are given less credit, so more of the baseline stays in the baseline. The ad row is the headline: €2.10 per euro under OLS, €1.50 under 2SLS, so the single equation overstated the effect by 40 percent. The standard error nearly doubled, from 0.31 to 0.52. That is the efficiency we gave up, and I would rather have a 95 percent band from roughly 0.5 to 2.5 around the right centre than a tight band around the wrong one. Organic signups gain a little, from €96 to €112 per signup, because some of the revenue OLS had handed to ads belonged to the organic channel, which happened to be busy in the same months. January barely moves: nothing in the feedback loop is about the calendar.
The bottom three rows are the checks. R squared falls under 2SLS, and it should; 2SLS does not maximise fit, and a higher R squared for OLS is not evidence in its favour. The first stage F of 18.4 says the two instruments explain enough of the variation in spend to be useful; anything under 10 is weak. The Hansen J test asks whether the two instruments tell the same story about ; a p value of 0.41 means they do, within noise. Had it been 0.01, one of them would be lying and I would have had to decide which.
The second equation is less glamorous, but it tells you whether the model understood the business:
| Term | OLS estimate | 2SLS estimate |
|---|---|---|
| Intercept (€) | 380 | 610 |
| Bookings this month (€ of spend per €) | 0.21 | 0.11 |
| Bookings last month (€ of spend per €) | 0.19 | 0.24 |
| Opening cash balance (€ of spend per €) | 0.012 | 0.014 |
OLS claims Miriam reacts to the current month with 21 cents of extra spend per euro of bookings; 2SLS says 11 cents, much closer to what she describes as "a modest top up if it is going well". The 25 percent rule shows up as 0.24 under 2SLS, almost exactly the stated policy, while OLS put it at 0.19 because it had stolen part of the rule's credit for the same month. Cash matters a little: about €1.40 of extra spend per €100 in the account. When the estimated system reproduces the rules the founder actually follows, I start trusting the estimated effect of the rules. And the overstatement scales with the reaction: simulate the same system with a 20 cent reaction instead of 11 and OLS reports about 2.70 for a true 1.50.
What did Miriam do with this? Not double the budget. At €1.50 of first year bookings per euro and roughly 80 percent gross margin, a euro of ads returns about €1.20 of contribution in year one. Fine, but not the licence to print money that 2.10 implied, and the curve bends downwards at higher spend as every channel's does. She stepped the budget up by 30 percent, and we ran a geographic holdout on Meta to check the 1.50 against something that needs no instrument at all. I have written about five ways to prove a campaign actually worked; a holdout is the first of them, and an estimate from observational data is a hypothesis for the holdout, not a substitute.
How to run it yourself
You need monthly data (weekly if you have the volume, and then more care about seasonality), at least 36 periods, ideally 60. For each period: the outcome, spend by channel, the exogenous drivers of the outcome you can measure (organic signups, calendar indicators, price changes), and the inputs to the budget decision as they were actually used (the lagged outcome, cash, the annual plan). Write the budget rule down before you look at any regression output. If nobody can, interview whoever sets the budget for twenty minutes; the rule exists even if it is a habit.
In Python the whole estimation is a few lines with the linearmodels package:
import pandas as pd
from linearmodels.iv import IV2SLS
df = pd.read_csv("werkbank_monthly.csv", parse_dates=["month"]).set_index("month")
df["bookings_lag1"] = df["bookings"].shift(1)
df["jan"] = (df.index.month == 1).astype(int)
df = df.dropna()
model = IV2SLS(
dependent=df["bookings"],
exog=df[["organic_signups", "jan"]].assign(const=1.0),
endog=df["ad_spend"],
instruments=df[["bookings_lag1", "opening_cash"]],
)
res = model.fit(cov_type="kernel") # HAC standard errors for monthly data
print(res.summary)
print(res.first_stage) # partial F for ad_spend
print(res.sargan) # overidentification test
print(res.wu_hausman()) # does 2SLS actually differ from OLS?
In R the same model is one call to ivreg with the instruments listed after a vertical bar. Whatever the tool, the checks before you trust the number are the same five. First stage F above 10. The overidentification test not rejecting. The Wu Hausman test rejecting, because if OLS and 2SLS do not differ you should say so and keep the simpler model. No residual autocorrelation, or HAC standard errors and a longer lag if there is. And a plot of fitted spend against actual spend, so you can see how much of the variation the instruments explain. Time: a week to assemble and clean the data, a day for the model, and a week of arguing about instruments, which is the week that matters.
Finding instruments in marketing data
The instrument question is where most attempts die, so here is what actually works, roughly in the order I reach for it. Written budget rules are the best instruments there are, because the rule is a mechanical link between something in the past and spend today, and you can read the exclusion restriction off the spreadsheet: lagged revenue, lagged margin, a share of last quarter's cash flow. Second, financial constraints: opening cash, card limits, a fiscal year budget that resets in April, the quarter end freeze the finance director imposes. Third, platform accidents: an account suspension, a tracking outage that left automated bidding blind for three weeks, a policy change that disapproved half the creatives. Fourth, with regional data, reach caps create uneven local exposure from a single national campaign, and that unevenness is close to random. Fifth, people: the founder's holiday, an agency handover, a maternity cover who did not touch the campaigns.
Now the ones that look like instruments and are not. The cost per click index in your category seems ideal, since competitors' bidding moves your cost and you did not choose it. But it changes what a euro of spend buys, so it belongs in the outcome equation, and an instrument that belongs in the outcome equation is not an instrument. Competitors' spend affects your demand directly. Weather affects both spend and demand for most seasonal businesses. Above all of these sits the one instrument that needs no argument: a randomised holdout. If you can switch spend off in a random set of regions or weeks, do that, and use this chapter to make sense of the years when you did not.
Pitfalls
Weak instruments are the classic failure. When the first stage F is low, 2SLS is biased towards OLS, the very thing you were trying to escape, and its sampling distribution is wide and oddly shaped, so the reported standard errors understate how little you know. The honest response is to find better instruments or to say that the data cannot answer the question.
Instruments that fail exclusion are worse, because nothing in the output warns you. The Hansen J test compares instruments with each other; if they are all wrong in the same direction it passes happily. The only protection is the argument you make in plain language about why this variable cannot reach the outcome except through spend, and the willingness to lose that argument.
Lingering shocks poison lagged instruments. If the booking residuals are autocorrelated, last month's bookings carry this month's shock and the instrument is contaminated. Check the residual autocorrelation as in the previous chapter, and see whether the estimate holds up with a two month lag. If it moves a lot, say so in the memo.
Small samples give wide bands, and the temptation is to trim instruments or controls until the band looks presentable. Resist it. Thirty six months is thin for this; the wide band is the result, and a decision maker who is told "between 0.5 and 2.5" can act sensibly on it, whereas one who is told "1.50" after you quietly removed an instrument cannot.
The functional form is still your problem. Two stage least squares fixes the direction of causation, not the shape of the response; if ad effects saturate, a linear system overstates the return at high spend even after the simultaneity is dealt with. And the system is the business as it was run: if Miriam changes her rule next year, the spend equation changes and so does the identification strategy. Re estimate when the rules change, and treat the number as a working figure, not a constant of nature.
How I do this for clients
The data I ask for is unglamorous: three to five years of monthly outcomes from the accounting system, spend by channel from the ad platforms, whatever exogenous drivers you can export (organic signups, price lists, calendar), and the budget rule as it was actually applied, including the informal parts. The first month starts with the free workshop, where we draw your feedback loop on a whiteboard and list every rule and habit that sets spend. Then two weeks of real work on my account, not yours: I assemble the system, test the instruments, run the checks above and come back with a first estimate and an honest statement of whether the data can support it.
What you get is a model in your own repository (you own everything I build, and it runs without me), a two page decision memo with one number, its band and the single biggest risk to it, and a small dashboard that answers one question: what is a euro of advertising worth this quarter, and how sure are we. Where it makes sense I also propose a budget rule that keeps the data readable in future, typically a planned holdout or a pre committed step change, because the best instrument is one you designed. This is data science work at its core, and it pairs naturally with performance marketing if you want the same person to run the campaigns and be accountable for the number. Pricing is a fixed fee for a defined piece of work or a commission on growth, explained plainly on the pricing page. No vanity metrics, and every number comes with its error margin attached.
Questions to ask whoever built your marketing model
- Is there anything in our business, written or habitual, that sets marketing spend from sales? If yes, how did the model account for it?
- Did the model treat spend as something that happened to us, or as something we chose in response to results?
- What are the instruments, and would a sceptical colleague accept that they cannot reach sales except through spend?
- What is the first stage F, and what happens to the estimate if the weakest instrument is dropped?
- How far did the answer move between the single equation and the system?
- What is the band around the number, and does the recommendation survive the bottom of it?
- Have we tested the estimate against a holdout since, and when will we?
This series is inspired by Mike Grigsby's Marketing Analytics (Kogan Page). The explanations, examples and numbers here are my own.