Statistics and experimentation skill 02 of 6

A/B test analysis

A finished A/B test can show a clean, significant lift that is completely false. This skill makes an AI agent check the test is trustworthy first, with a sample ratio and guardrail check, before reading the winner, so you ship on a result you can defend, not on a number that looked good.

ab-test-analysis/SKILL.md, version 1.0.0, about 2,400 words.

Download .mdSkill folder (.zip)

When to use this, and when not to

Use this skill when an online experiment has finished and someone needs to decide whether to ship the variant. The triggers are a request to analyse an A/B test, read experiment results, check whether a test is valid, or turn a "significant" result into a roll-out decision. The work is to confirm the test can be trusted at all, then read the primary metric and the guardrails, and only then make a call.

Do not use it to design or size a test that has not run; that is sample-size-calculation, and it belongs before launch. Do not use it to run a single significance test in isolation with no experiment context; that is hypothesis-testing, which this skill calls for the maths. Do not use it to build the event and tracking plan the numbers come from; that is event-tracking-plan. An analysis is only as good as the instrumentation underneath it, so if the tracking is in doubt, fix that first.

The core idea: the first question is not "did it win" but "can I trust this result enough to act on it" (Kohavi, Tang and Xu, *Trustworthy Online Controlled Experiments*). A broken test can show a clean, significant, entirely false lift. So validity comes before the verdict, every time, and a result that fails a validity check is set aside until the cause is found, not shipped because the number looked good.

Inputs the agent must have before starting

  1. The primary metric and how it is defined, plus the guardrail metrics that must not get worse (revenue, latency, error rate, core engagement).
  2. Per-variant results: users or sessions assigned, and the metric numerators and denominators for each variant. The denominator is the randomisation unit, usually users, not events.
  3. The expected traffic split (for example 50/50) and the planned sample size, so the test can be checked against its own design.
  4. How long the test ran, and whether it covered full business cycles (weekdays and weekends, at least one to two full weeks).
  5. Whether the result was looked at and stopped early, or run to the planned sample size.
  6. Any pre-registered segments, and whether segment cuts were planned in advance or are being picked after the fact.

If the traffic split, the planned sample size or the metric definitions are missing, ask. Without them the validity checks cannot run, and an analysis without validity checks is a guess with a confidence interval on it.

Raw SKILL.md file

.md

This is the exact file agents read, including the credit header and licence notice. Save it as ab-test-analysis/SKILL.md.

---
name: ab-test-analysis
description: >
  Read a completed online A/B test and decide ship or not, by checking the test is trustworthy before looking at the winner. Covers the sample ratio mismatch (SRM) check with a chi-square test and a p < 0.0005 flag, whether the test ran to its planned sample size and full business cycles, the primary metric with an effect size and confidence interval, guardrail metrics, segment and novelty checks, multiple-comparison corrections, and a complete ship/iterate/stop decision table. Use it for "analyse my A/B test", "did the variant win", "read these experiment results", "is my test valid", "sample ratio mismatch", "SRM", "the control and variant have uneven traffic", "which version should we ship", or "my test is significant, should I roll it out". Do NOT use it to design or size a test before launch (see sample-size-calculation), to run a single significance test in isolation (see hypothesis-testing), or to build the tracking and event plan the test depends on (see event-tracking-plan).
license: Free to use and adapt under CC BY 4.0, with credit to Afeez Adebayo. Link afeezadebayo.com, https://www.linkedin.com/in/afeez-adebayo/ and this skill's page at https://afeezadebayo.com/skills-md/data/statistics-experimentation/ab-test-analysis/.
---

# A/B test analysis

## When to use this, and when not to

Use this skill when an online experiment has finished and someone needs to decide whether to ship the variant. The triggers are a request to analyse an A/B test, read experiment results, check whether a test is valid, or turn a "significant" result into a roll-out decision. The work is to confirm the test can be trusted at all, then read the primary metric and the guardrails, and only then make a call.

Do not use it to design or size a test that has not run; that is `sample-size-calculation`, and it belongs before launch. Do not use it to run a single significance test in isolation with no experiment context; that is `hypothesis-testing`, which this skill calls for the maths. Do not use it to build the event and tracking plan the numbers come from; that is `event-tracking-plan`. An analysis is only as good as the instrumentation underneath it, so if the tracking is in doubt, fix that first.

