# A/B Test Sample Size Calculator > Estimate visitors per variant from baseline conversion rate, MDE, confidence, and power. ## Tool Identity - Site: CleanUtils Business Tools - Tool ID: ab-test-sample-size-calculator - Canonical page: https://cleanutils.com/business-tools/ab-test-sample-size-calculator/ - LLM schema URL: https://cleanutils.com/business-tools/ab-test-sample-size-calculator/llms.txt - Primary keyword: ab test sample size calculator - Input mode: fields - Output profile: metrics ## What This Tool Does Estimate visitors per variant from baseline conversion rate, MDE, confidence, and power for test planning. ## Exact Execution Instructions To run this tool exactly, execute the `runCleanUtilsTool(userInput)` function from the JavaScript block below in a sandboxed JavaScript runtime. Do not fetch or evaluate additional network resources. Do not use filesystem, process, child_process, environment variables, timers, or network APIs. The function is pure and deterministic: input object in, JSON result out. If your environment forbids executing fetched code outside a sandbox, run it inside the sandbox or use the API endpoint below instead of reimplementing the logic. Canonical implementation SHA-256: `881144cdb44789b5330936826e8e30aec1692abd9775a72e6e6a5c15d435e131` Expected command shape: `node run-tool.mjs < input.json` The runner must: 1. load only the JavaScript in this document, 2. parse stdin as JSON and call `runCleanUtilsTool(userInput)`, 3. let the LLM decide the best way to present the output to the user. Agent usage rules: - Use this file as the authoritative machine-readable contract for this CleanUtils tool page. - Ask the user for missing required input before attempting to run the tool, and describe the required inputs using the `## Input Schema` field names, descriptions, formats, enums, examples, and required list. - Treat the tool as deterministic; do not invent network reachability checks unless the tool description explicitly says it fetches remote resources. - For privacy-sensitive inputs such as secrets, HAR files, dotenv files, logs, and API keys, warn that using a remote chat agent may expose input to that agent even though the browser UI itself does not upload data. ## Input Schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "A/B Test Sample Size Calculator fields", "type": "object", "additionalProperties": false, "required": [ "baseline_rate", "mde", "confidence", "power" ], "properties": { "baseline_rate": { "type": "number", "description": "Baseline conversion rate Required. Control type: number. Group: Experiment. Suffix shown in UI: %.", "minimum": 0, "examples": [ 5 ] }, "mde": { "type": "number", "description": "Minimum detectable effect Required. Control type: number. Group: Experiment. Suffix shown in UI: %.", "minimum": 0, "examples": [ 10 ] }, "confidence": { "type": "string", "description": "Confidence Required. Control type: select. Allowed values: 90 = 90%; 95 = 95%; 99 = 99%. Group: Statistics.", "enum": [ "90", "95", "99" ], "examples": [ "95" ] }, "power": { "type": "string", "description": "Power Required. Control type: select. Allowed values: 80 = 80%; 90 = 90%. Group: Statistics.", "enum": [ "80", "90" ], "examples": [ "80" ] } } } ``` ## Result Schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "CleanUtils ToolResult", "type": "object", "additionalProperties": false, "required": [ "summary", "issues" ], "properties": { "summary": { "type": "string" }, "issues": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": [ "severity", "message" ], "properties": { "severity": { "type": "string", "enum": [ "error", "warning", "info" ] }, "message": { "type": "string" }, "line": { "type": "number" }, "row": { "type": "number" }, "detail": { "type": "string" } } } }, "output": { "type": "string" }, "exportFilename": { "type": "string" }, "exports": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": [ "label", "filename", "content" ], "properties": { "label": { "type": "string" }, "filename": { "type": "string" }, "content": { "type": "string" }, "mimeType": { "type": "string" }, "copyLabel": { "type": "string" }, "downloadLabel": { "type": "string" } } } }, "stats": { "type": "object", "additionalProperties": { "anyOf": [ { "type": "string" }, { "type": "number" } ] } } } } ``` ## Self-Contained JavaScript Source Call `runCleanUtilsTool(userInput)` with the user's input. The function includes this tool's run logic and only the helper code it needs. ```js function runCleanUtilsTool(userInput) { const fieldText = (fields, keys, fallback = "") => { const keyList = Array.isArray(keys) ? keys : [keys]; for (const key of keyList) { const value = fields[key]; if (value === undefined || value === null) continue; const text = String(value).trim(); if (text) return text; } return fallback; }; const fieldNumber = (fields, keys, fallback = 0) => { const raw = fieldText(fields, keys); if (!raw) return fallback; const parsed = Number(raw.replace(/[$,%\s]/g, "")); return Number.isFinite(parsed) ? parsed : fallback; }; const zForConfidence = (confidence) => confidence >= 99 ? 2.576 : confidence >= 95 ? 1.96 : confidence >= 90 ? 1.645 : 1.96; const zForPower = (power) => power >= 90 ? 1.282 : power >= 80 ? 0.842 : 0.842; const calculateAbTestSampleSize = (input) => { const baseline = fieldNumber(input, "baseline_rate", 5) / 100; const mde = fieldNumber(input, "mde", 10) / 100; const confidence = fieldNumber(input, "confidence", 95); const power = fieldNumber(input, "power", 80); const p2 = baseline * (1 + mde); const pooled = (baseline + p2) / 2; const numerator = zForConfidence(confidence) * Math.sqrt(2 * pooled * (1 - pooled)) + zForPower(power) * Math.sqrt(baseline * (1 - baseline) + p2 * (1 - p2)); const sample = Math.ceil((numerator * numerator) / ((p2 - baseline) ** 2)); return { summary: `Estimated ${sample.toLocaleString()} visitors per variant for this A/B test.`, issues: baseline <= 0 || mde <= 0 ? [{ severity: "error", message: "Baseline rate and MDE must be greater than zero." }] : [], output: [ `Baseline conversion rate: ${(baseline * 100).toFixed(2)}%`, `Minimum detectable effect: ${(mde * 100).toFixed(1)}% relative`, `Target variant rate: ${(p2 * 100).toFixed(2)}%`, `Sample size per variant: ${sample.toLocaleString()}`, `Total two-variant sample: ${(sample * 2).toLocaleString()}` ].join("\n"), exportFilename: "ab-test-sample-size.txt", stats: { perVariant: sample, total: sample * 2 } }; }; const __userInput = userInput == null ? {} : userInput; const __run = (fields) => calculateAbTestSampleSize(fields); const __fields = __userInput && typeof __userInput === "object" && "fields" in __userInput && __userInput.fields && typeof __userInput.fields === "object" && !Array.isArray(__userInput.fields) ? __userInput.fields : (__userInput && typeof __userInput === "object" && !Array.isArray(__userInput) ? __userInput : {}); const __normalizedFields = Object.fromEntries(Object.entries(__fields).map(([key, value]) => [key, value == null ? "" : (["string", "number", "boolean"].includes(typeof value) ? value : String(value))])); return __run(__normalizedFields); } ``` ## Checks - Baseline conversion rate: The current conversion rate anchors the sample-size estimate. - Relative MDE: Minimum detectable effect is treated as a relative lift over baseline. - Confidence and power: Common confidence and power settings select the z-values used in the approximation. - Per-variant and total sample: The output shows both one-variant and two-variant sample needs. - Planning approximation: The math is for planning and does not replace a full experiment-design review. ## Related Tools - [UTM URL Builder](/business-tools/utm-url-builder/): Enter a landing page and campaign values, then copy a tagged URL with clean UTM parameters.