Перейти к основному содержимому

Контекстные параметры и типы участников

Определения​

Контекстный параметр​

Контекстный параметр (context param) - это атрибут запроса к Splitter, по которому строятся условия попадания в эксперимент и исключения из него. В запросе значение всегда передаётся строкой. Тип данных, который вы указываете у параметра, задаёт, как Trisigma читает эту строку: какие операторы сравнения доступны в условии и в каком формате ждать значение.

Ваше приложение передаёт значение параметра в каждом запросе к Splitter в массиве randomizationUnits: в type - label параметра, в value - значение строкой. Splitter сравнивает значение с условием эксперимента и решает, участвует ли пользователь.

{
"tag": "product_page",
"platform": { "id": 1, "version": "2.15.0" },
"randomizationUnits": [
{ "type": "user_id", "value": "12345" },
{ "type": "has_active_subscription", "value": "true" }
]
}

Как сформировать запрос и какие методы принимают randomizationUnits - в описании API Splitter.

Тип участника​

Тип участника (participant type) - это идентификатор, который Splitter хеширует, чтобы назначить группу. Приложение передаёт его в том же массиве randomizationUnits, в type - label типа участника. Один и тот же идентификатор всегда получает одну и ту же группу. По этому же идентификатору отчёт находит данные участника: строки источника метрик, в которых значение колонки участника совпало с идентификатором, попадают в метрики его группы.

Чем они отличаются​

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

Контекстный параметрТип участника
Отвечает на вопросКто может попасть в экспериментПо какому идентификатору делить на группы
Где выбирается в экспериментеКонструктор условий на шаге «Дизайн эксперимента»Поле «Тип участника»
Сколько в одном экспериментеЛюбое количество условийОдин
Чем управляет тип данныхНабором операторов сравнения и форматом значенияСпособом построить ключ для связи с метриками

Как значение проходит путь до отчёта​

  1. Вы создаёте и активируете параметр или тип участника одним из двух способов: в интерфейсе Trisigma или в репозитории метрик. После активации контекстный параметр появляется в конструкторе условий на шаге «Дизайн эксперимента», а тип участника - в поле «Тип участника» формы эксперимента.
  2. Ваше приложение передаёт значение в запросе к Splitter в randomizationUnits, ключ type равен label: {"type": "account_id", "value": "acc-1042"}.
  3. Splitter проверяет условия, назначает группу и записывает событие экспозиции или назначения вместе со всеми переданными параметрами.
  4. Trisigma строит в вашем ClickHouse view v_clickstream_ab_event. Для каждого активного или архивного параметра и типа участника в нём есть колонка. Её значение берётся из события по ключу type, который приложение передало в randomizationUnits.
  5. Расчёт отчёта берёт участников из этого view и соединяет их с источником метрик по колонке, указанной в participant в sources.yaml.
Обновление view

View v_clickstream_ab_event обновляется раз в 10 минут. Новая запись попадает в отчёт в течение этого времени, в форме эксперимента она доступна сразу после активации.

Ключ связи с метриками​

Тип данных определяет, как значение превращается в ключ, по которому участник соединяется со строками источника метрик.

Тип данныхКлюч во viewЧто положить в колонку участника в источнике метрик
intЧисло из запроса, преобразование toUInt64OrZeroТот же идентификатор числом
str, float, bool, date, semver64-битный хеш xxHash64 от строки значенияfrom_big_endian_64(xxhash64(to_utf8(<колонка>)))

Хеш во view и формула в источнике дают одно и то же число для одной и той же строки. Пример источника со строковым идентификатором:

-- sources/sql/orders.sql
SELECT
from_big_endian_64(xxhash64(to_utf8(account_id))) AS account_key,
event_date,
revenue
FROM shop.orders
WHERE event_date BETWEEN :first_date AND :last_date
# sources/sources.yaml
orders:
sql: orders
dtm: event_date
connections: [trino]
participant: { account_id: account_key }
metric_configs: [orders]

В поле participant ключом служит label типа участника, значением - колонка источника с ключом.

Нечисловой идентификатор с типом int

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

Хеш считается от строки в том виде, в каком её передало приложение: регистр и пробелы не меняются, поэтому ABC-1 и abc-1 дают разные ключи. Передавайте в Splitter идентификатор в том же виде, в каком он хранится в источнике метрик. Уже записанные события правкой источника не исправить.

Базовые типы участников​

Типы участников user и visitor создаёт платформа. Их тип данных и колонки изменить нельзя.

Тип участникаКлюч в randomizationUnitsТип данныхЧто положить в колонку участника в источнике метрик
useruser_idintИдентификатор пользователя числом
visitorvisitor_idstrfrom_big_endian_64(xxhash64(to_utf8(<колонка с visitor_id>)))