The core idea: the first question is not "did it win" but "can I trust this result enough to act on it" (Kohavi, Tang and Xu, *Trustworthy Online Controlled Experiments*). A broken test can show a clean, significant, entirely false lift. So validity comes before the verdict, every time, and a result that fails a validity check is set aside until the cause is found, not shipped because the number looked good.

## Inputs the agent must have before starting

1. The primary metric and how it is defined, plus the guardrail metrics that must not get worse (revenue, latency, error rate, core engagement).
2. Per-variant results: users or sessions assigned, and the metric numerators and denominators for each variant. The denominator is the randomisation unit, usually users, not events.
3. The expected traffic split (for example 50/50) and the planned sample size, so the test can be checked against its own design.
4. How long the test ran, and whether it covered full business cycles (weekdays and weekends, at least one to two full weeks).
5. Whether the result was looked at and stopped early, or run to the planned sample size.
6. Any pre-registered segments, and whether segment cuts were planned in advance or are being picked after the fact.

If the traffic split, the planned sample size or the metric definitions are missing, ask. Without them the validity checks cannot run, and an analysis without validity checks is a guess with a confidence interval on it.

## The workflow, step by step

### 1. Check the sample ratio before anything else

Compare the actual split of users against the expected split with a chi-square goodness-of-fit test. If the p-value is below 0.0005, the test has a sample ratio mismatch (SRM) and the results cannot be trusted until the cause is found (Microsoft ExP, "Diagnosing sample ratio mismatch"). Microsoft reports that about 6% of their experiments have an SRM, and the missing users are usually not random, so the bias can point either way. A 50/50 test that came out 51/49 on a million users is almost certainly broken, even though 51/49 "looks" close.

Decision rule: SRM present (p < 0.0005) means stop and diagnose (assignment, logging, redirects, a variant that changes who stays). Do not report a winner from a test with an unexplained SRM.

### 2. Confirm the test actually completed

Check it ran to the planned sample size from `sample-size-calculation`, and covered at least one to two full business cycles so weekday and weekend behaviour are both represented (Optimizely; Kohavi). Check it was not stopped the moment it looked significant. A test stopped early on a good-looking peek has a false positive rate well above its stated level (Evan Miller, 2010), so an early stop is itself a reason to distrust the result.

### 3. Read the primary metric with an effect size and a confidence interval

Run the significance test for the metric type (see `hypothesis-testing` for the choice and the maths), and report the absolute difference, the relative lift, the 95% confidence interval and the p-value together. The confidence interval is the honest summary: it shows the range of true effects the data is consistent with. A significant lift whose lower confidence bound is below the smallest worthwhile effect is not yet a business win.

### 4. Check the guardrail metrics

A primary win bought with a worse guardrail is often a loss. Check the metrics that must not degrade, each with its own confidence interval: revenue per user, page latency, error rate, and the core engagement the product depends on. Decision rule: if the primary improved but a guardrail degraded beyond its agreed tolerance, do not ship on the primary alone; investigate the trade-off and escalate the decision.

### 5. Look at segments carefully, not opportunistically

Segment analysis (new versus returning, device, country) can find where an effect lives, but scanning many segments and reporting the significant ones is data dredging. Treat segment cuts as pre-registered or as exploratory, correct for the number of comparisons (see `hypothesis-testing`), and confirm any surprising segment result on fresh data before acting on it.

### 6. Check the effect is stable over time

Plot the metric by day. A lift that is large in the first days and fades is a novelty effect; a lift that only appears later may be a primacy effect as users adjust. Ship on the stable, settled effect, not the launch spike.

### 7. Make the call with a complete decision table

| Primary result | Guardrails | Decision |
|---|---|---|
| Significant positive, effect clears the worthwhile threshold | All stable | Ship, roll out in stages while monitoring |
| Significant positive | A guardrail degraded | Do not ship on the primary; investigate the trade-off |
| Significant positive, but effect below the worthwhile threshold | Stable | Usually not worth the complexity; decide on cost |
| Not significant, positive trend, test underpowered | Stable | Inconclusive; extend to the planned size or rerun, do not ship |
| Not significant, tight CI around zero | Stable | No meaningful effect; do not ship, and record the learning |
| Significant negative | Any | Do not ship; revert and find out why |
| Significant negative on primary, but a guardrail or secondary improved | Mixed | Do not ship the variant as is; isolate what helped |

