Принудительно выбери нужный вариант A/B-теста или feature-флага для QA
A/B-тесты и feature-флаги — отличная штука для продуктовых команд и сущая мука для QA. Тебя один раз случайно распределяют в корзину — и больше ты другой вариант уже не увидишь. Эта статья показывает, как взять контроль в свои руки: найти значение, по которому сайт тебя распределяет, переопределить его до того, как страница его прочитает, и закрепить вариант для конкретного URL-паттерна правилом JustZix.
Как сайты распределяют тебя по корзинам
Почти все клиентские инструменты экспериментов — Optimizely, GrowthBook, LaunchDarkly, Statsig, Split, самописные решения — работают одинаково. При первом визите бросается кубик, результат записывается куда-то в постоянное хранилище, и при каждом следующем визите читается то же место, чтобы твой опыт оставался стабильным. Это «постоянное хранилище» почти всегда — одна из трёх вещей:
- Cookie (например,
ab_variant=Bили анонимный идентификатор пользователя, который хэшируется в корзину). - Ключ localStorage (типично для SDK GrowthBook и Statsig).
- Серверное решение, вшитое в HTML или возвращаемое API-запросом.
Первые два можно переопределить напрямую. Третий сложнее — об этом ниже.
Поиск ключа распределения
Открой DevTools и перейди на вкладку Application. В разделе Storage рядом лежат Cookies и Local Storage. Перезагрузи страницу и поищи всё, что похоже на эксперимент: ключи со словами ab, exp, variant, flag, bucket, test, feature или с именем вендора вроде optimizely или growthbook.
Если ничего очевидного не видно, решение приходит по сети. Открой вкладку Network, отфильтруй по Fetch/XHR, перезагрузи и поищи запрос вроде /api/flags, /decide или config.json. JSON-ответ подскажет тебе имена вариантов и — что важнее всего — под каким ключом SDK их хранит.
Переопределение localStorage до того, как скрипты его прочитают
Тайминг решает всё. SDK экспериментов читает свой ключ рано, часто ещё до DOMContentLoaded. Твоё JS-правило JustZix должно сработать раньше этого чтения. Поставь правилу выполнение на document_start и запиши значение сразу:
// Закрепляем вариант в стиле GrowthBook до инициализации SDK
const KEY = 'gb_anonymous_id'; // ключ распределения, который ты нашёл
const FORCED = 'qa-pinned-variant-b';
// Перезаписываем значение, которое SDK бы выбрал
localStorage.setItem(KEY, FORCED);
// Некоторые SDK кэшируют весь объект решения — закрепи и его
localStorage.setItem('growthbook_features', JSON.stringify({
'new-checkout': { defaultValue: true },
'pricing-table-v2': { defaultValue: 'variant-b' }
}));
Для подхода с анонимным идентификатором выбери стабильный, неслучайный ID: большинство SDK хэшируют этот ID в корзину, поэтому одна и та же строка всегда попадает в один и тот же вариант. Перебери несколько ID один раз, заметь, какой даёт вариант B, и используй его всегда.
Переопределение cookie
Cookie проще — никакого SDK на пути, просто строка. Запиши её на document_start, чтобы скрипты самой страницы увидели твоё значение:
// Принудительно ставим cookie эксперимента для этого домена
function setCookie(name, value) {
document.cookie =
name + '=' + value + '; path=/; max-age=31536000; SameSite=Lax';
}
setCookie('ab_variant', 'B');
setCookie('feature_new_nav', 'on');
Если cookie помечена как HttpOnly, ты вообще не можешь её тронуть из JavaScript — это серверный флаг, о нём дальше. Это можно проверить на вкладке Application: HttpOnly-cookie имеют галочку в соответствующем столбце.
Работа с серверными флагами
Когда вариант решается на сервере, полученный тобой HTML уже и есть вариант. Никакого клиентского значения, которое можно переключить, нет. У тебя есть два честных варианта:
- Отправь подсказку, которую сервер уважает. Многие решения читают override-cookie не из категории HttpOnly вроде
x-force-variantили query-параметр?ab_force=Bспециально для того, чтобы QA могла тестировать ветки. Спроси свою команду — такие переопределения обычно существуют, просто не задокументированы. - Перерисуй тот вариант, что у тебя есть. Если получить настоящую разметку варианта B нельзя, иногда можно приблизить видимую разницу CSS-правилом для скриншотов — но это макет, а не настоящий тест. Используй это только для дизайн-ревью, никогда для функционального QA.
Переопределение через query-параметр — самый чистый путь. Если твой сайт поддерживает ?ff_override=new-checkout:true, тебе даже JavaScript не нужен — просто добавь URL в закладки.
Закрепление варианта для URL-паттерна
Настоящий выигрыш JustZix — в области действия. Тебе не нужно, чтобы все сайты были распределены одинаково — тебе нужно, чтобы именно это staging-окружение было закреплено на варианте B, а то осталось нетронутым. Создай правило с узким URL-паттерном:
URL-паттерн: https://staging.example.com/*
JS (document_start):
localStorage.setItem('exp_checkout', 'variant-b');
document.cookie = 'ab_force=B; path=/';
Сделай по одному правилу на вариант — «Закрепить checkout A», «Закрепить checkout B», «Закрепить контроль» — и переключай их из панели действий. Проход QA по всем трём веткам становится тремя кликами вместо трёх инкогнито-окон и кучи везения.
Проверка, что вариант действительно применился
Не верь, что переопределение сработало, только потому что страница выглядит иначе. Подтверди это. Большинство SDK где-то отдают активное назначение — выведи его в Output Console:
// Считываем обратно, что решил SDK, после его инициализации
window.addEventListener('load', () => {
// Пример с GrowthBook
if (window.growthbook) {
console.log('Active features:', window.growthbook.getFeatures());
}
// Универсально: дампим все ключи хранилища для аудита
console.log('Forced storage:', { ...localStorage });
});
Соедини это с окном Output Console, чтобы назначение было видно прямо в карте, пока ты прокликиваешь сценарий. Если SDK сообщает тот вариант, который ты задал, твой тест настоящий. Если он сообщает что-то другое, твоё правило сработало слишком поздно — переведи его на document_start.
Частые ошибки
- Слишком позднее выполнение. Правило на
document_idleпроигрывает гонку. SDK уже прочитал свой ключ. Для переопределений распределения всегда используйdocument_start. - Забыта серверная половина. Ты закрепил клиентский вариант, а сервер по-прежнему рендерит контроль. Поищи override-cookie или параметр.
- Загрязнение аналитики. Принудительные сессии искажают результаты экспериментов. Используй staging-окружение или попроси команду данных исключить QA-трафик.
- Устаревший кэш. Некоторые SDK кэшируют решение на часы. Сначала очисти нужный ключ хранилища, потом задай своё принудительное значение.
Смотри также
- Подменяй ответы API, перехватывая fetch — подделай эндпоинт флага вместо ключа хранилища.
- Правила по времени — планируй, какой вариант закреплён по дню или часу.
- Сценарии применения JustZix — больше воркфлоу для QA и отладки.
Перестань полагаться на инкогнито-окна и удачные броски кубика. Установи JustZix, построй по одному правилу на вариант и прогоняй каждую ветку каждого эксперимента по запросу.
Оцени эту статью
Оценок пока нет — оцени первым.