Как устроен GrowthBook

Как устроен GrowthBook


В последние месяцы на рынке вендорских A/B-платформ произошло несколько крупных событий – Statsig поднял 100 млн инвестиций, Datadog поглотил Eppo, а Авито – Sigma от EXPF. В свете этого предлагаю разобраться в том, как устроены эти самые вендорские платформы на примере еще одного популярного в СНГ игрока – GrowthBook.  

Так выглядит админка:

На левой панели есть три основных раздела: Features, Experimentation и Metrics. Рассмотрим подробнее каждый из них.

Features

Это раздел, в котором можно создавать и настраивать фиче флаги. С точки зрения админки, фиче флаг – это набор правил, определяющих то, в какую группу эксперимента попадет пользователь.

Давайте на примере. Я создаю в админке фиче флаг ab-testicles. GrowthBook попросит меня ввести дефолтное значение – в нашем случае это "EXPF". Всё, фиче флаг готов.

Сейчас это просто сущность в админке, которая вообще ничего не делает. Внизу справа есть кнопка Add Rule – она позволяет добавлять правила, которые будут определять логику работы фиче флага. Правила бывают разных типов. Самый базовый тип – это Experiment. Подробнее о настройках экспериментов я расскажу ниже. Пока что просто создадим обычный эксперимент внутри нашего фиче флага.

Теперь у нас настроена логика сплитования пользователей. Но, опять же, пока что это просто сущность в админке. Чтобы пользователи действительно начали сплитоваться, нужно добавить этот фиче флаг в код. Как это выглядит в проде – я не представляю. Но вот простой пример использования SDK Growthbook в питоне для получения значения фиче флага для конкретного пользователя:

В нашем случае фиче флаг будет возвращать feature_value = "Avito" или "EXPF" – в зависимости от того, в какой вариант эксперимента попадет пользователь.

Как это работает на практике:

1) Разработчики добавляют в код (на клиенте или на бэке) вызов SDK GrowthBook, который возвращает значение фиче-флага для конкретного пользователя. Сами правила для всех фиче флагов подтягиваются через API в момент открытия приложения.

В какой момент вызывается SDK – зависит от того, как это настроят разработчики. Допустим, у нас изменение на странице карточки товара. Соответственно, вызов SDK будет происходить в момент открытия пользователем этой страницы.

2) Пользователь открывает карточку товара. На основе его account_id SDK возвращает значение фиче флага – "EXPF" или "Avito".

3) Если фиче флаг вернул значение "EXPF", то пользователь увидит только раздел с описанием товара – контрольный вариант. А если "Avito", то раздел с описанием и раздел с характеристиками – тестовый вариант.

4) Также в этот момент идет запись в таблицу с участниками эксперимента со всей нужной для дальнейших расчетов информацией – account_id, experiment_id, timestamp, variant_id.

Feature flag vs Experiment

Обратите внимание: мы разводим понятия фиче флага и эксперимента. Это умный ход, который делает Growthbook очень гибким инструментом для управления изменениями в продукте.

Мы можем добавить в фиче флаг не только правило-эксперимент, но и другие типы правил. Один из них – Force Rule: это правило, которое определенной группе пользователей (например, тестировщикам) присвоит конкретное значение фиче флага.

В примере выше пользователь iOS с account_id = 36, стриггерив фиче флаг, получит значение "Avito", так как он подходит под условия Force Rule. Если пользователь получает значение фиче флага от какого-то правила, то к следующему правилу он не переходит. То есть account_id = 36 уже не будет сплитоваться в эксперименте. Порядок правил можно менять дрэг энд дропами.

Force Rule можно использовать не только для раскатки нужного варианта на тестировщиков приложения. Мы можем, например, присвоить контрольное значение всем пользователям Android, у которых версия приложения ниже X, если не хотим, чтобы они попадали в эксперимент.

Фиче флаг может существовать и без эксперимента. Если мы добавим в код фиче флаг, у которого в админке нет ни одного правила, то пользователям будет присваиваться дефолтное значение фиче флага, заданное при его создании. Это значение также будут получать те пользователи, которые не попали под условия ни одного из правил.

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

Еще одна удобная функция – это Temporary rollout. Когда вы завершаете эксперимент, вы можете не просто остановить его, деактивировав таким образом правило эксперимента, а раскатить нужный вариант на всех пользователей, которые дойдут до этого правила. Это полезно, когда нужно время на подумать, прежде чем принимать решение и выпиливать фиче флаг из кода, оставляя там только победивший вариант.

Эксперименты и слои

Сама настройка эксперимента в Growthbook тоже довольно гибкая. Как и в Force Rule, можно задать условия попадания в эксперимент на основе атрибутов пользователя – id, platform, app_version и т.д. Это позволяет, среди прочего, проводить два эксперимента на одном фиче флаге одновременно, если условия попадания в них не пересекаются. Например, один – для пользователей iOS, второй – для Android. Или один – для авторизованных пользователей, другой – для неавторизованных. Также можно проверять не только атрибуты пользователя, но и значение, которое вернет другой фиче флаг для этого пользователя. Это позволяет, в частности, очень легко реализовать холдаут.

Есть возможность регулировать процент пользователей, которые попадут в эксперимент – сделать это можно двумя способами. Первый – через слои (в Growthbook они называются Namespaces). Вы можете раскатить эксперимент на 30% пользователей внутри слоя. В таком случае на оставшихся 70% можно будет провести другой эксперимент без пересечения с вашим. С точки зрения работы сплитовалки это выглядит примерно так:

1) hash(namespace_id, account_id) -> бакет от 1 до 100.

2) Если бакет от 1 до 30, то пользователь проходит в эксперимент.

3) hash(experiment_id, account_id) -> бакет от 1 до 100.

4) Если бакет от 1 до 50, то пользователь попадает в контроль. В противном случае в тест.

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

Второй способ ограничить процент пользователей, попадающих в эксперимент – сделать это через параметры самого эксперимента.

1) hash(experiment_id, account_id) -> бакет от 1 до 100.

2) Если бакет от 1 до 15, то пользователь попадает в контроль. От 16 до 30 – в тест. В противном случае не попадает в эксперимент.

Можно даже (хоть это, как правило, излишне) комбинировать два способа. В примере ниже я выбрал слой Empty Search Suggestions и выделил на эксперимент 30% пользователей. При этом в настройках эксперимента я указал, что только 50% пользователей будут в него попадать. В итоге 30% * 50% = 15% пользователей, стриггеривших фиче флаг, попадут в эксперимент и посплитуются в соотношении 70/30.

Метрики

GrowthBook позволяет заводить метрики прямо в админке. Прежде чем сделать это, необходимо создать Fact Table. Фактовая таблица не является таблицей физически – это просто шаблон запроса в формате

В этом запросе может быть сколько угодно джойнов и столбцов. Важно, чтобы на выходе был хотя бы один столбец с единицей рандомизации (на скрине – account_id) и timestamp.

На основе фактовой таблицы можно создавать метрики. Достаточно выбрать столбец, по которому будет считаться метрика, и агрегирующую функцию. Также в Growthbook можно заводить фильтры, которые можно навешивать на метрики. В итоге конфиги метрики будут выглядеть так:

  • Fact Table – ab_testicles
  • Value – value_column
  • Per-User Aggregation – SUM
  • Row Filter – some_other_columns = 'Delivered'

Если метрика – ratio, то нужно отдельно указать конфиги для числителя и знаменателя.

Для каждой метрики можно включить каппинг, CUPED, сделать её оконной (учитывается только активность за X дней после попадания в эксперимент) или lookback (учитывается только активность за X дней до текущей даты или даты окончания эксперимента). Единицы рандомизации, с которыми работает метрика, определяются фактовой таблицей. В примере выше я добавил только столбец account_id, но мог бы добавить еще и, например, session_id.

Пайплайн расчетов

Основная часть расчетов делается в SQL. На основе конфигов эксперимента, фактовой таблицы и конфигов метрики формируется примерно такой скрипт:

В реальности он чуть сложнее, так как на него навешиваются дополнительные условия в виде разрезов, фильтров на ботов, каппинга, CUPED, CTE для знаменателя в случае ratio-метрики и т.д.

Все дальнейшие расчеты производятся в питоне с использованием библиотеки GrowthBook. Сам ноутбук с SQL-запросами и расчетами каждой метрики можно скачать на странице эксперимента.

Результаты эксперимента

Метрики в эксперименте можно добавить в один из трех разделов – Goal, Secondary и Guardrail. Если Goal метрик несколько, то к ним применяется поправка на множественные сравнения. Также любой пользователь может создать кастомный отчет со своими метриками и разрезами. Результаты можно представить в виде простых разностей или процентных приростов.

В GrowthBook частично реализован триггеринг. Если фиче флаг настроен так, что вариант пользователя запрашивается сильно раньше момента взаимодействия с фичей (например, при открытии приложения), то можно использовать функцию Activation Metric. Вы выбираете активационную метрику – конверсию в нужный экран. После этого GrowthBook модифицирует SQL-запрос так, чтобы в анализ попадала только активность тех пользователей, которые действительно достигли этого экрана, и только начиная с момента конверсии.

Статистика

Тут стандартный набор:

  • t-тест
  • дельта-метод для ratio-метрик и доверительных интервалов вокруг процентного прироста
  • CUPED
  • Холм-Бонферрони или Бенжамини-Хочберг для множественных сравнений
  • проверка на SRM и на попадание пользователей в более чем одну группу

Еще есть sequential, который корректирует ДИ, и байесовский подход.

Недавно GrowthBook добавил калькулятор MDE. Для его использования нужно выбрать:

  • фактовую таблицу, на основе которой можно выгрузить всех пользователей, которые заходят на экран с будущим изменением
  • интересующую метрику

Затем формируется скрипт, похожий на тот, что я приводил выше. Данные выгружаются за 8 недель. Пользователи бьются на когорты по дню первого захода на нужный экран. Для каждой когорты рассчитываются: количество пользователей, сумма по метрике и сумма квадратов по метрике (последняя нужна для вычисления дисперсии). Все эти величины аддитивны, а значит, можно сложить первые 7*n дней, чтобы рассчитать MDE для нужного количества недель.

Какое изящное решение, подумал я сначала. К сожалению, есть проблема: для каждой когорты сумма по метрике считается за весь период – вплоть до конца восьмой недели. В то время как нас интересует значение метрики только до конца i-й недели, где i – потенциальная длительность эксперимента в неделях. Так что спасибо, Growthbook, но мы пока лучше в ноутбуке задизайним.

Сколько стоит

В 2021-ом – 100-200к в год. Сейчас не знаю

Мой тгк @abtesticles

Report Page