### 8. Report with the trade-off in view

State the validity checks and their results first, then the primary effect with its confidence interval, the guardrails, the segments, the time trend, and the decision with its reasoning. The reader should see why the result can be trusted before they see what it says.

## Worked example, end to end

An experiment reports a +5.2% lift in sign-ups, significant at p = 0.01, and the team wants to ship. Before celebrating, the skill checks the sample ratio. The design was 50/50, but the variant received 252,100 users and the control 247,900, a total of 500,000.

```python
from scipy.stats import chisquare
observed = [252100, 247900]          # variant, control
expected = [250000, 250000]          # 50/50 of the total
chi2, p = chisquare(f_obs=observed, f_exp=expected)
print(round(chi2, 1), p)
# chi2 = 35.3, p = 2.8e-09  -> far below 0.0005: SRM present
```

The split fails the SRM check by a wide margin (p is about 3e-09), so the +5.2% lift cannot be trusted. Diagnosis shows the variant had a redirect that dropped slow mobile connections, so the extra users in the variant were systematically more engaged to begin with. The honest output is not "ship the 5.2% win"; it is "the test is invalid because of a sample ratio mismatch caused by the redirect, fix the redirect and rerun". Shipping on the raw number would have rolled out a change whose measured lift was an artefact of who was dropped, not what the change did.

## Templates you can use verbatim

```python
# 1. Sample ratio mismatch check (run this first, before any winner)
from scipy.stats import chisquare
def srm_check(n_variant, n_control, split=(0.5, 0.5)):
    total = n_variant + n_control
    expected = [total * split[0], total * split[1]]
    chi2, p = chisquare(f_obs=[n_variant, n_control], f_exp=expected)
    return {"chi2": chi2, "p": p, "srm": p < 0.0005}   # Microsoft ExP threshold
```

```python
# 2. Primary metric: lift with a 95% CI (two proportions) -- see hypothesis-testing
from statsmodels.stats.proportion import proportions_ztest, confint_proportions_2indep
stat, p = proportions_ztest([conv_var, conv_ctrl], [n_var, n_ctrl])
low, high = confint_proportions_2indep(conv_var, n_var, conv_ctrl, n_ctrl)
lift_abs = conv_var/n_var - conv_ctrl/n_ctrl
```

```text
Decision checklist (run in order)
1. SRM check passes (p >= 0.0005)                 -> if not, STOP, diagnose
2. Ran to planned sample size and full cycles     -> if not, inconclusive
3. Not stopped early on a peek                     -> if it was, distrust
4. Primary: effect, 95% CI, p; CI lower bound vs worthwhile threshold
5. Guardrails: each with a CI, none degraded past tolerance
6. Segments: pre-registered or exploratory, corrected for comparisons
7. Effect stable over time, not a novelty spike
8. Decision from the table, with reasoning and the trade-off stated
```

## Failure modes and anti-patterns

1. **Trusting a result with a sample ratio mismatch.** A broken split produces a clean, significant, false lift. Spot it with the chi-square SRM check at p < 0.0005. Fix: stop, find the cause (redirects, logging, assignment), rerun; never ship on an unexplained SRM.
2. **Shipping on the primary while a guardrail degraded.** A sign-up lift that slows the page or cuts revenue per user is often a net loss. Spot it by reading every guardrail with its own CI. Fix: do not ship on the primary alone; weigh the trade-off and escalate.
3. **Peeking and early stopping.** A test stopped the first day it looked significant has a false positive rate far above its stated level. Spot it from a stop date well before the planned sample size. Fix: run to the planned size, or use the platform's sequential method, and treat an early stop as a reason to distrust.
4. **Data-dredged segment wins.** Scanning twenty segments and reporting the one that is significant invents a finding. Spot it when a headline result lives only in an unplanned subgroup. Fix: pre-register segments, correct for the number of comparisons, confirm on fresh data.
5. **Reading a flat result as proof the versions are equal.** A non-significant test with a wide CI could not tell; it is not evidence of no difference. Spot it from a wide confidence interval around zero. Fix: call it inconclusive, extend or rerun, or run an equivalence test (see `hypothesis-testing`).

