Практика

Для каждой задачи определите: какое условие каузальности нарушено, почему это проблема, и что нужно сделать.

Задача 1. Рандомизация по времени регистрации

Команда запускает новый онбординг. Все пользователи, зарегистрированные до 1 марта — контроль (старый онбординг). Все зарегистрированные после 1 марта — тест (новый онбординг). Через месяц сравнивают retention.

Ответ

Нарушено: рандомизация. Это не A/B-тест, а before/after сравнение. Группы различаются по времени регистрации — любой внешний фактор (маркетинговая кампания, сезонность, изменение трафика) confounds результат.

Что делать: рандомизировать по user_id — каждый новый пользователь с равной вероятностью получает старый или новый онбординг, независимо от даты.

Задача 2. Маркетплейс: новый алгоритм ранжирования

E-commerce маркетплейс тестирует новый алгоритм ранжирования товаров. Рандомизация по покупателям: 50% видят новый алгоритм, 50% — старый. Метрика — GMV per buyer. Через 2 недели тест показывает +8% GMV.

Но: новый алгоритм показывает товары определённых продавцов чаще. Эти продавцы получают больше продаж, а продавцы, чьи товары ушли ниже — меньше.

Ответ

Нарушено: SUTVA (отсутствие интерференции). Treatment для одних покупателей влияет на товарное предложение для других. Продавцы — общий ресурс: если один покупатель видит товар выше, другой может не увидеть его вовсе.

Следствие: +8% GMV в тесте частично достигнуто за счёт контроля. Реальный ATE при 100% rollout будет значительно ниже — возможно, близок к нулю (zero-sum redistribution).

Что делать: (1) Рандомизация по кластерам (города, регионы). (2) Мониторить метрики продавцов. (3) При rollout сравнить фактический GMV с прогнозом из A/B.

Задача 3. CTR нового рекламного формата

Команда тестирует новый формат рекламного баннера. Рандомизация по пользователям. Метрика: CTR = клики / показы (глобальное отношение). Результат: CTR вырос на +12%.

Но: новый формат занимает больше экранного пространства, из-за чего алгоритм показывает меньше баннеров на пользователя (было 8, стало 5).

Ответ

Проблема: treatment-affected exposure. Treatment изменил знаменатель метрики (число показов). CTR вырос не потому, что баннер лучше, а потому, что число показов сократилось.

Что делать: (1) Сравнить абсолютное число кликов per user (не ratio). (2) Сравнить число показов между группами. (3) Если показы различаются — CTR невалиден как primary metric.

Задача 4. ARPPU и новый онбординг

Эксперимент: новый онбординг увеличивает конверсию в первую покупку. Метрика для оценки эффекта — ARPPU (средняя выручка на покупателя, только среди пользователей, совершивших покупку).

Результат: ARPPU в тест-группе на 15% ниже, чем в контроле. Вывод аналитика: «новый онбординг ухудшает выручку с покупателя».

Ответ

Нарушено: post-treatment conditioning. ARPPU считается только среди покупателей — это подмножество, определённое post-treatment поведением. Treatment увеличил конверсию → в тесте больше «новых» покупателей с мелкими чеками → средний чек падает.

Следствие: ARPPU ↓ не означает, что treatment плох. Total revenue мог вырасти.

Что делать: использовать ITT-метрику (revenue per user, включая нули) как primary. ARPPU — вспомогательная метрика для диагностики.

Задача 5. Гео-эксперимент с ценами

Компания тестирует повышение цен в приложении доставки еды. Рандомизация по городам: 10 городов — тест, 10 — контроль. Метрика: средний чек.

Аналитик проводит t-test на уровне пользователей (500K в тесте, 480K в контроле). Получает p = 0.0003. Вывод: «повышение цен значимо увеличило средний чек».

Ответ

Проблема: неправильная единица анализа. Рандомизация — по городам (кластерам), а анализ — по пользователям. Эффективный N ≈ 20 (число городов), а не 980K.

Следствие: t-test с N = 980K драматически занижает p-value. Реальная значимость: p ≈ 0.15–0.35.

Что делать: cluster-robust SE с кластером = город. Или randomization inference (permutation по 20 городам).

Задача 6. Утечка через shared device

Эксперимент: новый UI checkout-страницы. Рандомизация по user_id. Семейный аккаунт: несколько членов семьи используют один аккаунт.

Часть пользователей контрольной группы обсуждают «странную новую страницу оплаты» в семейном чате (screenshot от пользователя из теста).

Ответ

Нарушено: (1) Консистентность — если shared device, то один user_id может означать разных людей. (2) SUTVA — информация о treatment «протекает» в контроль через социальные связи.

Следствие: контроль загрязнён. ATE занижен (diluted).

Что делать: (1) Рандомизация по устройству или cookie. (2) Анализировать кластеры пользователей с общими device_id. (3) При значительном leakage — кластерная рандомизация по household.

Задача 7. Социальная сеть: новая фича шеринга

Социальная сеть тестирует кнопку «Поделиться» в новом формате. Рандомизация по пользователям. Метрика: число shares per user. Тест-группа: +25% shares.

Но: когда пользователь тест-группы делится контентом, его друзья (возможно из контроля) видят этот контент и тоже начинают делиться чаще.

Ответ

