Force a specific A/B test or feature-flag variant for QA
A/B tests and feature flags are great for product teams and miserable for QA. You get bucketed once, randomly, and then you can never see the other variant again. This article shows how to take control: find the value the site uses to bucket you, override it before the page reads it, and pin a variant per URL pattern with a JustZix rule.
How sites bucket you
Almost every client-side experimentation tool — Optimizely, GrowthBook, LaunchDarkly, Statsig, Split, homegrown setups — works the same way. On your first visit it rolls a dice, writes the result somewhere persistent, and reads that same place on every later visit so your experience stays stable. The "somewhere persistent" is almost always one of three things:
- A cookie (e.g.
ab_variant=Bor an anonymous user ID that hashes into a bucket). - A localStorage key (common with GrowthBook and Statsig SDKs).
- A server-side decision baked into the HTML or returned by an API call.
The first two you can override directly. The third is harder — more on that below.
Finding the bucketing key
Open DevTools and go to the Application tab. Under Storage you have Cookies and Local Storage side by side. Reload the page and scan for anything that looks like an experiment: keys containing ab, exp, variant, flag, bucket, test, feature, or a vendor name like optimizely or growthbook.
If nothing obvious shows up, the decision arrives over the network. Open the Network tab, filter to Fetch/XHR, reload, and look for a request to something like /api/flags, /decide, or config.json. The response JSON tells you the variant names and — crucially — which key the SDK stores them under.
Overriding localStorage before scripts read it
Timing is everything. The experimentation SDK reads its key early, often before DOMContentLoaded. Your JustZix JS rule must run before that read. Set the rule to run at document_start and write the value immediately:
// Pin the GrowthBook-style variant before the SDK initialises
const KEY = 'gb_anonymous_id'; // the bucketing key you found
const FORCED = 'qa-pinned-variant-b';
// Overwrite whatever value the SDK would have rolled
localStorage.setItem(KEY, FORCED);
// Some SDKs cache a whole decision object — pin that too
localStorage.setItem('growthbook_features', JSON.stringify({
'new-checkout': { defaultValue: true },
'pricing-table-v2': { defaultValue: 'variant-b' }
}));
Pick a stable, non-random ID for the anonymous ID approach: most SDKs hash that ID into a bucket, so the same string always lands in the same variant. Roll through a few IDs once, note which one gives you variant B, and reuse it forever.
Overriding a cookie
Cookies are simpler — there is no SDK in the way, just a string. Write it at document_start so the page's own scripts see your value:
// Force the experiment cookie for this domain
function setCookie(name, value) {
document.cookie =
name + '=' + value + '; path=/; max-age=31536000; SameSite=Lax';
}
setCookie('ab_variant', 'B');
setCookie('feature_new_nav', 'on');
If the cookie is HttpOnly you cannot touch it from JavaScript at all — that is a server-side flag, covered next. You can confirm this in the Application tab: HttpOnly cookies show a checkmark in that column.
Handling server-side flags
When the variant is decided on the server, the HTML you receive is already the variant. There is no client-side value to flip. You have two honest options:
- Send a hint the server respects. Many setups read a non-HttpOnly override cookie like
x-force-variantor a query parameter?ab_force=Bspecifically so QA can test branches. Ask your team — these overrides usually exist and are just undocumented. - Re-skin the variant you do have. If you cannot get the real variant B markup, you can sometimes approximate the visible difference with a CSS rule for screenshots — but that is a mock, not a real test. Use it only for design review, never for functional QA.
A query-parameter override is the cleanest path. If your site supports ?ff_override=new-checkout:true, you do not even need JavaScript — just bookmark the URL.
Pinning a variant per URL pattern
The real win with JustZix is scoping. You do not want every site bucketed the same way — you want this staging environment pinned to variant B and that one left alone. Create a rule with a tight URL pattern:
URL pattern: https://staging.example.com/*
JS (document_start):
localStorage.setItem('exp_checkout', 'variant-b');
document.cookie = 'ab_force=B; path=/';
Make one rule per variant — "Pin checkout A", "Pin checkout B", "Pin control" — and toggle them from the action bar. A QA pass through all three branches becomes three clicks instead of three incognito windows and a lot of luck.
Verifying the variant actually took
Do not trust that the override worked just because the page looks different. Confirm it. Most SDKs expose the active assignment somewhere — log it from the Output Console:
// Read back what the SDK decided, after it initialised
window.addEventListener('load', () => {
// GrowthBook example
if (window.growthbook) {
console.log('Active features:', window.growthbook.getFeatures());
}
// Generic: dump every storage key for the audit trail
console.log('Forced storage:', { ...localStorage });
});
Pair this with the Output Console window so the assignment is visible in-tab while you click through the flow. If the SDK reports the variant you forced, your test is real. If it reports something else, your rule ran too late — push it to document_start.
Common pitfalls
- Running too late. A rule at
document_idleloses the race. The SDK has already read its key. Always usedocument_startfor bucketing overrides. - Forgetting the server half. You pinned the client variant but the server still renders the control. Look for an override cookie or param.
- Polluting analytics. Forced sessions skew experiment results. Use a staging environment, or ask your data team to exclude QA traffic.
- Stale caches. Some SDKs cache the decision for hours. Clear the relevant storage key first, then set your forced value.
See also
- Mock API responses by intercepting fetch — fake the flag endpoint instead of the storage key.
- Time-based rules — schedule which variant is pinned by day or hour.
- JustZix use cases — more QA and debugging workflows.
Stop relying on incognito windows and lucky dice rolls. Install JustZix, build one rule per variant, and exercise every branch of every experiment on demand.
Rate this post
No ratings yet — be the first.