## Quality bar

- The sample ratio was checked with a chi-square test and passed (p at or above 0.0005) before any winner was reported.
- The test ran to its planned sample size over full business cycles and was not stopped early on a peek.
- The primary metric is reported with an effect size and a 95% confidence interval, and judged against the smallest worthwhile effect, not against 0.05 alone.
- Every guardrail metric was checked with its own interval, and a primary win with a degraded guardrail was not shipped on the primary alone.
- Segment results are pre-registered or labelled exploratory and corrected for multiple comparisons, and the effect was checked for stability over time.
- The decision comes from the full table, states its reasoning, and never reads a flat result as proof of equality.

## Data handling and safety

Experiment results sit on top of user-level data, so do not log raw user records, paste them into prompts or send them to a third-party service; work with the aggregated counts the platform already produces. Shipping, pausing or rolling back a change affects real users and revenue, so it is an irreversible decision that needs explicit human confirmation: this skill produces a recommendation with its reasoning, it does not roll anything out. Never fabricate a lift, a p-value, a confidence interval or an SRM result; every figure comes from the actual experiment data. When the test touches money, health, legal standing or employment, the read is evidence for a human decision, not the decision itself, and the trade-offs and uncertainty must be shown.

## Appendix: tool-specific notes (verify before relying on these)

- **scipy.stats:** `chisquare(f_obs, f_exp)` for the SRM goodness-of-fit test; the SRM flag is p < 0.0005. Use `chi2_contingency` or `proportions_ztest` for the primary metric, and the test choices in `hypothesis-testing` for other metric types.
- **statsmodels:** `proportions_ztest`, `confint_proportions_2indep`, and `multipletests` for correcting segment and multi-metric comparisons.
- **Optimizely and VWO:** their Stats Engine uses sequential testing and always-valid p-values, so their "significance" is designed to survive continuous monitoring; read their reported significance and confidence intervals rather than running a fixed-horizon test on top of their numbers, and still run the SRM check (Optimizely docs).
- **GA4, Firebase and warehouse data:** export per-variant users and conversions by day; confirm the randomisation unit is the user, deduplicate across sessions, and reconcile the totals against the assignment log before trusting any split.
- **R:** `prop.test`, `chisq.test` for SRM, and `p.adjust` for corrections; the `pwr` package for the power follow-up in `sample-size-calculation`.

## Sources

- Kohavi, Tang and Xu, *Trustworthy Online Controlled Experiments* (2020), and Kohavi et al., "Seven Rules of Thumb for Web Site Experimenters" (KDD 2014): that trust comes before the verdict, that effects are usually small, that tests should run over full business cycles, and the use of guardrail metrics and an overall evaluation criterion. Verified 7 November 2026.
- Microsoft Experimentation Platform, "Diagnosing Sample Ratio Mismatch in A/B Testing": the chi-square SRM check, the p < 0.0005 threshold, that about 6% of experiments have an SRM, that missing users are usually not random, and the rule not to trust a result with an unexplained SRM. Verified 7 November 2026.
- Evan Miller, "How Not To Run an A/B Test" (2010): that stopping a fixed-horizon test early on a significant peek inflates the false positive rate well above the stated level. Verified 7 November 2026.
- Optimizely documentation, "How long to run an experiment" and the Stats Engine notes: running over at least one business cycle, the role of baseline rate and minimum detectable effect, and that sequential methods change how significance is read. Verified 7 November 2026.
- SciPy and statsmodels documentation: `chisquare`, `chi2_contingency`, `proportions_ztest`, `confint_proportions_2indep`, `multipletests`. Verified 7 November 2026.
- Existing skills reviewed and improved on: `phuryn` ab-test-analysis and `openclaudia` ab-test-setup name sample ratio mismatch but give no test or threshold, apply no multiple-comparison correction, give no peeking rule, and read a flat result as "no difference"; `wdavidturner` trustworthy-experiments gives the principles but ships the detailed thresholds as placeholders. This skill supplies the SRM test and threshold, the guardrail and segment handling, and a complete decision table. Verified 7 November 2026.

