Почему A/B-тесту нельзя доверять: SRM, подглядывание и другие ошибки
Практический чеклист качества A/B-теста: как заметить перекос трафика, подглядывание в результаты, множественные проверки и поломку трекинга.
Содержание статьи
Иногда A/B-тест заканчивается не выводом, а красивым скриншотом: “победили с +8%”. Но результат мог появиться из-за перекоса распределения, досрочной остановки, нескольких параллельных метрик или сломанного события. Перед тем как поздравлять команду с победой, проверь, не нарушились ли базовые условия эксперимента.
Коротко
Доверие к тесту складывается из трёх вещей: группы получили эксперимент случайно, данные собираются одинаково, а правило остановки было задано заранее. Если хотя бы одно из этих условий нарушено, p-value и uplift создают видимость точности, но не спасают дизайн.
- Проверь SRM: фактическое распределение пользователей между группами должно соответствовать плану.
- Не останавливай тест в тот день, когда случайно появился красивый результат.
- Зафиксируй primary metric, guardrails и срок до старта эксперимента.
- После запуска проверь трекинг и полноту событий до чтения результата.
SRM: группы распределились не так, как планировали
Sample Ratio Mismatch — это ситуация, когда в группах оказалось существенно не то соотношение пользователей, которое задавали в эксперименте. При плане 50/50 ожидаем примерно одинаковое число назначений. Если в control попало 58%, а в test 42%, сначала расследуем рандомизацию, фильтры и доставку варианта, а не обсуждаем uplift.
SRM не доказывает, что результат неправильный, но показывает: механизм эксперимента мог повлиять на то, кто вообще попал в каждую группу. Причина часто находится в SDK, кэше, авторизации, исключении старых пользователей или фильтре уже после назначения варианта.
| Симптом | Куда смотреть |
|---|---|
| Перекос только на одном устройстве | SDK, версия приложения, кэш и повторная инициализация эксперимента |
| Перекос появляется после логина | склейка anonymous_id и user_id, правила исключения и повторное назначение |
| Одна группа теряет пользователей | краш, ошибка загрузки варианта, фильтр доступа или недоставленный feature flag |
| Распределение меняется по дням | сезонность трафика, лимит аудитории и логика ежедневного сэмплирования |
Подглядывание меняет правило игры
Если каждый день смотреть на p-value и останавливать тест при первом значении ниже 0,05, вероятность случайно объявить победителя становится выше заявленных 5%. Это не значит, что нельзя открывать дашборд вообще. Нельзя менять правило решения после того, как увидели промежуточный результат.
Безопасная практика: заранее записать минимальный срок или размер выборки, частоту проверок, primary metric и условие остановки. Если нужен последовательный дизайн, используй его осознанно и с подходящим методом, а не называй обычный тест последовательным задним числом.
Схема иллюстративная: чем чаще команда останавливает обычный тест по промежуточному p-value, тем выше риск ложного сигнала.
Множественные проверки и незапланированные срезы
Тест можно “найти” почти в любом результате, если одновременно проверять десять метрик, пять сегментов и несколько периодов. Один случайный p-value ниже 0,05 среди большого набора проверок не выглядит таким же убедительным, как заранее выбранная основная метрика.
Сегменты нужны для понимания механизма и поиска риска, но не для перебора до первого красивого числа. Отделяй подтверждающий анализ от исследовательского: первый влияет на решение по тесту, второй формирует следующую гипотезу.
- Назови primary metric до запуска и не меняй её на вторую по ходу теста.
- Список guardrail-метрик держи коротким: только реальные риски релиза.
- Сегментные находки помечай как exploratory, если они не были запланированы.
- Для нескольких сравнений используй поправку или отдельный дизайн, а не обычный порог механически.
Проверка событий важнее красивого дашборда
До чтения результата сравни размер аудитории эксперимента с числом пользователей в основной метрике. Если вариант видит 20 тысяч пользователей, а покупка считается только у 11 тысяч из них, нужно понять, это ожидаемый знаменатель или потеря события. Отдельно проверь дубли, задержку загрузки и одинаковую доступность целевого действия в обеих группах.
Полезно иметь диагностический график до primary metric: назначения по дням, доля пользователей с событием, доля неизвестных вариантов, ошибки и время от exposure до целевого действия. Он не заменяет анализ, но быстро показывает, где искать поломку.
| Проверка | Что должно быть понятно |
|---|---|
| Распределение | Фактическое соотношение групп и дата/момент назначения |
| Exposure | Пользователь действительно увидел вариант, а не только был записан в конфигурацию |
| Знаменатель | Одна и та же популяция и правило включения для control и test |
| Событие | Нет систематической потери или дублей целевого события в одной группе |
| Правило решения | Заранее понятно, что делаем при победе, нейтральном результате или guardrail-риске |
Чеклист аналитика
Перед финальным выводом пройди список сверху вниз. Если на каком-то шаге нет ответа, честнее отложить решение и починить эксперимент, чем превращать статистический отчёт в аргумент за уже принятое решение.
- Группы назначаются случайно и сохраняются за пользователем?
- SRM проверен на общей аудитории и ключевых технических срезах?
- Тест прожил заранее заданный срок или достиг плановой выборки?
- Primary metric и guardrails были определены до запуска?
- Данные одинаково полно собираются в обеих группах?
- Сегментные находки отделены от подтверждающего результата?
SRM: не только проверить процент
При плане 50/50 сначала посмотри на фактическое число назначений, но на этом проверка не заканчивается. Разбей распределение по дате, платформе, версии приложения, стране и статусу авторизации. Если общий результат близок к плану, а на iOS test почти не доставляется, среднее по всей аудитории скроет проблему, которая влияет на решение.
Сравни момент назначения, момент exposure и первый целевой шаг. Пользователь мог быть записан в test, но не увидеть интерфейс из-за ошибки загрузки. Для primary metric это уже не та популяция, которую команда думала сравнивать. Не удаляй перекошенный сегмент молча: зафиксируй масштаб, причину и правило, по которому он входит в итоговый анализ.
| Слой | Вопрос |
|---|---|
| Assignment | назначается ли пользователь в вариант по плановой доле? |
| Exposure | действительно ли вариант показан пользователю? |
| Eligibility | не меняется ли фильтр включения после назначения? |
| Persistence | сохраняется ли вариант между сессиями и устройствами? |
| Delivery | нет ли ошибок загрузки, fallback и повторного назначения? |
Подглядывание и последовательный дизайн
Открывать дашборд для контроля данных можно. Проблема начинается, когда команда каждый день сравнивает p-value с 0,05 и останавливает обычный тест в первый удачный момент. При множественных просмотрах случайный всплеск с большей вероятностью будет принят за доказательство, чем при одном заранее заданном чтении.
Если бизнесу нужно принимать решение постепенно, используй последовательный дизайн с заранее заданными границами и способом расчёта. Не называй обычный тест последовательным задним числом. В рабочем документе отдели технический мониторинг от формального условия остановки: первый защищает качество, второй определяет вывод.
Один и тот же массив данных может дать разные решения, если правило остановки меняется после каждого обновления дашборда. Планируй не только выборку, но и способ чтения.
- До запуска записать минимальный срок и плановую выборку.
- Разрешить ежедневный мониторинг SRM, ошибок и потери событий.
- Не менять primary metric после просмотра промежуточных результатов.
- При досрочной остановке явно назвать ограничение и метод.
Много метрик и сегментов: где появляется случайная находка
Если проверить десять метрик, пять стран, три устройства и несколько окон, красивый результат почти наверняка найдётся даже при отсутствии реального эффекта. Это не делает сегментный анализ бесполезным. Он помогает находить механизм и риски, но его статус должен быть понятен: подтверждающий вывод или exploratory-наблюдение.
Для подтверждающего анализа зафиксируй небольшой список до запуска. Если после теста обнаружился интересный сегмент, повтори проверку в новом эксперименте или подтверди её на отдельном периоде. Не превращай случайную находку в обещание для всей аудитории.
Условная схема: каждая дополнительная проверка создаёт ещё одну возможность увидеть красивый результат.
Сделай pre-read частью процесса
Pre-read — это короткий документ перед решением, а не ещё один отчёт ради отчёта. В нём должны быть дизайн, аудитория, период, primary, guardrails, фактическое распределение, состояние трекинга и правило остановки. Если любой блок неизвестен, его нужно обозначить как ограничение.
После теста сохрани не только победителя, но и технический разбор. Что произошло с delivery? Какие события задерживались? Были ли пользователи с несколькими вариантами? Какой срез оказался рискованным? Такой журнал экономит время в следующих экспериментах и превращает отдельную ошибку в улучшение платформы.
| Состояние | Решение |
|---|---|
| Дизайн и данные чистые | читать primary и guardrails по заранее заданному правилу |
| Есть ограничение, но риск локален | исключить или отдельно разобрать сегмент с документированным обоснованием |
| SRM или tracking сломан | не интерпретировать uplift; исправить и перезапустить |
| Есть неожиданный exploratory-сигнал | сформировать новую гипотезу и подтвердить отдельно |
Назначение, exposure и анализ: три разные популяции
Одна из частых причин путаницы — считать всех пользователей эксперимента одной аудиторией. Assignment означает, что система выбрала вариант. Exposure означает, что пользователь действительно увидел изменение. Analysis population может дополнительно иметь условие целевого действия или период наблюдения. Эти множества могут не совпадать, и расхождение нужно объяснить.
Если отбрасывать пользователей без exposure после просмотра результата, можно нарушить преимущество рандомизации. Для основного intent-to-treat-анализа обычно сохраняют всех корректно назначенных пользователей, а exposure и технические исключения используют для диагностики. Другой подход возможен, но его нужно планировать до запуска и описывать явно.
| Слой | Пример | Риск ошибки |
|---|---|---|
| Assignment | пользователь получил flag B | флаг не сохранился между сессиями |
| Exposure | вариант B отрисовался на экране | ошибка загрузки скрыла изменение |
| Eligibility | пользователь подходит под окно анализа | фильтр появился после назначения |
| Outcome | событие покупки произошло | сравнили только дошедших до checkout |
Поломка трекинга может выглядеть как эффект
Если событие покупки отправляется только после нового компонента, test может показать рост не потому, что пользователи стали покупать чаще, а потому, что событие стало записываться полнее. Обратная ситуация выглядит как проигрыш: интерфейс работает, но одна ветка не отправляет финальное событие. Поэтому перед primary смотри на технический funnel и долю пользователей, для которых доступен каждый шаг.
Сравни не только количество событий, но и отношение к устойчивому якорю: exposure, сессии, заказы из платёжной системы или серверные записи. Если клиентский и серверный источник расходятся только в одной группе, блокируй интерпретацию и разбирай доставку.
- Доля неизвестных вариантов и повторных exposure.
- Задержка между назначением и показом интерфейса.
- Доля пользователей с missing event в каждой группе.
- Сверка клиентских событий с серверным источником.
- Изменения схемы и версии SDK в период теста.
Как расследовать странный результат
Если uplift появился внезапно, не начинай с объяснения про поведение пользователей. Сначала построи timeline: запуск флага, релизы, ошибки, изменение источника, рост трафика и момент появления сигнала. Потом разбей результат по платформам, версиям, странам, новым и возвращающимся пользователям. Временная и техническая локализация часто быстрее находит причину, чем новый статистический тест.
Проверь три версии: эффект реальный, эффект вызван поломкой измерения, результат случайный. Для каждой запиши наблюдение, которое подтверждает или опровергает версию. Такой incident-style подход полезнее общего вывода “данные странные”, потому что превращает проверку в последовательность действий.
Условный пример: рост метрики начинается одновременно с изменением SDK, поэтому сначала проверяем доставку события.
Проверка перед публикацией результата
Финальный отчёт должен содержать отдельный раздел “что может быть неправильно”. Это не ослабляет вывод, а показывает зрелость анализа. Укажи, какой риск проверен, какой остался и влияет ли он на решение. Если эксперимент нельзя интерпретировать, напиши это прямо: перезапуск с чистым трекингом полезнее спорного rollout.
После исправления сохрани regression check. Он может проверять долю вариантов, уникальность exposure, наличие целевого события и дневной объём. Следующий эксперимент не должен снова обнаруживать ту же проблему вручную.
| Проверка | Pass condition |
|---|---|
| Распределение | соотношение соответствует плану, SRM объяснён |
| Стабильность | вариант сохраняется и нет cross-over |
| Доставка | exposure и технический funnel сопоставимы |
| Метрики | primary, guardrails и знаменатели заданы заранее |
| Решение | есть действие для победы, нейтрального исхода и риска |
Перед любым выводом проверь источник истины
Для коммерческих метрик заранее выбери источник истины: клиентские события, серверные записи, платёжный реестр или нормализованную витрину. Разные источники могут быть полезны для диагностики, но финальное решение должно опираться на понятный контракт. Иначе один и тот же эксперимент можно “выиграть” или “проиграть” выбором таблицы.
При расхождении сохрани обе цифры и причину расхождения в pre-read.
Это позволит отличить баг данных от реального изменения поведения и не потерять контекст через неделю.
Источник истины указывается рядом с primary и проверяется до rollout.
Если источник меняется во время эксперимента, останови интерпретацию и добавь это в ограничения.
Это короткое правило защищает отчёт от подмены источника после получения результата.
Если строка не означает то, что написано в названии метрики, точный расчёт не делает вывод надёжнее.
Мини-кейс: красивый uplift оказался поломкой delivery
Представим тест нового экрана оплаты. На третий день dashboard показывает +9% к paid order rate, p-value ниже порога, и команда готовит rollout. Аналитик замечает, что рост начался сразу после обновления SDK и почти полностью сосредоточен на Android 14. В test при этом стало на 7% меньше событий checkout_started, а серверный реестр заказов роста не подтверждает.
Разбор показывает: новый экран отправляет purchase при возврате из платёжного приложения, хотя заказ ещё не подтверждён. Primary выросла в клиентской аналитике, но бизнес-результат не изменился. Ошибка не в формуле p-value, а в том, что событие перестало означать то же самое. Такой тест нельзя “починить” фильтром после просмотра: нужно исправить событие, пересобрать baseline и перезапустить эксперимент.
Этот сценарий полезен как стандарт расследования. Сначала сравни клиентский и серверный источники, затем построи технический funnel, локализуй платформу и дату, проверь версии SDK и только потом возвращайся к продуктовой интерпретации. Так команда не тратит неделю на обсуждение эффекта, которого не было.
| Наблюдение | Скорее продукт | Скорее данные |
|---|---|---|
| Рост primary | виден в нескольких источниках | есть только в одном клиентском событии |
| Время появления | постепенно после изменения поведения | точно совпадает с релизом SDK |
| Сегмент | логично связан с гипотезой | одна версия ОС или канал доставки |
| Guardrail | изменяется согласованно | технические ошибки растут одновременно |
Материалы по теме

Статистическая значимость в A/B-тесте: p-value и доверительный интервал
Объясняем статистическую значимость без магии: как читать p-value, доверительный интервал и разницу между “значимо” и “полезно для бизнеса”.

MDE и размер выборки: как понять, хватит ли данных для A/B-теста
Что такое MDE, как он связан с размером выборки и длительностью эксперимента, почему маленький тест не может доказать большой продуктовый вывод.

Основная метрика и guardrail в A/B-тесте: что считать успехом
Как выбрать primary metric, вторичные показатели и guardrail-метрики для эксперимента, чтобы не объявить победу ценой ухудшения продукта.