Skip to content
echogeco
Measurement · Experiments

Sample size for a conversion lift test

Turn a baseline, the lift that matters and the share held out into the total audience a lift test needs, and read the weeks off the result.

codemediumExercise · 4 min · 34 of 60
On this page

A lift test sized as if the split were 50/50 and run with a 5% holdout is a test that was never going to see anything. The function below sizes it for the split it will actually run with, as holdouts, geo tests and power works by hand.

The situation

The growth team plans conversion lift tests on three paid channels a quarter. Its planning sheet sizes every test per arm, assuming equal groups, but the team asks the ad platforms for a 5% or 10% holdout to protect sales. Last quarter a test sized at 81,000 per arm, the lesson's 2.0% to 2.2% example, ran on 162,000 people with 10% held out. It could only have seen a lift of about 16%, read "not significant", and the channel was cut.

Assume a two-sided 5% significance level and 80% power, with z values from the standard normal distribution (1.96 and 0.84), and the lesson's formula for unequal groups, where p₁ is the held-out rate, p₂ = p₁ × (1 + lift) and h is the share held out:

total people = (z_α/2 + z_β)² × [p₁(1 − p₁) ÷ h + p₂(1 − p₂) ÷ (1 − h)] ÷ (p₂ − p₁)²

Round the total up to the next 1,000, never down: a test smaller than its size has less power than promised. The paid-social program reaches 2 million people a month, converts 0.10% of them without ads, and the lift that changes its budget is 15%.

The question

Write the function, then use it to decide which holdout share answers the paid-social question inside one quarter.

def solve(baseline, relative_lift, holdout_share=0.5, alpha=0.05, power=0.80):
    """Total people (held out plus exposed) a conversion lift test needs.

    baseline: the held-out group's conversion rate, 0 < p < 1 (0.02 for 2%).
    relative_lift: the lift to detect, as a fraction of the baseline (0.10 for +10%).
    holdout_share: the share of the audience that sees no ads, 0 < h < 1.
    alpha, power: two-sided significance level and power.
    Returns an int: the total, rounded UP to the next 1,000.
    """
solve(0.02, 0.10)          ->  162000
solve(0.02, 0.10, 0.05)    ->  814000
solve(0.001, 0.15, 0.05)   ->  7392000
solve(0.001, 0.15, 0.20)   ->  2244000

A strong answer · Rubric · Where answers go wrong · Solution

Write your answer first, then open