The workflow, step by step

1. Check the sample ratio before anything else

Compare the actual split of users against the expected split with a chi-square goodness-of-fit test. If the p-value is below 0.0005, the test has a sample ratio mismatch (SRM) and the results cannot be trusted until the cause is found (Microsoft ExP, "Diagnosing sample ratio mismatch"). Microsoft reports that about 6% of their experiments have an SRM, and the missing users are usually not random, so the bias can point either way. A 50/50 test that came out 51/49 on a million users is almost certainly broken, even though 51/49 "looks" close.

Decision rule: SRM present (p < 0.0005) means stop and diagnose (assignment, logging, redirects, a variant that changes who stays). Do not report a winner from a test with an unexplained SRM.

2. Confirm the test actually completed

Check it ran to the planned sample size from sample-size-calculation, and covered at least one to two full business cycles so weekday and weekend behaviour are both represented (Optimizely; Kohavi). Check it was not stopped the moment it looked significant. A test stopped early on a good-looking peek has a false positive rate well above its stated level (Evan Miller, 2010), so an early stop is itself a reason to distrust the result.

3. Read the primary metric with an effect size and a confidence interval

Run the significance test for the metric type (see hypothesis-testing for the choice and the maths), and report the absolute difference, the relative lift, the 95% confidence interval and the p-value together. The confidence interval is the honest summary: it shows the range of true effects the data is consistent with. A significant lift whose lower confidence bound is below the smallest worthwhile effect is not yet a business win.

4. Check the guardrail metrics

A primary win bought with a worse guardrail is often a loss. Check the metrics that must not degrade, each with its own confidence interval: revenue per user, page latency, error rate, and the core engagement the product depends on. Decision rule: if the primary improved but a guardrail degraded beyond its agreed tolerance, do not ship on the primary alone; investigate the trade-off and escalate the decision.

5. Look at segments carefully, not opportunistically

Segment analysis (new versus returning, device, country) can find where an effect lives, but scanning many segments and reporting the significant ones is data dredging. Treat segment cuts as pre-registered or as exploratory, correct for the number of comparisons (see hypothesis-testing), and confirm any surprising segment result on fresh data before acting on it.

6. Check the effect is stable over time

Plot the metric by day. A lift that is large in the first days and fades is a novelty effect; a lift that only appears later may be a primacy effect as users adjust. Ship on the stable, settled effect, not the launch spike.

7. Make the call with a complete decision table

Primary resultGuardrailsDecision
Significant positive, effect clears the worthwhile thresholdAll stableShip, roll out in stages while monitoring
Significant positiveA guardrail degradedDo not ship on the primary; investigate the trade-off
Significant positive, but effect below the worthwhile thresholdStableUsually not worth the complexity; decide on cost
Not significant, positive trend, test underpoweredStableInconclusive; extend to the planned size or rerun, do not ship
Not significant, tight CI around zeroStableNo meaningful effect; do not ship, and record the learning
Significant negativeAnyDo not ship; revert and find out why
Significant negative on primary, but a guardrail or secondary improvedMixedDo not ship the variant as is; isolate what helped

8. Report with the trade-off in view

State the validity checks and their results first, then the primary effect with its confidence interval, the guardrails, the segments, the time trend, and the decision with its reasoning. The reader should see why the result can be trusted before they see what it says.

Worked example, end to end

An experiment reports a +5.2% lift in sign-ups, significant at p = 0.01, and the team wants to ship. Before celebrating, the skill checks the sample ratio. The design was 50/50, but the variant received 252,100 users and the control 247,900, a total of 500,000.

from scipy.stats import chisquare
observed = [252100, 247900]          # variant, control
expected = [250000, 250000]          # 50/50 of the total
chi2, p = chisquare(f_obs=observed, f_exp=expected)
print(round(chi2, 1), p)
# chi2 = 35.3, p = 2.8e-09  -> far below 0.0005: SRM present

