Контекстные параметры и типы участников
Определения
Контекстный параметр
Контекстный параметр (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 бывает типом участника, чтобы делить аудиторию по аккаунтам, и контекстным параметром, чтобы отбирать аккаунты по признаку. Это две независимые записи: каждая создаётся, активируется и архивируется отдельно, изменения одной не затрагивают другую.
| Контекстный параметр | Тип участника | |
|---|---|---|
| Отвечает на вопрос | Кто может попасть в эксперимент | По какому идентификатору делить на группы |
| Где выбирается в эксперименте | Конструктор условий на шаге «Дизайн эксперимента» | Поле «Тип участника» |
| Сколько в одном эксперименте | Любое количество условий | Один |
| Чем управляет тип данных | Набором операторов сравнения и форматом значения | Способом построить ключ для связи с метриками |
Как значение проходит путь до отчёта
- Вы создаёте и активируете параметр или тип участника одним из двух способов: в интерфейсе Trisigma или в репозитории метрик. После активации контекстный параметр появляется в конструкторе условий на шаге «Дизайн эксперимента», а тип участника - в поле «Тип участника» формы эксперимента.
- Ваше приложение передаёт значение в запросе к Splitter в
randomizationUnits, ключtypeравен label:{"type": "account_id", "value": "acc-1042"}. - Splitter проверяет условия, назначает группу и записывает событие экспозиции или назначения вместе со всеми переданными параметрами.
- Trisigma строит в вашем ClickHouse view
v_clickstream_ab_event. Для каждого активного или архивного параметра и типа участника в нём есть колонка. Её значение берётся из события по ключуtype, который приложение передало вrandomizationUnits. - Расчёт отчёта берёт участников из этого view и соединяет их с источником метрик по колонке, указанной в
participantвsources.yaml.
View v_clickstream_ab_event обновляется раз в 10 минут. Новая запись п опадает в отчёт в течение этого времени, в форме эксперимента она доступна сразу после активации.
Ключ связи с метриками
Тип данных определяет, как значение превращается в ключ, по которому участник соединяется со строками источника метрик.
| Тип данных | Ключ во view | Что положить в колонку участника в источнике метрик |
|---|---|---|
int | Число из запроса, преобразование toUInt64OrZero | Тот же идентификатор числом |
str, float, bool, date, semver | 64-битный хеш 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 значение, которое не является неотрицательным целым числом, превращается в 0. Участник с ключом 0 исключается из расчёта, ошибку платфор ма при этом не возвращает. Если идентификатор может содержать буквы, выбирайте тип str.
Хеш считается от строки в том виде, в каком её передало приложение: регистр и пробелы не меняются, поэтому ABC-1 и abc-1 дают разные ключи. Передавайте в Splitter идентификатор в том же виде, в каком он хранится в источнике метрик. Уже записанные события правкой источника не исправить.
Базовые типы участников
Типы участников user и visitor создаёт платформа. Их тип данных и колонки изменить нельзя.
| Тип участника | Ключ в randomizationUnits | Тип данных | Что положить в колонку участника в источнике метрик |
|---|---|---|---|
user | user_id | int | Идентификатор пользователя числом |
visitor | visitor_id | str | from_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_ui | custom_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_param | label | Ключ в randomizationUnits запроса к Splitter |
report_allocation_column | label | Колонка с исходным значением во view |
report_metric_join_column | label | Колонка с ключом связи с метриками во 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 создавайте, только если по этому идентификатору нужны ещё и условия отбора.
Что происходит с запущенными экспериментами после архивации?
Они продолжают работать и считаться. Архивная запись остаётся в экспериментах, где уже выбрана, но недоступна для выбора в новых.
Что дальше
- Управление в интерфейсе - экраны, поля и действия в разделе «Настройки воркспейса».
- Управление в репозитории метрик - описание в YAML.
- Источники данных - поле
participantи связь с метриками.