Все материалы
Продуктовая аналитикачеклистсредний

Почему A/B-тесту нельзя доверять: SRM, подглядывание и другие ошибки

Практический чеклист качества A/B-теста: как заметить перекос трафика, подглядывание в результаты, множественные проверки и поломку трекинга.

КейсПрактика27 июля 2026 г.обновлено 12 сентября 2026 г.18 мин

Иногда A/B-тест заканчивается не выводом, а красивым скриншотом: «победили с +8%». Но результат мог появиться из-за перекоса распределения, досрочной остановки, нескольких параллельных метрик или сломанного события. Перед тем как поздравлять команду с победой, проверьте, не нарушились ли базовые условия эксперимента.

Коротко

Доверие к тесту складывается из трёх вещей: группы получили эксперимент случайно, данные собираются одинаково, а правило остановки было задано заранее. Если хотя бы одно из этих условий нарушено, p-value и uplift создают видимость точности, но не спасают дизайн.

  • Проверьте SRM: фактическое распределение пользователей между группами должно соответствовать плану.
  • Не останавливай тест в тот день, когда случайно появился красивый результат.
  • Зафиксируйте primary metric, guardrails и срок до старта эксперимента.
  • После запуска проверьте трекинг и полноту событий до чтения результата.

SRM: группы распределились не так, как планировали

Sample Ratio Mismatch — это ситуация, когда в группах оказалось существенно не то соотношение пользователей, которое задавали в эксперименте. При плане 50/50 ожидаем примерно одинаковое число назначений. Если в control попало 58%, а в test 42%, сначала расследуем рандомизацию, фильтры и доставку варианта, а не обсуждаем uplift.

SRM не доказывает, что результат неправильный, но показывает: механизм эксперимента мог повлиять на то, кто вообще попал в каждую группу. Причина часто находится в SDK, кэше, авторизации, исключении старых пользователей или фильтре уже после назначения варианта.

Проверка занимает меньше минуты и делается до всех остальных расчётов. Порог здесь строже привычного — 0,0005: SRM смотрят у каждого теста, и при 0,05 каждый двадцатый здоровый тест поднимал бы ложную тревогу.

Что проверить при перекосе групп
СимптомКуда смотреть
Перекос только на одном устройстве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 до целевого действия. Он не заменяет анализ, но быстро показывает, где искать поломку.

Минимальный pre-read перед решением по A/B-тесту
ПроверкаЧто должно быть понятно
РаспределениеФактическое соотношение групп и дата/момент назначения
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 после просмотра промежуточных результатов.
  • При досрочной остановке явно назвать ограничение и метод.

Бюджет в 5% делится между взглядами: 0,005 + 0,005 + 0,010 + 0,030

Запрет на досрочную остановку выглядит неудобно: решение обычно нужно раньше, чем закончится запланированный месяц. Выход есть, и он не в том, чтобы смотреть пореже. Пять процентов — это бюджет ошибки на весь эксперимент, и его можно разложить по чтениям заранее.

Допустим, вы собираешься читать результат четыре раза: на четверти выборки, на половине, на трёх четвертях и на полной. Разделите 0,05 между этими моментами — например 0,005; 0,005; 0,010 и 0,030. В сумме ровно 0,05. На каждом чтении p-value сравнивают не с общим порогом, а с границей именно этого чтения, и тогда вероятность объявить победу при отсутствии эффекта возвращается к заявленной. График расхода фиксируют до старта вместе с числом чтений: расходовать можно только то, что расписано заранее.

Раскладка бюджета — это выбор, а не формальность. Схема Покока тратит его почти поровну: остановиться рано легко, но за это финальная граница оказывается строже 0,05, и тест, дотянувший до конца с p = 0,04, победителем уже не считается. Схема О’Брайена — Флеминга оставляет почти весь бюджет на финал: рано остановиться получится только при крупном эффекте, зато последнее чтение почти не отличается от обычного. Для продукта, где ранний выход нужен лишь при сильном результате, вторая удобнее.

Остановка с выводом «эффекта нет» бюджета не расходует вовсе. Ошибка первого рода — это объявленная победа, которой не было; решение закрыть тест раньше срока такой победы не создаёт. Оно увеличивает другой риск — пропустить реальный эффект, — поэтому границу бесполезности удобно задавать по интервалу: если верхняя граница уже ниже порога окупаемости, продолжать нечего.

У досрочной победы есть цена, которую редко называют в отчёте. Тест, остановленный в момент пересечения границы, почти всегда переоценивает эффект: он останавливается на удачном колебании, а не на средней оценке. Поэтому при ранней остановке пишите нижнюю границу интервала и заранее предупреждай команду, что на раскатке прирост окажется скромнее.

Если эксперименты идут на платформе, проверьте, какое p-value она показывает. Часть платформ считает always-valid вариант (mSPRT и родственные методы), где смотреть можно в любой момент — ценой более широких интервалов. Если платформа отдаёт обычное p-value, свободы смотреть нет, как бы часто ни обновлялся дашборд.

Пример графика расхода alpha на четыре чтения
ЧтениеДоля выборкиГраница p-valueЧто значит пересечение
1-е25%0,005выходим только при очень крупном эффекте
2-е50%0,005выход возможен, оценка будет завышена
3-е75%0,010ранний вывод с широким интервалом
4-е100%0,030финальное решение по этой границе, а не по 0,05

Много метрик и сегментов: где появляется случайная находка