The split fails the SRM check by a wide margin (p is about 3e-09), so the +5.2% lift cannot be trusted. Diagnosis shows the variant had a redirect that dropped slow mobile connections, so the extra users in the variant were systematically more engaged to begin with. The honest output is not "ship the 5.2% win"; it is "the test is invalid because of a sample ratio mismatch caused by the redirect, fix the redirect and rerun". Shipping on the raw number would have rolled out a change whose measured lift was an artefact of who was dropped, not what the change did.

Templates you can use verbatim

# 1. Sample ratio mismatch check (run this first, before any winner)
from scipy.stats import chisquare
def srm_check(n_variant, n_control, split=(0.5, 0.5)):
    total = n_variant + n_control
    expected = [total * split[0], total * split[1]]
    chi2, p = chisquare(f_obs=[n_variant, n_control], f_exp=expected)
    return {"chi2": chi2, "p": p, "srm": p < 0.0005}   # Microsoft ExP threshold
# 2. Primary metric: lift with a 95% CI (two proportions) -- see hypothesis-testing
from statsmodels.stats.proportion import proportions_ztest, confint_proportions_2indep
stat, p = proportions_ztest([conv_var, conv_ctrl], [n_var, n_ctrl])
low, high = confint_proportions_2indep(conv_var, n_var, conv_ctrl, n_ctrl)
lift_abs = conv_var/n_var - conv_ctrl/n_ctrl
Decision checklist (run in order)
1. SRM check passes (p >= 0.0005)                 -> if not, STOP, diagnose
2. Ran to planned sample size and full cycles     -> if not, inconclusive
3. Not stopped early on a peek                     -> if it was, distrust
4. Primary: effect, 95% CI, p; CI lower bound vs worthwhile threshold
5. Guardrails: each with a CI, none degraded past tolerance
6. Segments: pre-registered or exploratory, corrected for comparisons
7. Effect stable over time, not a novelty spike
8. Decision from the table, with reasoning and the trade-off stated

Failure modes and anti-patterns

  1. Trusting a result with a sample ratio mismatch. A broken split produces a clean, significant, false lift. Spot it with the chi-square SRM check at p < 0.0005. Fix: stop, find the cause (redirects, logging, assignment), rerun; never ship on an unexplained SRM.
  2. Shipping on the primary while a guardrail degraded. A sign-up lift that slows the page or cuts revenue per user is often a net loss. Spot it by reading every guardrail with its own CI. Fix: do not ship on the primary alone; weigh the trade-off and escalate.
  3. Peeking and early stopping. A test stopped the first day it looked significant has a false positive rate far above its stated level. Spot it from a stop date well before the planned sample size. Fix: run to the planned size, or use the platform's sequential method, and treat an early stop as a reason to distrust.
  4. Data-dredged segment wins. Scanning twenty segments and reporting the one that is significant invents a finding. Spot it when a headline result lives only in an unplanned subgroup. Fix: pre-register segments, correct for the number of comparisons, confirm on fresh data.
  5. Reading a flat result as proof the versions are equal. A non-significant test with a wide CI could not tell; it is not evidence of no difference. Spot it from a wide confidence interval around zero. Fix: call it inconclusive, extend or rerun, or run an equivalence test (see hypothesis-testing).

Quality bar

  • The sample ratio was checked with a chi-square test and passed (p at or above 0.0005) before any winner was reported.
  • The test ran to its planned sample size over full business cycles and was not stopped early on a peek.
  • The primary metric is reported with an effect size and a 95% confidence interval, and judged against the smallest worthwhile effect, not against 0.05 alone.
  • Every guardrail metric was checked with its own interval, and a primary win with a degraded guardrail was not shipped on the primary alone.
  • Segment results are pre-registered or labelled exploratory and corrected for multiple comparisons, and the effect was checked for stability over time.
  • The decision comes from the full table, states its reasoning, and never reads a flat result as proof of equality.

Data handling and safety

Experiment results sit on top of user-level data, so do not log raw user records, paste them into prompts or send them to a third-party service; work with the aggregated counts the platform already produces. Shipping, pausing or rolling back a change affects real users and revenue, so it is an irreversible decision that needs explicit human confirmation: this skill produces a recommendation with its reasoning, it does not roll anything out. Never fabricate a lift, a p-value, a confidence interval or an SRM result; every figure comes from the actual experiment data. When the test touches money, health, legal standing or employment, the read is evidence for a human decision, not the decision itself, and the trade-offs and uncertainty must be shown.

