A/B testing and experiments
An A/B test is the cleanest way to find out whether a change really caused an improvement. Learn how to design one, how to read a p-value in plain terms, how much data you need, and the mistakes that produce false wins.
Brew & Bean wants more people who open the pickup-ordering page to actually place an order. The designer suggests changing the button from "Place order" to "Order now, pick up in 10 minutes". Will it help?
You could change it and compare this month with last month, but many things differ between months: weather, exams, festivals, offers. An A/B test removes that problem by running both versions at the same time and choosing randomly who sees which.
The basic idea
Parts of an A/B test
| Term | Meaning | Example |
|---|---|---|
| Control (A) | The current version | Button says "Place order" |
| Variant (B) | The changed version | Button says "Order now, pick up in 10 minutes" |
| Randomisation | Each visitor is assigned to A or B by chance | Visitor ID decides, 50/50 |
| Primary metric | The one number that decides the test | Conversion rate: orders divided by visitors who opened the page |
| Guardrail metric | Something that must not get worse | Average order value, cancellations, page load time |
| Hypothesis | A testable prediction with a reason | "A clear pickup promise will raise conversion because customers worry about waiting" |
Because assignment is random, the two groups are alike in everything except the change. So any lasting difference in the metric can be credited to the change. This is what lets an experiment prove cause, which a simple before-and-after comparison cannot.
Designing the test
Before you launch
- 1Write the hypothesis and pick one primary metric. Decide guardrail metrics too.
- 2Define who is included (for example, everyone who opens the order page) and the unit of randomisation (usually the user, so one person always sees the same version).
- 3Choose the smallest improvement worth caring about. This is the minimum detectable effect.
- 4Work out the sample size you need (see below) and how many days that takes. Run for whole weeks so weekdays and weekends are balanced.
- 5Write down the decision rule in advance: what result means ship, keep testing, or stop.
- 6Check the setup: both versions work, traffic really splits about 50/50, and events are being recorded.
Reading the result: significance in plain English
Suppose 1,000 people see A and 100 order (10%). Another 1,000 see B and 125 order (12.5%). B looks better. But if you showed the same page to two random groups of 1,000, the conversion rates would differ a little by luck alone. The question is: is this gap bigger than luck would usually produce?
The p-value answers a narrow question: if there were truly no difference between A and B, how often would we see a gap this large or larger just by chance? A small p-value (the common cut-off is 0.05) means the gap would be unusual under pure chance, so we call the result statistically significant.
The p-value is not the probability that B is better, and a result with p below 0.05 does not mean the effect is large or important. Always look at the size of the difference too. A confidence interval gives a range of plausible values for the real difference and is more informative than the p-value alone.
from math import sqrt, erf
def normal_cdf(z):
return 0.5 * (1 + erf(z / sqrt(2)))
def two_proportion_test(conv_a, n_a, conv_b, n_b):
"""Two-sided z-test for the difference between two conversion rates."""
p_a = conv_a / n_a
p_b = conv_b / n_b
pooled = (conv_a + conv_b) / (n_a + n_b)
se = sqrt(pooled * (1 - pooled) * (1 / n_a + 1 / n_b))
z = (p_b - p_a) / se
p_value = 2 * (1 - normal_cdf(abs(z)))
return p_a, p_b, z, p_value
def sample_size_per_group(baseline, min_lift):
"""Rule of thumb for 5% significance and 80% power."""
return round(16 * baseline * (1 - baseline) / min_lift ** 2)
# 1,000 visitors each: 100 orders vs 125 orders
p_a, p_b, z, p = two_proportion_test(100, 1000, 125, 1000)
print(f"A: {p_a:.1%} B: {p_b:.1%} z = {z:.2f} p-value = {p:.3f}")
# Same rates with 4,000 visitors each
p_a, p_b, z, p = two_proportion_test(400, 4000, 500, 4000)
print(f"A: {p_a:.1%} B: {p_b:.1%} z = {z:.2f} p-value = {p:.4f}")
# Visitors needed per group to detect a 2 percentage point lift from 10%
print(sample_size_per_group(0.10, 0.02))Uses only the Python standard library. Save as ab_test.py and run with python ab_test.py.
A: 10.0% B: 12.5% z = 1.77 p-value = 0.077
A: 10.0% B: 12.5% z = 3.54 p-value = 0.0004
3600Look at the first two lines. The rates are identical (10% and 12.5%), but with 1,000 visitors per group the result is not significant (p = 0.077) and with 4,000 per group it is clearly significant. More data makes real differences easier to separate from luck. With too little data, you cannot tell.
The last line says: to detect a lift from 10% to 12% with decent reliability you need about 3,600 visitors per group. That formula is a rough rule of thumb; real tools use more exact calculations, but it shows the point. Small improvements need a lot of traffic.
Power, and why sample size is decided first
Power is the chance your test will detect a real effect of the size you care about. A common target is 80%. A test with low power often ends with "not significant", which wrongly feels like "no effect". It really means "we couldn't tell". That is why you calculate the sample size before the test and not after.
Common mistakes
Peeking and stopping early
If you check the p-value every day and stop the moment it dips below 0.05, you will get false wins far more often than 5% of the time, because the p-value wanders up and down by chance. Decide the sample size or duration in advance and read the result at the end. (Some tools offer sequential tests designed for continuous monitoring; use those only if you understand how they work.)
Mistakes to avoid
| Mistake | Why it hurts | Fix |
|---|---|---|
| Testing many metrics and reporting the one that won | With 20 metrics, one will look significant by luck | One primary metric chosen in advance; treat others as extra clues |
| Running the test only on weekdays or only a few days | Behaviour differs by day, so the groups are not representative | Run whole weeks |
| Not randomising (A on Monday, B on Tuesday) | Day effects get mixed up with the change | Assign at the same time, randomly |
| Ignoring a broken split (60/40 instead of 50/50) | Signals a bug that can bias the result | Check the split before trusting results |
| Declaring victory on a tiny, unimportant lift | Significant is not the same as useful | Compare to the minimum effect worth acting on, and to the cost |
| Changing several things in B | You won't know which change worked | Change one thing, or test combinations deliberately |
A test can also tell you B is no better than A, and that is a useful answer: you avoided shipping a change that did nothing. Small businesses with little traffic often cannot run a precise A/B test; they can still run simple trials, such as one outlet or one week with a change, but should be honest that those are weaker evidence.
How this comes up in interviews
Product and data analyst interviews often ask: "How would you test this change?", "What metric would you choose and why?", "The test shows p = 0.04 but the lift is tiny; do you ship?", or "How long would you run it?". Strong answers state the hypothesis, one primary metric plus guardrails, randomisation unit, sample size and duration, and a decision rule. They also mention peeking and multiple metrics as risks.
I want to run an A/B test for [business or product]. The change is [describe the change]. Our current baseline for [metric] is about [number] and we get about [number] visitors per week.
Help me plan: (1) a hypothesis, (2) the primary metric and two guardrail metrics, (3) the unit of randomisation, (4) roughly how many visitors per group I need and how many weeks that takes, showing the formula, (5) a decision rule, (6) risks that could make the result misleading.What to expect: Ask the AI to show its sample size calculation and check it against the rule of thumb in this lesson. If the weeks needed are too long, reduce ambition: test a bigger change or accept a weaker trial.
Try it: Does it deserve a win?
Using the code in this lesson, change the numbers and answer: 1. 50 orders from 500 visitors on A versus 62 from 500 on B: is B significantly better? 2. How many visitors per group would you need to detect a lift from 5% to 6% conversion? 3. Your teammate says 'we peeked on day 3 and p was 0.03, so let us ship'. What do you say?
Key takeaways
- An A/B test randomly splits users between control and variant at the same time, so differences can be credited to the change.
- Decide the hypothesis, one primary metric, guardrails, sample size and decision rule before launching.
- A p-value shows how surprising the gap would be if there were no real difference; it does not say how big or how important the effect is.
- Small effects need a lot of data; an underpowered test cannot tell you much.
- Do not peek and stop early, and do not hunt through many metrics for a winner.
- Not significant means 'we can't tell', not 'there is no effect'.
Check yourself
Finishing the quiz marks the lesson as done.
1. Why is 'compare this month with last month' weaker than an A/B test?
2. A test gives p = 0.03. What does that mean?
3. With the same conversion rates, why did 4,000 visitors per group give a significant result when 1,000 did not?
4. You check the test daily and stop the first day p drops below 0.05. What is the problem?
5. What is a guardrail metric?
Saved on this device. Create a free account to keep it on every device.
Practise this with Sam
A real mock interview, out loud, with an honest scorecard. Free to start.