Anti-Flicker

Flicker (also called FOOC, the flash of original content) is when a visitor briefly sees the original page before the variation is applied. A vs B prevents it, and this is the one page that explains how. Everything below matches what the code actually does.

What flicker is

Without protection, this is the sequence that causes a flash:

  1. The visitor requests your page.
  2. The browser paints the HTML and CSS, so the visitor sees the original page.
  3. The A vs B bundle finishes downloading and reads your project's config.
  4. The variation's changes are applied.
  5. The page visually changes in front of the visitor.

Steps 2 and 5 are the flash. It looks broken, and it pollutes your data, because visitors in the variant group briefly saw the control.

How A vs B prevents it

The hide lives in the first tag you paste, not in the downloaded bundle. That is the whole trick. The loader tag is async, so the bundle (and then your project config) arrive after the browser has already painted. Anything that started hiding at that point would be too late by definition.

The last line of the first tag notes the time, starts downloading your experiment settings right away, and then hides:

JavaScript
(function(){window.avsb._t0=Date.now();window.avsb._df=fetch('https://cdn.avsb.cloud/YOUR_SNIPPET_KEY/datafile.json').catch(function(){});var d=document,e=d.documentElement,s=d.currentScript,a=s&&s.getAttribute('data-avsb-timeout'),t=a==null?3000:+a;if(!(t>0)||window.avsb.version)return;e.style.opacity='0';e.style.pointerEvents='none';window.avsb._t=setTimeout(function(){e.style.removeProperty('opacity');e.style.removeProperty('pointer-events')},t)})();
JavaScript1 line

In plain terms:

  1. It records when the tag ran and starts fetching your experiment settings immediately, in parallel with the bundle, so experiments are ready to show sooner and the page spends less time hidden.
  2. It sets opacity: 0 on the <html> element and blocks clicks on it, while the browser is still reading your <head>, before the first paint. The visitor sees your page background, never the original content, and can't click anything on it until it's revealed.
  3. It starts a 3 second timer that reveals the page on its own.
  4. When the bundle arrives, evaluates your experiments and applies the winning variation, A vs B removes both that inline opacity and the click-block again. Removing them rather than setting values back means a site that styles its own html { opacity } or html { pointer-events } keeps its value.

So the visitor's first paint is already the correct variation, with an async loader that never blocks your page.

Both tags, first tag first

The hide is in the first tag. If you paste only the loader tag, experiments still run, but nothing hides the page and above-the-fold changes will flash. Paste both tags, in order, as early in the <head> as you can. See Quick Install.

The safety timeout

The timer in the tag is what guarantees your visitors always see your site. If the bundle never arrives at all, because the CDN is blocked, an ad blocker got in the way, or the visitor dropped offline, the page reveals itself anyway.

The default is 3 seconds. Change it with a data-avsb-timeout attribute on the first tag:

HTML
<script data-avsb-timeout="1000">window.avsb=window.avsb||{};/* ... rest of the stub, unchanged ... */</script>
HTML4 lines
  • data-avsb-timeout is the hide budget: how long the page may stay hidden before it reveals itself.
  • A shorter value (say 1000) reveals the page sooner on bad connections, at the cost of a possible flash for the visitors who hit the timeout.
  • data-avsb-timeout="0" turns the hide off completely, which is the honest way to opt out: the line stays, and it does nothing.

Fetching your experiment config runs against the same clock. The request is given whatever is left of your timeout, minus a small reserve kept back for applying the variation, so on a normal load the changes land and the page is revealed before the timer ever fires. A low timeout therefore also shortens how long the config may take: visitors whose connection cannot deliver it in time simply see your original page. With the hide turned off there is no clock to race: the config request keeps its full deadline and changes are applied whenever they are ready.

Your project JavaScript cannot delay the reveal either: if it is slow to run, the page is shown first and your code runs on the visible page.

Info

The timeout is a safety net, not a performance target. When the bundle and config are served warm from the CDN, the page is usually revealed in well under 100 milliseconds and no visitor notices the hide at all.

When it matters

Most when an experiment changes something above the fold, the part visible without scrolling:

  • A hero headline or image
  • Navigation bar elements
  • Call-to-action buttons near the top
  • The page background colour

Less for changes below the fold, since the variation is almost always applied before a visitor scrolls that far. Not at all for experiments that change behaviour rather than appearance, such as redirecting to a different page or changing what a form submit does.

The project setting

Project Settings → Configuration → Advanced settings has an Anti-flicker protection toggle. It controls what the bundle does with the hide it inherits from your tag:

  • On (default): keep the page hidden until experiments have been evaluated and variations applied, then reveal.
  • Off: reveal as soon as the config has been read, without waiting for variations. Visitors may see a brief flash of the original.
  1. The Anti-flicker protection toggle, on by default.

The toggle cannot remove the hide in your tag, because that tag lives in your HTML, not in our config. To have no hiding at all, set data-avsb-timeout="0" or delete the hide line from the first tag.

Single-page apps and other paths

  • Client-side navigation inside a single-page app is not hidden. The page is already visible and the variation is re-applied in place. The one exception is a split URL experiment whose control URL matches the new route: the page is re-hidden briefly so the visitor does not watch the control render before the redirect.
  • Consent Mode reveals the page immediately and never hides it again. A visitor has to be able to read your page and your cookie banner while they decide, and hiding the page at the moment they accept would be a full-page blink at the worst possible time. See Consent Mode.
  • Visitors who deny analytics get the original page revealed straight away, with nothing applied and nothing measured.

How to test it

Open DevTools, go to the Network tab, set throttling to Slow 3G, and reload. You should see your page background (blank) for a moment, then the page appear fully formed with the right variation. You should never see the original content appear and then change.

If the page appears with the original content first, work through Flicker in troubleshooting: nine times out of ten the first tag is missing, or the tags are lower in the page than they look.

Earlier is better

The earlier the two tags sit in the <head>, the less of your page can paint before the hide takes effect, and the more time the bundle has to arrive before the timeout. Put them first, ahead of other scripts and stylesheets.

Was this helpful?