Appendix: tool-specific notes (verify before relying on these)

  • scipy.stats: chisquare(f_obs, f_exp) for the SRM goodness-of-fit test; the SRM flag is p < 0.0005. Use chi2_contingency or proportions_ztest for the primary metric, and the test choices in hypothesis-testing for other metric types.
  • statsmodels: proportions_ztest, confint_proportions_2indep, and multipletests for correcting segment and multi-metric comparisons.
  • Optimizely and VWO: their Stats Engine uses sequential testing and always-valid p-values, so their "significance" is designed to survive continuous monitoring; read their reported significance and confidence intervals rather than running a fixed-horizon test on top of their numbers, and still run the SRM check (Optimizely docs).
  • GA4, Firebase and warehouse data: export per-variant users and conversions by day; confirm the randomisation unit is the user, deduplicate across sessions, and reconcile the totals against the assignment log before trusting any split.
  • R: prop.test, chisq.test for SRM, and p.adjust for corrections; the pwr package for the power follow-up in sample-size-calculation.

Sources

  • Kohavi, Tang and Xu, *Trustworthy Online Controlled Experiments* (2020), and Kohavi et al., "Seven Rules of Thumb for Web Site Experimenters" (KDD 2014): that trust comes before the verdict, that effects are usually small, that tests should run over full business cycles, and the use of guardrail metrics and an overall evaluation criterion. Verified 7 November 2026.
  • Microsoft Experimentation Platform, "Diagnosing Sample Ratio Mismatch in A/B Testing": the chi-square SRM check, the p < 0.0005 threshold, that about 6% of experiments have an SRM, that missing users are usually not random, and the rule not to trust a result with an unexplained SRM. Verified 7 November 2026.
  • Evan Miller, "How Not To Run an A/B Test" (2010): that stopping a fixed-horizon test early on a significant peek inflates the false positive rate well above the stated level. Verified 7 November 2026.
  • Optimizely documentation, "How long to run an experiment" and the Stats Engine notes: running over at least one business cycle, the role of baseline rate and minimum detectable effect, and that sequential methods change how significance is read. Verified 7 November 2026.
  • SciPy and statsmodels documentation: chisquare, chi2_contingency, proportions_ztest, confint_proportions_2indep, multipletests. Verified 7 November 2026.
  • Existing skills reviewed and improved on: phuryn ab-test-analysis and openclaudia ab-test-setup name sample ratio mismatch but give no test or threshold, apply no multiple-comparison correction, give no peeking rule, and read a flat result as "no difference"; wdavidturner trustworthy-experiments gives the principles but ships the detailed thresholds as placeholders. This skill supplies the SRM test and threshold, the guardrail and segment handling, and a complete decision table. Verified 7 November 2026.

When to use this skill, and when not to

Use this skill when an online experiment has finished and you need to decide whether to ship the variant. It fits the moment a dashboard shows a lift, when traffic between control and variant looks uneven, or when a result is significant and someone asks whether to roll it out.

It is not for sizing a test before launch (see sample-size-calculation), for running a single significance test with no experiment context (see hypothesis-testing), or for building the event tracking the numbers rely on (see event-tracking-plan).

Who it is for

Product managers, growth and experimentation teams, analysts and anyone who owns a ship or no-ship call on an A/B test. No statistics background is needed: the skill runs the validity checks, names what each one found, and explains the decision.

What is inside

An eight-step read that puts trust before the verdict: a sample ratio mismatch check with a chi-square test and a p < 0.0005 flag, a completion and peeking check, the primary metric with an effect size and confidence interval, guardrail metrics, segment and novelty checks with multiple-comparison corrections, and a complete ship, iterate or stop decision table. It comes with a worked example and ready-to-run Python.

Example prompts

“Analyse my A/B test.” “Did the variant win?” “My control and variant have uneven traffic, is that a problem?” “The test is significant, should we ship?” “Read these experiment results and tell me what to do.”

Example output

The skill reports the validity checks first (sample ratio, completion, peeking), then the primary effect with its confidence interval, the guardrails, any segment and time-trend findings, and a decision from the table with its reasoning. A broken or inconclusive test is called out as such, not dressed up as a win.