Если проверить десять метрик, пять стран, три устройства и несколько окон, красивый результат почти наверняка найдётся даже при отсутствии реального эффекта. Это не делает сегментный анализ бесполезным. Он помогает находить механизм и риски, но его статус должен быть понятен: подтверждающий вывод или exploratory-наблюдение.

Для подтверждающего анализа зафиксируйте небольшой список до запуска. Если после теста обнаружился интересный сегмент, повторите проверку в новом эксперименте или подтверди её на отдельном периоде. Не превращайте случайную находку в обещание для всей аудитории.

Почему большое число проверок повышает риск случайного сигнала

Условная схема: каждая дополнительная проверка создаёт ещё одну возможность увидеть красивый результат.

Риск случайного сигнала, %

Десять независимых проверок превращают 5% в 40%: сначала посчитайте семейство

Арифметика здесь короткая. При m независимых проверках и пороге 0,05 вероятность хотя бы одной ложной находки равна 1 − 0,95^m: пять проверок дают 23%, десять — 40%, двадцать — 64%. Счёт занимает полминуты, и делать его стоит до того, как открываете разрезы, а не после.

У формулы есть оговорка, которая объясняет разницу с графиком выше. Повторные чтения одной метрики сильно связаны между собой: каждый новый день добавляет к выборке немного, поэтому риск растёт медленнее формулы. А вот десять разных метрик или десять стран ближе к независимости — там 1 − 0,95^m работает как рабочий ориентир.

Поправка начинается с вопроса, что входит в семейство. Семейство — это набор проверок, отвечающих на одно решение. Один primary, посчитанный на четырёх платформах, чтобы понять, где раскатывать, — семейство из четырёх. Шесть secondary, которые объясняют механизм и ничего не решают, в семейство не входят: права объявить победу они не дают.

Возьмите десять p-value одного семейства, отсортированных по возрастанию: 0,002; 0,008; 0,012; 0,030; 0,060 и дальше вверх. Бонферрони делит порог на число проверок: 0,05 / 10 = 0,005, проходит только первое значение. Холм идёт по порядку и сравнивает k-е значение с 0,05 / (10 − k + 1); на втором шаге 0,008 уже больше 0,00556, перебор останавливается — снова одна находка. Бенджамини — Хохберг решает другую задачу: он держит долю ложных среди объявленных и сравнивает k-е значение с k · 0,05 / 10. Третье значение 0,012 меньше 0,015, поэтому подтверждаются три.

Поправка не бесплатна: любая из них снижает мощность, то есть повышает шанс не заметить настоящий эффект. Поэтому к guardrail-метрикам семейные поправки обычно не применяют — у защитной метрики безопасная сторона противоположная, пропустить вред дороже, чем лишний раз проверить подозрение. Единственный primary, зафиксированный до запуска, тоже не требует ничего: это семейство из одной проверки.

И последнее разделение, которое снимает путаницу: поправка закрывает количество проверок, но не их повторение во времени — этим занимается бюджет alpha из раздела выше. А самый надёжный ответ на случайную находку остаётся нестатистическим: повторить её на новой выборке или на holdout. Сегмент, выживший в двух независимых экспериментах, убедительнее любого пересчитанного порога. Полный расчёт трёх поправок на пяти каналах DragonKeep — в разборе множественных сравнений.

Итог: Бонферрони и Холм подтверждают одну находку, Бенджамини — Хохберг — три
№p-valueБонферрониХолмБенджамини — Хохберг
10,002≤ 0,005 — проходит≤ 0,0050 — проходит≤ 0,005 — проходит
20,008выше порогавыше 0,0056 — перебор остановлен≤ 0,010 — проходит
30,012выше порогане проверяется≤ 0,015 — проходит
40,030выше порогане проверяетсявыше 0,020
50,060выше порогане проверяетсявыше 0,025
Число проверок записывают, а не вспоминают

Если в отчёте нет списка всех сравнений, поправку считать не из чего: семейство задним числом всегда оказывается меньше того, что реально смотрели в ноутбуке.

Сделайте 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 подход полезнее общего вывода «данные странные», потому что превращает проверку в последовательность действий.

Timeline помогает связать результат с изменениями системы

Условный пример: рост метрики начинается одновременно с изменением SDK, поэтому сначала проверяем доставку события.

Primary, %Missing event, %

Проверка перед публикацией результата

Финальный отчёт должен содержать отдельный раздел «что может быть неправильно». Это не ослабляет вывод, а показывает зрелость анализа. Укажите, какой риск проверен, какой остался и влияет ли он на решение. Если эксперимент нельзя интерпретировать, напишите это прямо: перезапуск с чистым трекингом полезнее спорного rollout.

После исправления сохраните regression check. Он может проверять долю вариантов, уникальность exposure, наличие целевого события и дневной объём. Следующий эксперимент не должен снова обнаруживать ту же проблему вручную.

Итоговый quality gate
Проверка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 и только потом возвращайтесь к продуктовой интерпретации. Так команда не тратит неделю на обсуждение эффекта, которого не было.

Как отличить продуктовый сигнал от tracking-инцидента
НаблюдениеСкорее продуктСкорее данные
Рост primaryвиден в нескольких источникахесть только в одном клиентском событии
Время появленияпостепенно после изменения поведенияточно совпадает с релизом SDK
Сегментлогично связан с гипотезойодна версия ОС или канал доставки
Guardrailизменяется согласованнотехнические ошибки растут одновременно
Продолжить чтение
Вся библиотека