Нарушено: SUTVA. Социальный граф создаёт интерференцию: treatment одного пользователя влияет на поведение его друзей.

Следствие: +25% — переоценка каузального эффекта. Часть роста вызвана spillover.

Что делать: (1) Graph cluster randomization — рандомизировать связанные компоненты. (2) Замерить степень загрязнения контроля: среди пользователей контроля с >50% друзей в тесте shares выше?

Задача 8. Эксперимент с багом в delivery

Тест: новый алгоритм распределения заказов по курьерам. Рандомизация по заказам. Метрика: время доставки. Из-за бага 20% заказов в тест-группе обрабатывались старым алгоритмом.

Результат: среднее время доставки в тесте на 3% лучше, чем в контроле.

Ответ

Нарушено: консистентность. 20% тестовой группы фактически получили контрольный treatment. Наблюдаемый Y для них — Y(0), а не Y(1).

Следствие: attenuation bias — реальный эффект больше 3%. ITT = 3%, LATE = 3% / 0.8 = 3.75%.

Что делать: (1) Исправить баг и перезапустить. (2) Оценить LATE через IV. (3) Раскрыть процент non-compliance в отчёте.

Задача 9. Рандомизация по сессиям

Эксперимент: новый дизайн страницы каталога. Рандомизация по сессиям: каждая сессия случайно попадает в тест или контроль. Один пользователь в разных сессиях может видеть разные версии.

Метрика: конверсия (покупка / пользователь).

Ответ

Проблема: единица рандомизации (сессия) ≠ единица анализа (пользователь). Один пользователь может быть и в тесте, и в контроле — нарушение assignment consistency.

Следствие: (1) Attenuation bias. (2) Непоследовательный пользовательский опыт (novelty/confusion effect). (3) Нельзя атрибутировать покупку конкретной версии.

Что делать: рандомизировать по user_id (sticky assignment). Если нужна session-level рандомизация — метрика тоже session-level.

Задача 10. AB-тест ценового плана (B2B)

B2B SaaS: тестируют новый ценовой план. Рандомизация по компаниям (100 + 100). Метрика: revenue per company. Результат: +22% revenue в тесте.

Но: 3 крупных enterprise-клиента, попавших в тест, сгенерировали 60% revenue тестовой группы.

Ответ

Проблема: (1) Малая выборка (200 компаний). (2) Экстремальный heavy tail — 3 компании определяют результат. (3) Баланс по размеру случаен и ненадёжен.

Следствие: +22% может быть целиком объяснён тем, что крупные компании случайно попали в тест. Повторная рандомизация может дать −15%.

Что делать: (1) Block randomization по размеру. (2) Winsorization / trimmed mean. (3) Permutation test. (4) Проверить результат без 3 крупнейших компаний.

Задача 11. Conditioning on a collider

Эксперимент: новая модель рекомендаций. Рандомизация по пользователям. Аналитик анализирует конверсию только среди пользователей, просмотревших ≥5 товаров (аргумент: «неактивные зашумляют результат»).

Treatment влияет на то, сколько товаров пользователь просматривает (рекомендации стали релевантнее → больше просмотров).

Ответ

Нарушено: post-treatment conditioning. «Просмотр ≥5 товаров» — post-treatment переменная, зависящая от treatment. Фильтрация создаёт разный состав подвыборок.

Следствие: в тесте подвыборка включает «новых активных» пользователей, в контроле — только изначально активных. Сравнение смещено.

Что делать: (1) ITT — анализировать всех. (2) Сегментировать по pre-treatment активности. (3) Просмотры → secondary metric, не фильтр.

Задача 12. Два эксперимента одновременно

Две команды одновременно запускают эксперименты на одних и тех же пользователях. Команда A тестирует новый checkout. Команда B — новую цену. Рандомизация независимая.

Команда A видит +5% CR. Но в подгруппе, где одновременно активен тест B — CR +12%. Без теста B — CR +1%.

Ответ

Проблема: interaction effect. Два treatment взаимодействуют: новый checkout хорошо работает с новой ценой, но плохо — со старой. Средний эффект (+5%) маскирует гетерогенность.

Следствие: если запустить только checkout без новой цены — реальный эффект +1%, а не +5%.

Что делать: (1) Factorial design (2×2) — анализировать interaction term. (2) Принимать решение с учётом второго эксперимента. (3) При сильном interaction — запускать последовательно.

Задача 13. Survivor bias в retention

Эксперимент: новая фича повышает retention. Аналитик измеряет Day 30 retention. Но: в тест-группе 5% пользователей деинсталлировали приложение на Day 3 (из-за багов в новой фиче). Эти пользователи не учитываются в Day 30 retention.

Результат: Day 30 retention в тесте = 42%, в контроле = 38%. Вывод: «фича улучшает retention».

Ответ

Нарушено: survivor bias (форма post-treatment conditioning). Пользователи, ушедшие из-за бага, исключены из анализа. Оставшиеся — «выжившие», изначально более лояльные.

Следствие: 42% — retention среди выживших. С учётом ушедших: 42% × 0.95 = 39.9% — практически как в контроле.

Что делать: (1) ITT: считать retention по всем, включая деинсталлировавших (retention = 0). (2) Мониторить uninstall rate как guardrail. (3) Если uninstall rate выше — red flag.