What the agent needs from you

The primary and guardrail metrics and how they are defined, per-variant users and conversions, the expected traffic split, the planned sample size, how long the test ran, and whether it was stopped early. For segment work, say which cuts were planned in advance. If these are missing, the skill asks before judging.

How to install and use it

In the Claude apps, use the buttons above to download the skill, then upload the SKILL.md in a new chat or add it to a Project. In Claude Code and other Agent Skills tools, copy the ab-test-analysis folder into ~/.claude/skills/, or .agents/skills/ for Codex. The skill loads itself when your request matches its triggers, so you do not need to call it by name.

How to analyse an A/B test step by step

Check the sample ratio first with a chi-square test; if p is below 0.0005 the test is broken, so stop and diagnose before anything else. Confirm it ran to the planned sample size over full business cycles and was not stopped early. Read the primary metric with an effect size and a confidence interval, then check every guardrail with its own interval. Look at segments only as planned or clearly exploratory, corrected for the number of comparisons, and check the effect is stable over time. Finish with the decision table, stating the trade-off.

Worked example

A test reports a +5.2% lift in sign-ups at p = 0.01, and the team wants to ship. The sample ratio check on a 50/50 design finds 252,100 versus 247,900 users, which fails at p of about 3e-09. A redirect in the variant was dropping slow mobile connections, so the extra users were more engaged to start with. The honest output is not ship the win; it is fix the redirect and rerun, because the lift was an artefact of who was dropped.

Situations this skill handles

SituationWhat the skill does
Uneven traffic between armsRuns a chi-square sample ratio check and stops if p is below 0.0005
Significant primary, slower pageFlags the guardrail and withholds a ship-on-primary call
Test stopped early on a good dayTreats the early stop as a reason to distrust the result
A win only in one unplanned segmentCorrects for comparisons and asks for confirmation on fresh data
Flat result, wide intervalCalls it inconclusive, not proof the versions are equal
Big first-week spikeChecks the effect is stable before shipping on it

What makes this skill different

Most A/B analysis helpers name sample ratio mismatch but give no test and no threshold, skip multiple-comparison corrections, say nothing about peeking, and read a flat result as proof of no difference. This skill runs the chi-square SRM check at p < 0.0005, reads every guardrail with a confidence interval, corrects segment comparisons, checks the effect over time, and makes the call from a complete decision table, with every rule sourced.

Common mistakes

The usual errors are trusting a result that has a sample ratio mismatch, shipping on the primary while a guardrail degraded, stopping the test early on a good look, mining segments for a win, and reading a flat test as a tie. The skill names each one, shows how to spot it, and gives the fix.

Size the test first with sample-size-calculation, and use hypothesis-testing for the significance maths behind the primary metric. For the tracking the results depend on, see event-tracking-plan.

Frequently asked questions

It is when the actual split of users does not match the split you set, for example 51/49 when you planned 50/50. It usually means something in assignment, logging or redirects is broken, and the users that went missing are rarely random. The skill runs a chi-square check and, if p is below 0.0005, treats the whole result as untrustworthy until the cause is found.

No. A significant primary can sit on top of a broken split, a degraded guardrail, or a first-week spike that fades. The skill checks validity and guardrails first, reads the effect against the smallest lift worth shipping, and only then recommends a decision.

Not for a fixed-horizon test. Stopping at the first significant look can push the real false positive rate several times above the level you think you have. Run to the planned sample size, or use a platform built for sequential testing. An early stop is itself a reason to distrust the result.

No. A non-significant test with a wide confidence interval could not tell the difference; it is not proof there is none. The skill calls that inconclusive and suggests extending the test, rerunning, or running an equivalence test if you need to show the versions match.

Yes. The skill reads per-variant counts from any platform or warehouse export. It notes that Optimizely and VWO use sequential statistics, so their significance is read differently, and it still runs the sample ratio check on their numbers. It reconciles totals against the assignment log first.

No. It produces a recommendation with its reasoning. Shipping, pausing or rolling back affects real users and revenue, so that action is always left for a person to confirm.

Changelog

1.0.0, 7 November 2026: first release. Use, adapt and share under CC BY 4.0 with credit to Afeez Adebayo.