![[Research] We benchmarked four geo-experimentation packages on 8,000 simulated panels with known ground truth. None achieved nominal 95% coverage without substantially missing real effects.](https://external-preview.redd.it/n2lJKQR3gNyMqa1XU0hUXm9RGO6r_Qgf02wkj50sX2w.png?width=1080&crop=smart&auto=webp&s=cf31a13a43cadb099d280c2a5e70a0f14b20f4d3)
[Research] We benchmarked four geo-experimentation packages on 8,000 simulated panels with known ground truth. None achieved nominal 95% coverage without substantially missing real effects.
Our research team benchmarked four open-source incrementality packages: CausalPy (Bayesian synthetic control), Meta GeoLift (augmented synthetic control with conformal inference), Google Matched Markets (time-based regression), and CausalImpact (Bayesian structural time series). We simulated panels where the true treatment effect is known and the headline result was that no tool delivered nominal 95% coverage together with adequate power. Coverage here means the share of runs where the tool's 95% interval contains the true effect we injected in the data.
We ran this study because a lot of practitioners treat these tools as interchangeable, yet none of them can be sense-checked on real data because the counterfactual is unobservable. On synthetic data the truth is known, so calibration and power stop being matters of opinion and become things that can actually be measured.
The tools we studied split into the following groups:
- Meta GeoLift was the only one near nominal coverage (92–95%) with false positive rates of 3–5% on null data, but its intervals were wide enough that it failed to reject zero in 89–96% of runs where a true 7.5% lift existed.
- CausalImpact had the most power (false negative rate 34–48%) but 70–72% coverage, false positive rates of 28–30%, and a consistent upward bias of +1.87 to +4.21 percentage points.
- Matched Markets and CausalPy landed in between, with 76–86% coverage, false positive rate 14–25%, under-covered and under-powered at the same time.
We ran four scenarios in the study that stress test different conditions. There’s a clean baseline (20 donors, 90 pre-treatment days), a 5x outlier treated geo, a 9-donor pool, and a 30-day pre-period. Then we ran 1,000 iterations per scenario × effect condition with all four tools fit on identical panels, which yielded 32,000 model fits in total.
One methodological finding worth flagging is that CausalPy's default observation-noise prior (HalfNormal(sigma=1)) assumes roughly unit-scale residuals. On data at realistic sales magnitudes its false positive rate was 86%+ across all scenarios until we standardized each series against its pre-period mean and SD (then back-transformed). After that it was the least biased estimator in the outlier scenario. This is worth knowing if you use PyMC-based tools on raw KPIs.
A few honest limitations in the study are that a single DGP with shared trend/seasonality means parallel trends holds by construction, which favors synthetic-control methods and likely flatters every tool relative to real data. Moreover, we have just one non-null effect size (7.5%) and relatively short post-period. All of this is in the report's limitations section.
The three things I'd take from this study are: (1) coverage and power have to be judged together, since a tool can keep its 95% promise and still be useless for detection (GeoLift hits 95.1% coverage in the short pre-period scenario with a 95.7% false negative rate); (2) check what scale your estimator's priors assume before fitting, a default is a modeling decision someone else made for different data; (3) before any of these tools informs a real budget decision, you should run it on synthetic data where you know the answer.
Everything in the study is reproducible and we created a Makefile that runs the whole pipeline:
- Code: https://github.com/getrecast/geolift-simulation-study
- Full report: https://research.getrecast.com/geolift-sim-study
Disclosure: I co-founded Recast (marketing planning & analysis). The study covers open-source tools only. If you think the DGP should be harder (idiosyncratic geo trends, heavier tails, spillovers) the generator is parameterized, and I'd honestly like to see those runs!