Если идентификатор пользователя содержит буквы, тип user не подходит: такие значения превращаются в 0. Создайте свой тип участника с типом данных str и другим label.

Интерфейс или репозиторий метрик​

Интерфейс TrisigmaРепозиторий метрик
Кто работаетПользователь с правом редактирования настроекПользователь с доступом к репозиторию
Когда запись доступна в форме экспериментаСразу после активацииПосле run merge
Когда запись доступна в отчётеВ течение 10 минутПосле run merge
Имена колонокВсе технические имена равны labelЗадаются отдельно для Splitter, аллокации и связи с метриками
Связи типов участников (participation_mapping)НедоступныДоступны
Маппинг идентификаторов (int_id_mapping, transform)НедоступенДоступен
История измененийЖурнал статусовИстория git и ревью
Источник в спискеcustom_uicustom_git

Выбирайте интерфейс, когда label совпадает с ключом, который приложение передаёт в Splitter, а дополнительные преобразования не нужны. Выбирайте репозиторий метрик, когда нужны разные имена колонок, маппинг идентификаторов или связи между типами участников.

Записи из двух источников живут рядом. В интерфейсе записи из репозитория доступны только для просмотра, синхронизация репозитория не меняет записи, созданные в интерфейсе. Подробнее о работе с YAML - в разделе Управление в репозитории метрик.

Источник записи​

ИсточникОткуда записьГде меняется
custom_uiСоздана в интерфейсеВ интерфейсе
custom_gitОписана в traffic_markup/ репозитория метрикЧерез pull request в репозиторий метрик
system_gitБазовые типы платформы user и visitorНе меняется, архивировать и удалить нельзя

Статусы​

Статус в интерфейсеЗначениеМожно использовать в экспериментахЧто меняется в интерфейсе
«Черновик»draftНетВсё, кроме label
«Активный»activeДа, в новых и запущенныхТолько название
«Архив»archivedТолько в экспериментах, где уже выбранНичего, доступно восстановление
«Удалён»deletedНетНичего

Поля​

Поле в интерфейсеПоле в YAMLОбязательностьОписание
«Название»titleДаНазвание, которое видно в списках и в форме эксперимента. Уникально в рамках домена среди активных и архивных записей. Меняется в черновике и в активном статусе
«Лейбл»labelДаТехнический идентификатор и ключ в randomizationUnits. В интерфейсе: латинские строчные буквы, цифры и _, начинается с буквы, до 63 символов. Не меняется после создания
«Домен»domainНетОграничивает, в экспериментах какого домена доступна запись. Подробнее ниже
«Тип данных»typeДаint, str, float, bool, date, semver. Меняется только в черновике
«Типы экспериментов»allowed_experiment_typesДа, только для типа участникаТипы экспериментов, в которых можно выбрать этот тип участника. Список значений зависит от настроек вашего пространства

Уникальность label:

  • среди контекстных параметров label уникален во всём пространстве, включая удалённые записи;
  • среди типов участников действует такое же правило;
  • контекстный параметр и тип участника могут иметь одинаковый label.

Домен работает по-разному для двух сущностей:

  • контекстный параметр без домена доступен в экспериментах любого домена, с доменом - только в экспериментах этого домена;
  • тип участника доступен только в эксперименте с тем же доменом. Тип участника без домена не подходит эксперименту, у которого домен выбран. Указывайте домен ваших экспериментов.

Технические поля​

В репозитории метрик у записи есть ещё три имени. Интерфейс их не показывает и заполняет значением label.

Поле в YAMLЗначение при создании в интерфейсеНазначение
splitter_allocation_paramlabelКлюч в randomizationUnits запроса к Splitter
report_allocation_columnlabelКолонка с исходным значением во view
report_metric_join_columnlabelКолонка с ключом связи с метриками во view

Операторы сравнения для контекстного параметра​

Тип данных параметра решает две вещи: какие сравнения можно задать в условии и в каком виде приложение присылает значение. Значение в randomizationUnits всегда передаётся строкой, даже если это число.

Тип данныхКакие сравнения доступныКак передать значение
intравно (eq), не равно (ne), входит в список (in), не входит в список (not_in), больше (gt), меньше (lt), больше или равно (ge), меньше или равно (le)Целое число: "42"
floatТе же, что у intЧисло через точку: "3.14"
dateТе же, что у intДата в формате "YYYY-MM-DD": "2026-10-06"
strРавно, не равно, входит в список, не входит в списокЛюбая строка
boolРавно, не равно, входит в список, не входит в список"true" или "false"
semverБольше или равно (ge), меньше (lt)Версия: "10.2.3"

