Guide
How A/B testing tools avoid flicker without slowing down your website
A/B testing tools avoid flicker by applying the variant before the browser paints the original. There are three ways: a small synchronous script in the head, an anti-flicker snippet that hides the page or only the tested elements until the changes are in (with a timeout), or server-side and edge testing that sends the variant in the HTML. Each trades a little speed for safety; the fastest setups hide as little as possible, for as short as possible.
Last reviewed Markdown version
Definition
Flicker (a flash of original content) is the moment a visitor sees the original page before a client-side testing script swaps in the variant. It looks broken, can shift the layout, and biases the test: only the variant's visitors see the jump.Why client-side tests flicker
A browser paints as soon as it can. If the testing script arrives after the element it changes has been painted, the visitor sees the original first. Common reasons: the script loads asynchronously or through a tag manager, a performance plugin defers or delays it, the change runs after a slow network request, or a JavaScript framework re-renders the element and puts the original back.
The three techniques
1. A synchronous script in the head
The script sits in the head, without async or defer, so the browser runs it before it renders the body. It can change elements as they are parsed, before the first paint. The cost is one render-blocking request, which is why the script must be small, served from a fast CDN and cached. Optimizely's documentation says its Web Experimentation snippet is synchronous to prevent flickering, and that variation code can be loaded asynchronously as an option (Optimizely docs).
2. An asynchronous script with an anti-flicker snippet
The script loads without blocking the page, and a small inline snippet hides content until the tool reports it has applied the changes, or until a timeout runs out. The timeout matters: without one, a slow or blocked script leaves a blank page. VWO (Wingify) documents this model for its asynchronous SmartCode: it hides the page body by default, waits up to 2,000 ms for settings and 2,500 ms for its library by default, and lets you choose which element to hide instead, with a warning that hiding nothing may flash original content (Wingify help).
Hiding the whole page is the safest against flicker and the most visible on slow connections: nothing shows until the timeout. Hiding only the elements under test lets the rest of the page render normally.
3. Server-side or edge testing
The variant is chosen on your server, at the edge or in your code behind a feature flag, so the HTML arrives already changed. There is nothing to swap in the browser and nothing to hide. The cost is setup: a developer, a deploy per test, and caching that knows about variants. It is the right choice for tests that change behaviour (a checkout flow, pricing logic) rather than what a page looks like.
| Technique | Flicker | Speed cost | Who sets up a test |
|---|---|---|---|
| Synchronous script in the head | None if the script is fast and not deferred | One small blocking request | Marketers or an agent, no deploy |
| Async script + anti-flicker snippet | None until the timeout, then the original | Hidden content up to the timeout | Marketers or an agent, no deploy |
| Server-side or edge | None | Variant logic on the server | Developers, a deploy per test |
What actually slows the page down
- Script size and caching. Every kilobyte in a blocking script delays rendering; a script that is cached and revalidated cheaply costs little on repeat visits.
- How much is hidden, and for how long. Hiding the body delays everything; hiding three elements delays three elements. Keep the timeout as short as your script reliably loads.
- Optimisers that rewrite scripts. Rocket Loader, WP Rocket, LiteSpeed and similar tools can defer a synchronous testing script, which brings the flicker back. Exclude the script from them.
- Tag managers. A script loaded through a tag manager always runs later than one in the HTML.
- Layout shift. A variant that inserts or resizes content after paint moves the page; that shows up in Cumulative Layout Shift.
The React and Next.js catch: hydration
On server-rendered React, Vue, Svelte or Astro sites, changing text or structure before the framework has hydrated the element makes it throw the server HTML away or report a mismatch. A careful tool waits for hydration for those changes, with the element still hidden, which keeps it hidden longer. If only the variant waits, the original appears earlier than the variant and the test is unfair. See A/B testing on Next.js.
How Duelpilot handles it
- One synchronous script in the head: the runtime and your site's config in one file of about 15 KB gzip, with a fixed size budget in the build, served from its own edge and cached with revalidation. The install guides say never to add async or defer, and the tag carries data-cfasync="false" against Cloudflare Rocket Loader. An asynchronous snippet exists only for tag managers when nobody can edit the template, and it flickers more on slow connections.
- Anti-flicker per element: only the elements a running test changes are hidden (opacity 0, in every arm including the original, so all arms get the same timing), and each one is revealed the moment its change is applied, not when the whole page is done. The page itself is never hidden, except for redirect tests and previews.
- A failsafe: hiding ends after 1,200 ms by default (adjustable from 300 to 3,000 ms), whatever happens.
- Style changes are applied as a stylesheet, and DOM changes are applied as elements appear and re-applied when a framework re-renders them.
- Hydration-safe mode on React/Next.js, Vue/Nuxt, Astro, SvelteKit and Angular: text and structure wait for hydration in every arm alike, so the original and the variant appear at the same moment. Content marked data-dp-early that the framework never hydrates can change at once.
- Measured before launch: site checks open every version on phone, tablet and desktop and sample each frame for original content showing on a tested element. Flicker in view fails the check, flicker below the fold is a warning, and so is a reveal slower than 1.5 seconds; layout shift and JavaScript errors are recorded too. Autopilot never launches a variant whose check failed.
- Tests that change behaviour run in your own code on the Code plan: your own agent builds them behind a Duelpilot flag, which your server can evaluate with Duelpilot's SDK, so no script swaps content in the browser.
Duelpilot's visual tests are client-side. If your team wants every test in code from the start, a feature-flag tool such as GrowthBook or Statsig may suit you better.
Try Duelpilot with your own agent
Give your agent one line: set up Duelpilot for my site using /agents.md. It opens a workspace, installs and verifies the script, and drafts the first test; you approve it, then switch on autopilot if you like. Or see pricing.
€0 until you launch your first test
Questions
Does an anti-flicker snippet hurt page speed?
It can. Hidden content is content the visitor doesn't see yet, so hiding the whole page until a slow script loads delays everything up to the timeout. Hiding only the tested elements, with a short timeout and a small cached script, keeps the cost small.
What is a good anti-flicker timeout?
As short as your script reliably loads on a slow phone connection. Long timeouts hide flicker but turn a slow script into a blank page or blank elements. Duelpilot's default is 1,200 ms, adjustable from 300 to 3,000 ms.
Why does my test still flicker with a synchronous snippet?
Usually something deferred the script (a performance plugin, Rocket Loader, a tag manager), the change was written as custom JavaScript that runs late, or a framework re-rendered the element after the change. Check where and how the script actually loads in the live HTML.
Is server-side testing always better?
It avoids flicker completely, but each test needs a developer and a deploy. Client-side testing suits frequent copy, layout and design tests; server-side suits changes to behaviour and logic.
Sources
Last reviewed 2026-10-29. Spot an error? Tell us.
- Load snippet synchronously and asynchronously | Optimizely (checked 2026-10-29)
- Customize your Wingify SmartCode – Wingify (checked 2026-10-29)