---
title: "How to Declare a Winner and Remove All A/B Testing Code in One PR"
description: "The part of A/B testing most tools skip. Here's what a clean winner declaration actually requires, and why most setups leave dead code behind."
canonical: https://landtest.dev/blog/how-to-declare-winner-remove-ab-testing-code
last-updated: 2026-10-30
---

# How to Declare a Winner and Remove All A/B Testing Code in One PR

> The part of A/B testing most tools skip. Here's what a clean winner declaration actually requires, and why most setups leave dead code behind.

Declaring a winner and removing A/B testing code in one PR requires three things most setups don't have by default: the losing variant needs to be an isolated branch (not mixed into main behind a runtime check), the test scaffolding (analytics beacon, anti-flicker boot script, split configuration) needs to be identifiable as a discrete diff, and the decision to stop needs to come from a statistical method that doesn't require you to keep the test running "just a bit longer to be sure." Most tools handle the statistics; almost none handle the cleanup.

## Why cleanup usually doesn't happen

A flag-based A/B test (GrowthBook, LaunchDarkly, a hand-rolled cookie check) embeds the split as a runtime branch: `if (flagEnabled) { return <VariantB /> } else { return <VariantA /> }`. When the test ends, "removing the code" means finding every place that flag is checked, deleting the losing branch, deleting the flag itself, and deleting the flag from the platform's dashboard. Each of those is a manual step, and [LaunchDarkly's own reviewers cite stale flags as the most common complaint](https://www.growthbook.io/insights/launchdarkly-review) precisely because that cleanup is easy to defer and easy to forget.

A visual-editor test (VWO, Optimizely, Convert) has the opposite problem: the winning variant often only exists inside the tool's runtime layer, never as committed code. "Cleanup" here means someone has to manually rebuild the winning version into the actual page source — a second implementation of something that already worked once.

## What a clean cleanup actually looks like

The variant needs to exist as a real branch from the start, not a runtime conditional. That way, "the test is over" maps directly onto "merge this branch, delete that one" — a normal git operation your team already understands, not a special procedure for undoing test infrastructure. The beacon script, anti-flicker boot snippet, and any split configuration need to be scoped to files that can be deleted wholesale, not scattered as inline conditionals through your components. And the decision to stop needs to come from a method — mSPRT sequential testing checked against an SRM-verified split — that gives you a real answer at whatever point you check it, rather than a fixed sample size you have to wait out regardless of how clear the result already looks.

This is the specific design goal behind Landtest's workflow: winner declared → one PR → beacon, boot script, and losing branch all removed → back to a bare `page.tsx`. Not because the statistics are different from what a well-configured GrowthBook or Statsig setup can produce, but because the artifact you're left with afterward is a normal, clean codebase rather than a flag someone will trip over in eight months.

## FAQ

**Why do A/B testing flags become tech debt?**
Because removing a flag is a manual, multi-step process (find every check, delete the losing branch, delete the flag from the platform) that's easy to defer once the test result is already known and the team has moved on.

**What should be removed when an A/B test ends?**
The losing variant's code, any analytics beacon or anti-flicker script added specifically for the test, and the split/routing configuration — ideally as one reviewable diff, not scattered edits across the codebase.

**How does Landtest handle test cleanup?**
Declaring a winner generates a PR that removes the losing branch and all test scaffolding, leaving a bare `page.tsx` with the winning version as the only code path.

---

Related: [Best A/B testing tools for Next.js developers](/blog/best-ab-testing-tools-nextjs-developers) · [A/B test without middleware conflicts](/blog/ab-test-nextjs-landing-page-without-middleware-conflicts) · [Landtest for A/B testing](/ab-testing)
