A/B Test Setup - Experimentation Design & Analysis
Category: Product Team
Tags: A/B testing, experiments, statistical significance, sample size, feature flags, hypothesis testing
Overview
A/B Test Setup provides the complete framework for designing experiments that produce statistically valid, actionable results. Most A/B tests fail not because the variant was wrong, but because the test was poorly designed: wrong sample size, wrong metric, or someone peeked at results and stopped early. This skill prevents those mistakes.
Clarify First
Before designing the experiment, confirm these inputs. If any is unknown or vague, ASK — do not assume:
Stop rule: ask only the 2-3 that most change the output. If the user says "just draft it," proceed and list your assumptions at the top of the artifact.
The Experiment Lifecycle
1. HYPOTHESIZE → 2. DESIGN → 3. CALCULATE → 4. IMPLEMENT
↑ │
│ ▼
7. ITERATE ← 6. DOCUMENT ← 5. ANALYZE ← [Run to completion]
Step 1: Hypothesis Formulation
The Hypothesis Template
Because [observation or data point],
we believe [specific change]
will cause [measurable outcome]
for [defined audience segment].
We'll know this is true when [primary metric] changes by [minimum detectable effect].
We'll watch [guardrail metrics] to ensure no negative impact.
Good vs Bad Hypotheses
| Quality |
Hypothesis |
Problem |
| Bad |
"Changing the button color might increase clicks" |
No data basis, no target, no measurement plan |
| Mediocre |
"A green button will get more clicks than blue" |
No "why", no target size, no guardrails |
| Good |
"Because heatmaps show 40% of users don't notice our CTA, making the button 2x larger with contrasting color will increase CTA clicks by 15%+ for new visitors. Guardrail: page load time stays under 2s." |
Data-backed, specific change, measurable outcome, defined audience, guardrail |
Hypothesis Sources (Where to Find Test Ideas)
| Source |
What to Look For |
Example |
| Analytics data |
Drop-off points, low-performing pages |
"80% of users drop off at step 3 of onboarding" |
| User research |
Confusion, frustration, unmet needs |
"Users don't understand what the product does from the homepage" |
| Heatmaps/session recordings |
Ignored elements, rage clicks |
"Nobody scrolls past the fold on pricing page" |
| Support tickets |
Recurring complaints, feature confusion |
"Users constantly ask how to invite team members" |
| Competitor analysis |
Different approaches to same problem |
"Competitor uses a wizard; we use a form" |
| Sales objections |
Common reasons prospects don't convert |
"Prospects want to see pricing before signing up" |
Step 2: Test Design
Test Types
| Type |
Variants |
Traffic Need |
Best For |
| A/B |
2 (control + 1 variant) |
Moderate |
Single change validation |
| A/B/n |
3+ variants |
High |
Comparing multiple approaches |
| Multivariate (MVT) |
Combinations of changes |
Very high |
Optimizing multiple elements |
| Split URL |
Different pages |
Moderate |
Major redesigns |
| Bandit |
Dynamic allocation |
Low-moderate |
Revenue optimization |
Default recommendation: Standard A/B test. Only use A/B/n or MVT when you have enough traffic and a specific need.
What to Test (By Impact)
| Category |
High Impact |
Medium Impact |
Low Impact |
| Copy |
Headline/value prop, CTA text |
Body copy, social proof |
Microcopy, labels |
| Design |
Page layout, above-fold content |
Visual hierarchy, imagery |
Color, font size |
| UX |
Number of steps, form fields |
Button placement, navigation |
Animations, transitions |
| Pricing |
Price point, plan names |
Feature packaging, anchoring |
Billing frequency display |
| Social Proof |
Testimonials vs none, logos |
Testimonial format, placement |
Testimonial count |
Metric Selection
Every test needs three types of metrics:
Primary Metric (1 only)
- The single metric that determines success
- Directly tied to the hypothesis
- Must be measurable within the test duration
- Examples: signup rate, click-through rate, purchase rate
Secondary Metrics (2-3)
- Explain why the primary metric moved
- Provide context for decision-making
- Examples: time on page, scroll depth, feature adoption rate
Guardrail Metrics (1-3)
- Things that must NOT get worse
- Stop the test if significantly negative
- Examples: error rate, support ticket volume, page load time, refund rate
Step 3: Sample Size Calculation
Quick Reference Table
Minimum visitors PER VARIANT needed (95% confidence, 80% power):
| Baseline Rate |
5% Lift |
10% Lift |
15% Lift |
20% Lift |
50% Lift |
| 1% |
620,000 |
156,000 |
70,000 |
39,000 |
6,400 |
| 2% |
305,000 |
77,000 |
34,000 |
19,500 |
3,200 |
| 3% |
200,000 |
51,000 |
23,000 |
12,800 |
2,100 |
| 5% |
116,000 |
29,500 |
13,200 |
7,500 |
1,250 |
| 10% |
54,000 |
13,800 |
6,200 |
3,500 |
600 |
| 20% |
24,000 |
6,200 |
2,800 |
1,600 |
280 |
| 50% |
6,100 |
1,600 |
720 |
410 |
75 |
Duration Calculation
Duration (days) = (Sample size per variant * Number of variants) / Daily traffic to test page
Minimum duration: 7 days (to capture day-of-week effects)
Maximum recommended: 6 weeks (beyond this, external factors contaminate results)
What If You Don't Have Enough Traffic?
| Situation |
Solution |
| Need 100K visitors, get 5K/week |
Increase minimum detectable effect (test bolder changes) |
| Very low traffic (<1K/week) |
Use qualitative testing (user testing, surveys) instead |
| Medium traffic (5-20K/week) |
Run for 4-6 weeks, test big changes only |
| High traffic (50K+/week) |
You can test subtle changes, run multiple tests |
Step 4: Implementation
Client-Side Implementation
JavaScript modifies the page after initial render.
Pros: Quick to implement, no deploy needed
Cons: Can cause flicker (flash of original content), blocked by ad blockers
Tools: PostHog, Optimizely, VWO, Google Optimize
Anti-flicker pattern:
// Add to <head> before any rendering
<style>.ab-test-hide { opacity: 0 !important; }</style>
<script>document.documentElement.classList.add('ab-test-hide');</script>
// In your test script (runs after variant assignment):
document.documentElement.classList.remove('ab-test-hide');
Server-Side Implementation
Variant determined before page renders. No flicker, no client-side dependency.
Pros: No flicker, not blocked by ad blockers, works for logged-in features
Cons: Requires engineering work, deploy needed
Tools: PostHog, LaunchDarkly, Split, Unleash, custom feature flags
Basic feature flag pattern:
# Server-side variant assignment
def get_variant(user_id: str, experiment: str) -> str:
# Deterministic hash ensures same user always sees same variant
hash_input = f"{user_id}:{experiment}"
hash_value = hashlib.md5(hash_input.encode()).hexdigest()
bucket = int(hash_value[:8], 16) % 100
if bucket < 50:
return "control"
else:
return "variant"
Traffic Allocation
| Strategy |
Split |
When to Use |
| Standard |
50/50 |
Default. Maximum statistical power. |
| Conservative |
90/10 or 80/20 |
Risky changes, revenue-impacting tests |
| Ramped |
Start 95/5, increase to 50/50 |
New infrastructure, technical risk |
Critical rules:
- Users must see the same variant on every visit (sticky assignment by user ID or cookie)
- Allocation must be balanced across time of day and day of week
- Never change allocation mid-test
Step 5: Running the Test
Pre-Launch Checklist
During the Test
DO:
- Monitor for technical errors (variant not rendering, tracking broken)
- Check that traffic split is balanced daily
- Document any external events that might affect results
DO NOT:
- Look at results before reaching sample size ("peeking problem")
- Make changes to either variant
- Add traffic from new sources mid-test
- Stop the test early because one variant "looks like it's winning"
The Peeking Problem (Critical)
Looking at results before reaching the planned sample size and stopping because one variant looks better leads to a 25-40% false positive rate (vs the intended 5%).
Why: Statistical significance fluctuates wildly with small samples. A variant can show p < 0.05 at 20% of planned sample size and p > 0.30 at full sample.
Solutions:
- Pre-commit to sample size and do not check results until reached
- If you must monitor: use sequential testing methods (group sequential design, always-valid p-values)
- Set calendar reminder for expected completion date -- that is when you look
Step 6: Analysis
Analysis Checklist
- Did we reach planned sample size? If not, results are preliminary only.
- Is it statistically significant? p < 0.05 = 95% confidence the difference is real.
- What's the confidence interval? Tells you the range of likely true effect.
- Is the effect size meaningful? A 0.1% lift that's "significant" may not be worth implementing.
- Are secondary metrics consistent? Do they support the primary result?
- Any guardrail violations? Did anything get worse?
- Segment analysis: Different results for mobile vs desktop? New vs returning?
Interpreting Results
| Result |
Primary Metric |
Confidence |
Action |
| Clear winner |
Variant +15%, p < 0.01 |
High |
Implement variant |
| Modest winner |
Variant +5%, p < 0.05 |
Medium |
Implement if easy, else run longer |
| Flat |
< 2% difference, p > 0.20 |
High (no effect) |
Keep control, test something bolder |
| Loser |
Variant -10%, p < 0.05 |
High |
Keep control, investigate why |
| Inconclusive |
5% difference, p = 0.08 |
Low |
Need more traffic or bolder test |
| Mixed signals |
Primary up, guardrail down |
Investigate |
Dig into segments, do not ship blindly |
Common Analysis Mistakes
| Mistake |
Consequence |
Prevention |
| Stopping at first significance |
25-40% false positive rate |
Commit to sample size |
| Cherry-picking segments |
Finding "winners" that don't replicate |
Pre-register segments of interest |
| Ignoring confidence intervals |
Overestimating effect size |
Always report CI alongside p-value |
| Multiple comparisons |
Inflated Type I error |
Bonferroni correction for A/B/n |
| Survivorship bias |
Only analyzing users who completed flow |
Include all users from assignment point |
| Simpson's paradox |
Aggregate hides segment reversal |
Always check key segments |
Step 7: Documentation
Every test must be documented, regardless of outcome.
Test Documentation Template
EXPERIMENT: [Name]
DATE: [Start] to [End]
OWNER: [Name]
HYPOTHESIS:
Because [observation], we believed [change] would cause [outcome] for [audience].
VARIANTS:
- Control: [description]
- Variant: [description + screenshot]
METRICS:
- Primary: [metric] (baseline: [X]%, MDE: [Y]%)
- Secondary: [metrics]
- Guardrails: [metrics]
RESULTS:
- Sample size: [actual] / [planned]
- Duration: [X] days
- Primary metric: Control [X]% vs Variant [Y]% (p = [Z], CI: [range])
- Secondary metrics: [results]
- Guardrails: [all clear / violation noted]
DECISION: [Ship variant / Keep control / Iterate]
LEARNINGS:
- [What we learned about our users]
- [What we'd do differently next time]
Experiment Prioritization Framework
ICE Scoring
| Factor |
Score (1-10) |
Question |
| Impact |
How much will this move the metric? |
Big change to primary KPI = 10 |
| Confidence |
How sure are we it will work? |
Strong data supporting hypothesis = 10 |
| Ease |
How easy is it to implement and measure? |
Can ship in a day = 10 |
ICE Score = (Impact + Confidence + Ease) / 3
Rank all test ideas by ICE score. Run highest first.
Test Backlog Template
| # |
Hypothesis |
Primary Metric |
ICE |
Est. Duration |
Status |
| 1 |
Larger CTA increases signups |
Signup rate |
8.3 |
2 weeks |
Ready |
| 2 |
Social proof on pricing increases conversion |
Plan selection rate |
7.0 |
3 weeks |
Needs design |
| 3 |
Shorter onboarding increases activation |
Feature activation |
6.7 |
4 weeks |
In backlog |
Proactive Triggers
- Someone debates between two design options: propose an A/B test instead of opinionating
- Conversion rate mentioned as underperforming: offer to design a test, not guess at solutions
- Pricing page changes discussed: always test pricing changes with guardrail metrics
- Post-launch of any feature: propose follow-up experiment to optimize
- "Let's just try it and see": redirect to structured hypothesis before implementation
Related Skills
| Skill |
Use When |
| analytics-tracking |
Setting up event tracking that feeds experiment metrics |
| campaign-analytics |
Folding experiment results into broader attribution |
| launch-strategy |
Testing within a product launch sequence |
| prompt-engineer-toolkit |
A/B testing AI prompts in production |
Tool Reference
sample_size_calculator.py
Calculates required sample size per variant using the normal approximation to the two-proportion z-test. Includes Bonferroni correction for multi-variant tests and duration estimation.
| Flag |
Type |
Default |
Description |
--baseline, -b |
float |
(required) |
Baseline conversion rate (e.g. 0.05 for 5%) |
--mde, -m |
float |
(required) |
Minimum detectable effect as relative lift (e.g. 0.10 for 10%) |
--alpha, -a |
float |
0.05 |
Significance level |
--power, -p |
float |
0.80 |
Statistical power |
--variants, -v |
int |
2 |
Number of variants including control |
--daily-traffic, -d |
int |
0 |
Daily eligible traffic for duration estimation |
--one-tailed |
flag |
False |
Use one-tailed test instead of two-tailed |
--json |
flag |
False |
Output as JSON |
python scripts/sample_size_calculator.py --baseline 0.05 --mde 0.10
python scripts/sample_size_calculator.py --baseline 0.12 --mde 0.15 --power 0.9 --daily-traffic 5000
python scripts/sample_size_calculator.py --baseline 0.05 --mde 0.10 --variants 3 --json
experiment_analyzer.py
Analyzes A/B test results using the two-proportion z-test with confidence intervals and segment breakdown.
| Flag |
Type |
Default |
Description |
input |
positional |
(required) |
CSV file with results or "sample" to create sample |
--alpha, -a |
float |
0.05 |
Significance level |
--json |
flag |
False |
Output as JSON |
CSV format: variant,visitors,conversions,segment
python scripts/experiment_analyzer.py sample
python scripts/experiment_analyzer.py results.csv
python scripts/experiment_analyzer.py results.csv --alpha 0.01 --json
experiment_planner.py
Generates a structured experiment plan from a hypothesis text, including metric selection, sample size, timeline, risks, and documentation template.
| Flag |
Type |
Default |
Description |
--hypothesis, -H |
string |
(required) |
Experiment hypothesis text |
--baseline, -b |
float |
0.05 |
Baseline conversion rate |
--mde, -m |
float |
0.10 |
Minimum detectable effect as relative lift |
--daily-traffic, -d |
int |
0 |
Daily eligible traffic |
--variants, -v |
int |
2 |
Number of variants including control |
--json |
flag |
False |
Output as JSON |
python scripts/experiment_planner.py --hypothesis "Larger CTA will increase signups by 15%"
python scripts/experiment_planner.py -H "Simplified checkout boosts conversions" -b 0.08 -m 0.15 -d 3000
python scripts/experiment_planner.py -H "New pricing page" --json
Troubleshooting
| Problem |
Cause |
Solution |
| Sample size is unrealistically large |
MDE too small or baseline too low |
Increase MDE (test bolder changes) or target a higher-traffic page |
| Test duration exceeds 6 weeks |
Insufficient daily traffic |
Consider qualitative methods, test bigger changes, or combine traffic from multiple pages |
| p-value hovers around 0.05 |
Borderline significance |
Do not stop early; run to planned sample size or extend 20% |
| Results significant but lift is tiny (<1%) |
Overpowered test |
Check practical significance alongside statistical significance |
| Segment results contradict overall |
Simpson's paradox |
Investigate segment composition; report both overall and segment results |
| Variant performs differently on mobile vs desktop |
Device-specific UX issues |
Design device-specific variants; increase per-segment sample size |
| Calculator produces negative CI |
Very small samples or extreme rates |
Ensure sufficient sample size; check data integrity |
Success Criteria
| Criterion |
Target |
How to Measure |
| Tests reach planned sample size |
100% of tests |
Compare actual vs planned sample at conclusion |
| False positive rate |
<5% |
Track post-implementation lift vs test prediction |
| Test velocity |
2+ tests per team per month |
Count experiments documented per sprint |
| Documentation completeness |
100% of tests documented |
Audit experiment records quarterly |
| Average test duration |
<4 weeks |
Measure start-to-conclusion calendar days |
| Decision quality |
>80% of shipped variants hold gains at 90 days |
Post-ship metric tracking |
Scope & Limitations
In scope:
- Hypothesis formulation and validation
- Sample size and power calculations
- Frequentist two-proportion z-tests
- A/B, A/B/n, and split URL test planning
- Segment-level analysis
- Pre/post test documentation
Out of scope:
- Bayesian A/B testing methods (use dedicated Bayesian tools)
- Multi-armed bandit algorithms (require real-time allocation infrastructure)
- Multivariate testing (MVT) analysis (combinatorial explosion requires specialized tools)
- Server-side feature flag implementation (see engineering skills)
- Revenue-based metrics requiring transaction-level data
- Sequential testing / always-valid p-values (use Optimizely Stats Engine or similar)
Integration Points
| Tool / Platform |
Integration Method |
Use Case |
| PostHog / Amplitude |
JSON export from experiment_analyzer |
Feed results into product analytics |
| Jira / Linear |
experiment_planner JSON output |
Create experiment tickets with metadata |
| Google Sheets |
CSV export from experiment_analyzer |
Share results with non-technical stakeholders |
| LaunchDarkly / Unleash |
experiment_planner checklist |
Pre-launch validation before feature flag rollout |
| Slack / Notion |
Copy human-readable output |
Async experiment status updates |
| CI/CD pipelines |
--json flag on all scripts |
Automated experiment health checks |
1---2name: ab-test-setup-23description: >4 Design and run statistically rigorous A/B tests and experiments. Use when5 planning experiments, calculating sample sizes, designing test variants,6 selecting metrics, analyzing results, or when someone says "let's test that."7license: MIT + Commons Clause8metadata:9 version: 1.0.010 author: borghei11 category: product-team12 domain: experimentation13 updated: 2026-03-0914 tags: [ab-testing, experimentation, hypothesis, statistical-significance]15 frameworks: hypothesis-testing, statistical-significance, feature-flags16---1718# A/B Test Setup - Experimentation Design & Analysis1920**Category:** Product Team21**Tags:** A/B testing, experiments, statistical significance, sample size, feature flags, hypothesis testing2223## Overview2425A/B Test Setup provides the complete framework for designing experiments that produce statistically valid, actionable results. Most A/B tests fail not because the variant was wrong, but because the test was poorly designed: wrong sample size, wrong metric, or someone peeked at results and stopped early. This skill prevents those mistakes.2627---2829## Clarify First3031Before designing the experiment, confirm these inputs. If any is unknown or vague, ASK — do not assume:3233- [ ] **Primary metric + minimum detectable effect** — the one success metric and smallest lift worth detecting (drives sample size, duration, and metric selection)34- [ ] **Baseline conversion rate** — current rate for the primary metric (sets required sample size per variant)35- [ ] **Available traffic to the test surface** — daily eligible visitors (decides whether the test is feasible or needs a bolder change / qualitative method)36- [ ] **The change and its rationale** — what varies and the data behind it (drives the hypothesis and variant design)3738Stop rule: ask only the 2-3 that most change the output. If the user says "just draft it," proceed and list your assumptions at the top of the artifact.3940## The Experiment Lifecycle4142```431. HYPOTHESIZE → 2. DESIGN → 3. CALCULATE → 4. IMPLEMENT44 ↑ │45 │ ▼467. ITERATE ← 6. DOCUMENT ← 5. ANALYZE ← [Run to completion]47```4849---5051## Step 1: Hypothesis Formulation5253### The Hypothesis Template5455```56Because [observation or data point],57we believe [specific change]58will cause [measurable outcome]59for [defined audience segment].6061We'll know this is true when [primary metric] changes by [minimum detectable effect].62We'll watch [guardrail metrics] to ensure no negative impact.63```6465### Good vs Bad Hypotheses6667| Quality | Hypothesis | Problem |68|---------|-----------|---------|69| Bad | "Changing the button color might increase clicks" | No data basis, no target, no measurement plan |70| Mediocre | "A green button will get more clicks than blue" | No "why", no target size, no guardrails |71| Good | "Because heatmaps show 40% of users don't notice our CTA, making the button 2x larger with contrasting color will increase CTA clicks by 15%+ for new visitors. Guardrail: page load time stays under 2s." | Data-backed, specific change, measurable outcome, defined audience, guardrail |7273### Hypothesis Sources (Where to Find Test Ideas)7475| Source | What to Look For | Example |76|--------|-----------------|---------|77| Analytics data | Drop-off points, low-performing pages | "80% of users drop off at step 3 of onboarding" |78| User research | Confusion, frustration, unmet needs | "Users don't understand what the product does from the homepage" |79| Heatmaps/session recordings | Ignored elements, rage clicks | "Nobody scrolls past the fold on pricing page" |80| Support tickets | Recurring complaints, feature confusion | "Users constantly ask how to invite team members" |81| Competitor analysis | Different approaches to same problem | "Competitor uses a wizard; we use a form" |82| Sales objections | Common reasons prospects don't convert | "Prospects want to see pricing before signing up" |8384---8586## Step 2: Test Design8788### Test Types8990| Type | Variants | Traffic Need | Best For |91|------|----------|-------------|---------|92| A/B | 2 (control + 1 variant) | Moderate | Single change validation |93| A/B/n | 3+ variants | High | Comparing multiple approaches |94| Multivariate (MVT) | Combinations of changes | Very high | Optimizing multiple elements |95| Split URL | Different pages | Moderate | Major redesigns |96| Bandit | Dynamic allocation | Low-moderate | Revenue optimization |9798**Default recommendation:** Standard A/B test. Only use A/B/n or MVT when you have enough traffic and a specific need.99100### What to Test (By Impact)101102| Category | High Impact | Medium Impact | Low Impact |103|----------|-----------|---------------|-----------|104| **Copy** | Headline/value prop, CTA text | Body copy, social proof | Microcopy, labels |105| **Design** | Page layout, above-fold content | Visual hierarchy, imagery | Color, font size |106| **UX** | Number of steps, form fields | Button placement, navigation | Animations, transitions |107| **Pricing** | Price point, plan names | Feature packaging, anchoring | Billing frequency display |108| **Social Proof** | Testimonials vs none, logos | Testimonial format, placement | Testimonial count |109110### Metric Selection111112Every test needs three types of metrics:113114**Primary Metric (1 only)**115- The single metric that determines success116- Directly tied to the hypothesis117- Must be measurable within the test duration118- Examples: signup rate, click-through rate, purchase rate119120**Secondary Metrics (2-3)**121- Explain why the primary metric moved122- Provide context for decision-making123- Examples: time on page, scroll depth, feature adoption rate124125**Guardrail Metrics (1-3)**126- Things that must NOT get worse127- Stop the test if significantly negative128- Examples: error rate, support ticket volume, page load time, refund rate129130---131132## Step 3: Sample Size Calculation133134### Quick Reference Table135136Minimum visitors PER VARIANT needed (95% confidence, 80% power):137138| Baseline Rate | 5% Lift | 10% Lift | 15% Lift | 20% Lift | 50% Lift |139|--------------|---------|----------|----------|----------|----------|140| 1% | 620,000 | 156,000 | 70,000 | 39,000 | 6,400 |141| 2% | 305,000 | 77,000 | 34,000 | 19,500 | 3,200 |142| 3% | 200,000 | 51,000 | 23,000 | 12,800 | 2,100 |143| 5% | 116,000 | 29,500 | 13,200 | 7,500 | 1,250 |144| 10% | 54,000 | 13,800 | 6,200 | 3,500 | 600 |145| 20% | 24,000 | 6,200 | 2,800 | 1,600 | 280 |146| 50% | 6,100 | 1,600 | 720 | 410 | 75 |147148### Duration Calculation149150```151Duration (days) = (Sample size per variant * Number of variants) / Daily traffic to test page152```153154**Minimum duration:** 7 days (to capture day-of-week effects)155**Maximum recommended:** 6 weeks (beyond this, external factors contaminate results)156157### What If You Don't Have Enough Traffic?158159| Situation | Solution |160|-----------|----------|161| Need 100K visitors, get 5K/week | Increase minimum detectable effect (test bolder changes) |162| Very low traffic (<1K/week) | Use qualitative testing (user testing, surveys) instead |163| Medium traffic (5-20K/week) | Run for 4-6 weeks, test big changes only |164| High traffic (50K+/week) | You can test subtle changes, run multiple tests |165166---167168## Step 4: Implementation169170### Client-Side Implementation171172JavaScript modifies the page after initial render.173174**Pros:** Quick to implement, no deploy needed175**Cons:** Can cause flicker (flash of original content), blocked by ad blockers176**Tools:** PostHog, Optimizely, VWO, Google Optimize177178**Anti-flicker pattern:**179```javascript180// Add to <head> before any rendering181<style>.ab-test-hide { opacity: 0 !important; }</style>182<script>document.documentElement.classList.add('ab-test-hide');</script>183184// In your test script (runs after variant assignment):185document.documentElement.classList.remove('ab-test-hide');186```187188### Server-Side Implementation189190Variant determined before page renders. No flicker, no client-side dependency.191192**Pros:** No flicker, not blocked by ad blockers, works for logged-in features193**Cons:** Requires engineering work, deploy needed194**Tools:** PostHog, LaunchDarkly, Split, Unleash, custom feature flags195196**Basic feature flag pattern:**197```python198# Server-side variant assignment199def get_variant(user_id: str, experiment: str) -> str:200 # Deterministic hash ensures same user always sees same variant201 hash_input = f"{user_id}:{experiment}"202 hash_value = hashlib.md5(hash_input.encode()).hexdigest()203 bucket = int(hash_value[:8], 16) % 100204205 if bucket < 50:206 return "control"207 else:208 return "variant"209```210211### Traffic Allocation212213| Strategy | Split | When to Use |214|----------|-------|-------------|215| Standard | 50/50 | Default. Maximum statistical power. |216| Conservative | 90/10 or 80/20 | Risky changes, revenue-impacting tests |217| Ramped | Start 95/5, increase to 50/50 | New infrastructure, technical risk |218219**Critical rules:**220- Users must see the same variant on every visit (sticky assignment by user ID or cookie)221- Allocation must be balanced across time of day and day of week222- Never change allocation mid-test223224---225226## Step 5: Running the Test227228### Pre-Launch Checklist229230- [ ] Hypothesis documented with primary metric and minimum detectable effect231- [ ] Sample size calculated, expected duration estimated232- [ ] Both variants implemented and QA'd on all device types233- [ ] Tracking verified (events fire correctly for both variants)234- [ ] No other tests running on the same page/feature235- [ ] Stakeholders informed of test duration and "no peeking" rule236- [ ] External factor calendar checked (no major launches, holidays, press)237238### During the Test239240**DO:**241- Monitor for technical errors (variant not rendering, tracking broken)242- Check that traffic split is balanced daily243- Document any external events that might affect results244245**DO NOT:**246- Look at results before reaching sample size ("peeking problem")247- Make changes to either variant248- Add traffic from new sources mid-test249- Stop the test early because one variant "looks like it's winning"250251### The Peeking Problem (Critical)252253Looking at results before reaching the planned sample size and stopping because one variant looks better leads to a **25-40% false positive rate** (vs the intended 5%).254255Why: Statistical significance fluctuates wildly with small samples. A variant can show p < 0.05 at 20% of planned sample size and p > 0.30 at full sample.256257**Solutions:**2581. Pre-commit to sample size and do not check results until reached2592. If you must monitor: use sequential testing methods (group sequential design, always-valid p-values)2603. Set calendar reminder for expected completion date -- that is when you look261262---263264## Step 6: Analysis265266### Analysis Checklist2672681. **Did we reach planned sample size?** If not, results are preliminary only.2692. **Is it statistically significant?** p < 0.05 = 95% confidence the difference is real.2703. **What's the confidence interval?** Tells you the range of likely true effect.2714. **Is the effect size meaningful?** A 0.1% lift that's "significant" may not be worth implementing.2725. **Are secondary metrics consistent?** Do they support the primary result?2736. **Any guardrail violations?** Did anything get worse?2747. **Segment analysis:** Different results for mobile vs desktop? New vs returning?275276### Interpreting Results277278| Result | Primary Metric | Confidence | Action |279|--------|---------------|------------|--------|280| Clear winner | Variant +15%, p < 0.01 | High | Implement variant |281| Modest winner | Variant +5%, p < 0.05 | Medium | Implement if easy, else run longer |282| Flat | < 2% difference, p > 0.20 | High (no effect) | Keep control, test something bolder |283| Loser | Variant -10%, p < 0.05 | High | Keep control, investigate why |284| Inconclusive | 5% difference, p = 0.08 | Low | Need more traffic or bolder test |285| Mixed signals | Primary up, guardrail down | Investigate | Dig into segments, do not ship blindly |286287### Common Analysis Mistakes288289| Mistake | Consequence | Prevention |290|---------|-------------|------------|291| Stopping at first significance | 25-40% false positive rate | Commit to sample size |292| Cherry-picking segments | Finding "winners" that don't replicate | Pre-register segments of interest |293| Ignoring confidence intervals | Overestimating effect size | Always report CI alongside p-value |294| Multiple comparisons | Inflated Type I error | Bonferroni correction for A/B/n |295| Survivorship bias | Only analyzing users who completed flow | Include all users from assignment point |296| Simpson's paradox | Aggregate hides segment reversal | Always check key segments |297298---299300## Step 7: Documentation301302Every test must be documented, regardless of outcome.303304### Test Documentation Template305306```307EXPERIMENT: [Name]308DATE: [Start] to [End]309OWNER: [Name]310311HYPOTHESIS:312Because [observation], we believed [change] would cause [outcome] for [audience].313314VARIANTS:315- Control: [description]316- Variant: [description + screenshot]317318METRICS:319- Primary: [metric] (baseline: [X]%, MDE: [Y]%)320- Secondary: [metrics]321- Guardrails: [metrics]322323RESULTS:324- Sample size: [actual] / [planned]325- Duration: [X] days326- Primary metric: Control [X]% vs Variant [Y]% (p = [Z], CI: [range])327- Secondary metrics: [results]328- Guardrails: [all clear / violation noted]329330DECISION: [Ship variant / Keep control / Iterate]331332LEARNINGS:333- [What we learned about our users]334- [What we'd do differently next time]335```336337---338339## Experiment Prioritization Framework340341### ICE Scoring342343| Factor | Score (1-10) | Question |344|--------|-------------|----------|345| **Impact** | How much will this move the metric? | Big change to primary KPI = 10 |346| **Confidence** | How sure are we it will work? | Strong data supporting hypothesis = 10 |347| **Ease** | How easy is it to implement and measure? | Can ship in a day = 10 |348349**ICE Score = (Impact + Confidence + Ease) / 3**350351Rank all test ideas by ICE score. Run highest first.352353### Test Backlog Template354355| # | Hypothesis | Primary Metric | ICE | Est. Duration | Status |356|---|-----------|---------------|-----|---------------|--------|357| 1 | Larger CTA increases signups | Signup rate | 8.3 | 2 weeks | Ready |358| 2 | Social proof on pricing increases conversion | Plan selection rate | 7.0 | 3 weeks | Needs design |359| 3 | Shorter onboarding increases activation | Feature activation | 6.7 | 4 weeks | In backlog |360361---362363## Proactive Triggers364365- Someone debates between two design options: propose an A/B test instead of opinionating366- Conversion rate mentioned as underperforming: offer to design a test, not guess at solutions367- Pricing page changes discussed: always test pricing changes with guardrail metrics368- Post-launch of any feature: propose follow-up experiment to optimize369- "Let's just try it and see": redirect to structured hypothesis before implementation370371---372373## Related Skills374375| Skill | Use When |376|-------|----------|377| **analytics-tracking** | Setting up event tracking that feeds experiment metrics |378| **campaign-analytics** | Folding experiment results into broader attribution |379| **launch-strategy** | Testing within a product launch sequence |380| **prompt-engineer-toolkit** | A/B testing AI prompts in production |381382---383384## Tool Reference385386### sample_size_calculator.py387388Calculates required sample size per variant using the normal approximation to the two-proportion z-test. Includes Bonferroni correction for multi-variant tests and duration estimation.389390| Flag | Type | Default | Description |391|------|------|---------|-------------|392| `--baseline`, `-b` | float | (required) | Baseline conversion rate (e.g. 0.05 for 5%) |393| `--mde`, `-m` | float | (required) | Minimum detectable effect as relative lift (e.g. 0.10 for 10%) |394| `--alpha`, `-a` | float | 0.05 | Significance level |395| `--power`, `-p` | float | 0.80 | Statistical power |396| `--variants`, `-v` | int | 2 | Number of variants including control |397| `--daily-traffic`, `-d` | int | 0 | Daily eligible traffic for duration estimation |398| `--one-tailed` | flag | False | Use one-tailed test instead of two-tailed |399| `--json` | flag | False | Output as JSON |400401```bash402python scripts/sample_size_calculator.py --baseline 0.05 --mde 0.10403python scripts/sample_size_calculator.py --baseline 0.12 --mde 0.15 --power 0.9 --daily-traffic 5000404python scripts/sample_size_calculator.py --baseline 0.05 --mde 0.10 --variants 3 --json405```406407### experiment_analyzer.py408409Analyzes A/B test results using the two-proportion z-test with confidence intervals and segment breakdown.410411| Flag | Type | Default | Description |412|------|------|---------|-------------|413| `input` | positional | (required) | CSV file with results or "sample" to create sample |414| `--alpha`, `-a` | float | 0.05 | Significance level |415| `--json` | flag | False | Output as JSON |416417**CSV format:** `variant,visitors,conversions,segment`418419```bash420python scripts/experiment_analyzer.py sample421python scripts/experiment_analyzer.py results.csv422python scripts/experiment_analyzer.py results.csv --alpha 0.01 --json423```424425### experiment_planner.py426427Generates a structured experiment plan from a hypothesis text, including metric selection, sample size, timeline, risks, and documentation template.428429| Flag | Type | Default | Description |430|------|------|---------|-------------|431| `--hypothesis`, `-H` | string | (required) | Experiment hypothesis text |432| `--baseline`, `-b` | float | 0.05 | Baseline conversion rate |433| `--mde`, `-m` | float | 0.10 | Minimum detectable effect as relative lift |434| `--daily-traffic`, `-d` | int | 0 | Daily eligible traffic |435| `--variants`, `-v` | int | 2 | Number of variants including control |436| `--json` | flag | False | Output as JSON |437438```bash439python scripts/experiment_planner.py --hypothesis "Larger CTA will increase signups by 15%"440python scripts/experiment_planner.py -H "Simplified checkout boosts conversions" -b 0.08 -m 0.15 -d 3000441python scripts/experiment_planner.py -H "New pricing page" --json442```443444---445446## Troubleshooting447448| Problem | Cause | Solution |449|---------|-------|----------|450| Sample size is unrealistically large | MDE too small or baseline too low | Increase MDE (test bolder changes) or target a higher-traffic page |451| Test duration exceeds 6 weeks | Insufficient daily traffic | Consider qualitative methods, test bigger changes, or combine traffic from multiple pages |452| p-value hovers around 0.05 | Borderline significance | Do not stop early; run to planned sample size or extend 20% |453| Results significant but lift is tiny (<1%) | Overpowered test | Check practical significance alongside statistical significance |454| Segment results contradict overall | Simpson's paradox | Investigate segment composition; report both overall and segment results |455| Variant performs differently on mobile vs desktop | Device-specific UX issues | Design device-specific variants; increase per-segment sample size |456| Calculator produces negative CI | Very small samples or extreme rates | Ensure sufficient sample size; check data integrity |457458---459460## Success Criteria461462| Criterion | Target | How to Measure |463|-----------|--------|----------------|464| Tests reach planned sample size | 100% of tests | Compare actual vs planned sample at conclusion |465| False positive rate | <5% | Track post-implementation lift vs test prediction |466| Test velocity | 2+ tests per team per month | Count experiments documented per sprint |467| Documentation completeness | 100% of tests documented | Audit experiment records quarterly |468| Average test duration | <4 weeks | Measure start-to-conclusion calendar days |469| Decision quality | >80% of shipped variants hold gains at 90 days | Post-ship metric tracking |470471---472473## Scope & Limitations474475**In scope:**476- Hypothesis formulation and validation477- Sample size and power calculations478- Frequentist two-proportion z-tests479- A/B, A/B/n, and split URL test planning480- Segment-level analysis481- Pre/post test documentation482483**Out of scope:**484- Bayesian A/B testing methods (use dedicated Bayesian tools)485- Multi-armed bandit algorithms (require real-time allocation infrastructure)486- Multivariate testing (MVT) analysis (combinatorial explosion requires specialized tools)487- Server-side feature flag implementation (see engineering skills)488- Revenue-based metrics requiring transaction-level data489- Sequential testing / always-valid p-values (use Optimizely Stats Engine or similar)490491---492493## Integration Points494495| Tool / Platform | Integration Method | Use Case |496|-----------------|-------------------|----------|497| PostHog / Amplitude | JSON export from experiment_analyzer | Feed results into product analytics |498| Jira / Linear | experiment_planner JSON output | Create experiment tickets with metadata |499| Google Sheets | CSV export from experiment_analyzer | Share results with non-technical stakeholders |500| LaunchDarkly / Unleash | experiment_planner checklist | Pre-launch validation before feature flag rollout |501| Slack / Notion | Copy human-readable output | Async experiment status updates |502| CI/CD pipelines | `--json` flag on all scripts | Automated experiment health checks |