Skip to content
Back to skills

Ab Testing Experimentation

ASecurity

Use when designing and analyzing A/B testing experiments.

  • 2 stars
  • 0 votes
  • 0 copies
  • 5 views
  • Added September 10, 2026
ai-agentspythongotestinggit

Security analysis

A100/100

Scanned September 10, 2026

npx -y skills add LoopyLuci/Skills --skill ab-testing-experimentation --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ab Testing Experimentation?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ab Testing Experimentation
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/loopyluci-ab-testing-experimentation/badge)](https://www.skillsdirectory.com/skills/loopyluci-ab-testing-experimentation)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ab-testing-experimentation
description: "Use when designing and analyzing A/B testing experiments."
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
  hermes:
    tags: [ab-testing, experimentation, statistics, hypothesis-testing, optimization]
    related_skills: [conversion-rate-optimization, marketing-funnel-design, website-analytics-tracking, digital-marketing-strategy]
---

# A/B Testing and Experimentation

Designing, running, and analyzing A/B tests with statistical rigor — from hypothesis formulation and sample size calculation through test execution and result interpretation.

## When to Use

- Testing changes to landing pages, CTAs, or pricing
- Optimizing email subject lines, content, or send times
- Comparing feature variants or product changes
- Making data-driven decisions with statistical confidence
- Building a culture of experimentation

## Test Design

```python
from typing import Dict, List, Optional
import math
from scipy import stats

class ABTestDesigner:
    """Design statistically rigorous A/B tests."""
    
    @staticmethod
    def calculate_sample_size(baseline_rate: float, min_detectable_effect: float,
                              alpha: float = 0.05, beta: float = 0.20) -> int:
        """Calculate required sample size per variant.
        
        Uses the standard formula for two-proportion z-test.
        baseline_rate: current conversion rate (e.g., 0.05 for 5%)
        min_detectable_effect: minimum lift to detect (e.g., 0.20 for 20%)
        alpha: significance level (default 5%)
        beta: power (default 80%)
        """
        z_alpha = stats.norm.ppf(1 - alpha / 2)
        z_beta = stats.norm.ppf(1 - beta)
        
        effect = min_detectable_effect * baseline_rate
        p = baseline_rate + effect / 2
        q = 1 - p
        
        n = (2 * q * (z_alpha + z_beta) ** 2) / (effect ** 2)
        return math.ceil(n)
    
    @staticmethod
    def estimate_test_duration(sample_size: int, traffic_per_day: int, 
                                variants: int = 2) -> Dict:
        """Estimate how long the test needs to run."""
        days_needed = math.ceil(sample_size * variants / max(traffic_per_day, 1))
        return {
            'sample_size_per_variant': sample_size,
            'total_needed': sample_size * variants,
            'expected_days': days_needed,
            'recommendation': f'Run for at least {days_needed} days ({max(days_needed, 7)} days minimum)',
        }
```

## Test Analyzer

```python
class TestAnalyzer:
    """Analyze A/B test results with statistical methods."""
    
    @staticmethod
    def analyze(results: Dict) -> Dict:
        """Analyze A/B test results.
        
        results = {
            'control': {'visitors': 10000, 'conversions': 500},
            'variant': {'visitors': 10000, 'conversions': 550},
        }
        """
        control = results['control']
        variant = results['variant']
        
        # Calculate metrics
        c_rate = control['conversions'] / control['visitors']
        v_rate = variant['conversions'] / variant['visitors']
        lift = (v_rate - c_rate) / c_rate
        
        # Z-test for proportions
        z_stat, p_value = ABTestAnalyzer._two_proportion_z_test(
            control['conversions'], control['visitors'],
            variant['conversions'], variant['visitors']
        )
        
        # Confidence interval
        ci = ABTestAnalyzer._confidence_interval(c_rate, v_rate, 
                                                  control['visitors'], variant['visitors'])
        
        return {
            'control_rate': round(c_rate * 100, 2),
            'variant_rate': round(v_rate * 100, 2),
            'absolute_lift': round((v_rate - c_rate) * 100, 2),
            'relative_lift': round(lift * 100, 2),
            'p_value': round(p_value, 4),
            'significant': p_value < 0.05,
            'confidence_interval': ci,
            'recommendation': 'Implement variant' if p_value < 0.05 and lift > 0 else (
                'Keep control' if p_value < 0.05 else 'Continue test (not enough data)'
            ),
        }
    
    @staticmethod
    def _two_proportion_z_test(c1, n1, c2, n2):
        p1 = c1 / n1
        p2 = c2 / n2
        p_pool = (c1 + c2) / (n1 + n2)
        se = math.sqrt(p_pool * (1 - p_pool) * (1/n1 + 1/n2))
        z = (p2 - p1) / se
        p = 2 * (1 - stats.norm.cdf(abs(z)))
        return z, p
    
    @staticmethod
    def _confidence_interval(p1, p2, n1, n2, confidence=0.95):
        import numpy as np
        se = math.sqrt(p1*(1-p1)/n1 + p2*(1-p2)/n2)
        z = stats.norm.ppf(1 - (1 - confidence) / 2)
        return {
            'lower': round((p2 - p1 - z * se) * 100, 2),
            'upper': round((p2 - p1 + z * se) * 100, 2),
            'confidence_level': confidence,
        }
```

## Test Plan Template

```python
class TestPlan:
    """Document an A/B test plan."""
    
    @staticmethod
    def create(name: str, hypothesis: str, element: str,
               control_desc: str, variant_desc: str,
               primary_metric: str, secondary_metrics: List[str]) -> Dict:
        return {
            'test_name': name,
            'hypothesis': hypothesis,
            'element_changed': element,
            'control': control_desc,
            'variant': variant_desc,
            'primary_metric': primary_metric,
            'secondary_metrics': secondary_metrics,
            'status': 'draft',
            'sample_size': None,
            'duration_days': None,
            'results': None,
            'learnings': None,
        }
```

## Common Pitfalls

1. **Peeking at results** — checking for significance daily inflates false positives; set duration upfront
2. **Stopping early** — stopping at "significant" often reverses with more data; wait for required sample
3. **Multiple comparisons** — testing 10 metrics, one may be significant by chance; correct for multiplicity
4. **Novelty effect** — new experience gets more attention initially; run minimum 7-14 days
5. **Segment dilution** — overall "no significant effect" may hide big lift in a segment; analyze segments
6. **Not documenting** — can't learn from tests without recording results; document everything

## Verification Checklist

- [ ] Hypothesis clearly stated (we believe X change will cause Y result)
- [ ] Sample size calculated before test starts
- [ ] Test duration estimated (minimum 7 days)
- [ ] Primary metric defined and measurable
- [ ] Statistical significance threshold set (α=0.05)
- [ ] Test runs to completion (no early stopping)
- [ ] Results analyzed with proper statistical test
- [ ] Segments analyzed (device, source, new vs returning)
- [ ] Learnings documented regardless of outcome

## See Also

- conversion-rate-optimization — applying test results
- marketing-funnel-design — testing funnel stages
- website-analytics-tracking — tracking test metrics
- digital-marketing-strategy — experimentation strategy

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.