Если приложение не прислало параметр, прислало пустую строку или "0", пользователь не попадает в эксперимент. То же самое происходит, если значение не подходит под тип, например "abc" для int. Ошибки при этом нет. Поэтому не обозначайте «признака нет» значением 0 или пустой строкой. Для «да/нет» берите bool со значениями "true" и "false". Если вариантов может стать больше двух, сразу берите str: тип потом не поменять.

В одном условии «входит в список» или «не входит в список» число значений ограничено настройкой пространства. Если превысить лимит, форма покажет «Максимальное количество элементов: N». Чтобы исключить больше значений, добавьте в тот же сегмент ещё одно условие «не входит в список»: условия внутри сегмента должны выполняться все сразу. Чтобы включить больше значений, разбейте их на несколько сегментов: пользователю достаточно подойти под любой из них. Остальные условия повторите в каждом сегменте. Каждый сегмент показывается в отчёте отдельной вкладкой.

Ограничения​

  • Label выбирается один раз. Даже после удаления записи этот label нельзя взять снова, поэтому продумайте имя заранее.
  • После активации тип данных и домен не меняются. Если ошиблись, создайте новую запись с другим label.
  • В отчёт новая запись попадает не сразу, а в течение 10 минут после активации. Запускайте эксперимент после этого.
  • Label не должен совпадать со служебными колонками и с колонками других записей. Иначе перестанут применяться все изменения из репозитория метрик. Какие имена заняты - в разделе ниже.

Конфликт имён колонок​

Trisigma хранит значения всех параметров и типов участников в одной общей таблице - view v_clickstream_ab_event. У каждой записи там своя колонка, имя колонки берётся из label. Если две записи претендуют на одно имя, таблица не собирается. На практике это значит:

  • run merge не проходит ни для одного pull request в репозитории метрик, даже если он не касается разметки трафика. Pull request остаётся невлитым, бот пишет в нём комментарий об ошибке;
  • изменения, которые уже попали в репозиторий метрик, не загружаются в Trisigma: новые и изменённые метрики, источники, контекстные параметры и типы участников из YAML не появляются в интерфейсе и в отчётах;
  • запущенные эксперименты продолжают считаться, но по прежней версии таблицы. Новая запись, из-за которой возник конфликт, в отчёт не попадает.

Так продолжается, пока конфликт не устранён.

Поэтому не берите label, который уже занят:

  • служебными колонками: event_date, event_timestamp, eid, is_human, business_platform, app_version, ab_event_type, abs;
  • базовыми типами участников: user, user_id, cookie, cookie_id;
  • другой записью с другим типом данных. Например, контекстный параметр store_id с типом int и тип участника store_id с типом str конфликтуют.

Если после создания записи изменения из репозитория метрик перестали применяться, архивируйте эту запись, а затем удалите. Архивная запись всё ещё занимает колонку, удалённая - нет.

Частые вопросы​

Почему эксперимент не возвращается в ответе Splitter?​

Приложение не передало значение типа участника или параметра из условия, передало "" или "0", либо значение не разбирается под тип данных. Проверьте, что ключ type в randomizationUnits совпадает с label.

Если эксперимент то приходит, то нет, приложение передаёт разный набор randomizationUnits в разных вызовах. Группа зависит только от идентификатора, поэтому одинаковый запрос всегда даёт одинаковый ответ. Пользователь контрольной группы получает эксперимент с вариантом control; пустой ответ значит, что запрос не попал в эксперимент.

Почему в отчёте нет участников при работающем Splitter?​

Проверьте:

  • тип данных int, а идентификатор содержит буквы - ключ становится 0;
  • тип данных не int, а в источнике метрик лежит исходная строка или число без хеша;
  • в колонке участника в источнике метрик лежит другой идентификатор, например ID сессии вместо visitor_id. Ключи совпадают, только если источник считает их от того же значения, которое приложение передаёт в Splitter;
  • строка в запросе к Splitter и в источнике различается регистром или форматом;
  • с момента активации прошло меньше 10 минут, или синхронизация репозитория остановлена конфликтом колонок.

Как поменять тип данных активного параметра?​

Никак. Создайте запись с новым label и нужным типом, перенастройте приложение на новый ключ, старую запись архивируйте.

Можно ли создать тип участника без контекстного параметра?​

Да. Тип участника - самостоятельная запись. Контекстный параметр с тем же label создавайте, только если по этому идентификатору нужны ещё и условия отбора.

Что происходит с запущенными экспериментами после архивации?​

Они продолжают работать и считаться. Архивная запись остаётся в экспериментах, где уже выбрана, но недоступна для выбора в новых.

Что дальше​