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

Общие положения API Сплиттера

Перед началом работы​

Запросите у менеджера Trisigma два параметра. Они уникальны для каждого клиента:

ПараметрГде используется
<host>Адрес API в URL каждого запроса
Bearer-токенЗаголовок Authorization каждого запроса

Формат запроса​

API Splitter использует RPC-протокол на базе HTTP. Каждый метод вызывается POST-запросом:

POST https://<host>/<method_name>/
примечание

Косая черта (/) в конце адреса запроса обязательна.

Обязательные заголовки​

ЗаголовокЗначениеНазначение
AuthorizationBearer <ваш_токен>Авторизация клиента
Content-Typeapplication/jsonФормат тела запроса
User-AgentИмя вашего сервиса, например my-service/1.0Идентификация источника трафика
Запрос без User-Agent не дойдёт до Splitter

Инфраструктурная защита Trisigma блокирует запросы с пустым или отсутствующим User-Agent до того, как они достигают сервиса. Передавайте непустое значение в каждом запросе.

Список доверенных IP-адресов​

Шаг опциональный: без него интеграция также работает.

Если ваш сервис обращается к Splitter с фиксированного набора IP-адресов, передайте их список менеджеру Trisigma. Команда добавит адреса в список доверенных на уровне инфраструктуры - это снижает риск ложной блокировки при всплесках нагрузки.

Шаг подходит сервисам, у которых:

  • запросы к Splitter идут только с бэкенда (сервер-сервер), без прямых обращений с мобильных клиентов
  • исходящие IP известны заранее и меняются редко

Методы API​

Параметры пользователя передавайте через randomizationUnits - он поддерживает любые типы партисипантов: стандартные (user_id, visitor_id) и кастомные (например, store_id, city_id, phone_hash).

Допустимые значения поля type задают контекстные параметры и типы участников вашего пространства: в type передаётся их label. Как их создать и как значение попадает в отчёт - в разделе Контекстные параметры и типы участников.

Поле participant устарело

Поле participant (userId/visitorId) оставлено для обратной совместимости. Удаление не планируется - существующие интеграции продолжат работать. В новых интеграциях, пожалуйста, используйте randomizationUnits.

Значение value - всегда строка

В randomizationUnits внутри value значение всегда передаётся строкой, даже для числовых типов. При переходе с participant число становится строкой: {"participant": {"userId": 123456}} - то же самое, что {"randomizationUnits": [{"type": "user_id", "value": "123456"}]}.

Передать оба поля (participant и randomizationUnits) в одном запросе не ошибка. Значения объединяются: при совпадении типа (например, user_id) побеждает randomizationUnits, несовпадающие типы суммируются. Подробнее - ниже, в параметрах getFeaturesByTag.

Получение списка фичей (getFeaturesByTag)​

Метод getFeaturesByTag возвращает список фичей по заданному тегу.

Алгоритм работы​

  1. Отбор экспериментов, в которых есть переданный tag

  2. Проверка участия пользователя в отобранных экспериментах. В ходе проверки переданные параметры пользователя сравниваются с конфигурацией эксперимента

    примечание

    Если конфигурация эксперимента требует параметра пользователя (см. Условия попадания в эксперимент), которого нет в запросе, эксперимент не попадёт в ответ. Метод ошибку не возвращает.

  3. Сохранение информации о запросе фичи пользователя для аналитики.

  4. Формирование ответа

Общие рекомендации​

  1. Убедитесь, что в заголовке запроса используется актуальный Bearer токен, выданный вам командой Trisigma.
  2. Передавайте максимум возможной информации о пользователе, чтобы гарантировать прохождение всех фильтров эксперимента.
  3. При формировании запроса на получение фичей, в параметре tag укажите значение, связанное с конкретным сервисом или страницей, для которых вы хотите получить данные.
  4. Кеширование ответа. Запрашивайте участие пользователя у Splitter один раз за сессию. Этот подход используется в мобильных приложениях. Данные групп меняются редко - частые запросы не нужны.
  5. Точка запроса. Старт приложения или начало сессии - подходящий момент для получения всего списка экспериментов и фичей.
Пустые и нулевые идентификаторы не дают ошибку, но ломают распределение

Если передать userId: 0, пустой visitorId: "" или пустой список randomizationUnits, Splitter не определит группу пользователя и вернёт пустой список фичей. При этом ошибки 400 может не быть - придёт 200 с пустым результатом.

Всегда передавайте хотя бы один ненулевой идентификатор.

Параметры запроса​

ПараметрТипОбязательностьПримерОписание
tagstringДа"product_page"Тэг эксперимента, используемый для группировки.
platform.idintДа1ID платформы, идентифицирует устройство или среду.
platform.versionstringНет"2.15.0"Версия платформы (например, версия приложения).
randomizationUnitslistУсловно[{"type": "user_id", "value": "12345"}]Параметры пользователя (рекомендуемый способ). Хотя бы один параметр должен быть передан.
randomizationUnits.typestringДа"user_id"Тип параметра пользователя: "user_id", "visitor_id", кастомные типы.
randomizationUnits.valuestringДа"12345"Значение параметра пользователя. Всегда строка, даже для числовых типов.
participant.userIdintУсловно123456Устаревший. ID пользователя. Используйте randomizationUnits с type: "user_id".
participant.visitorIdstringУсловно"a1b2c3d4"Устаревший. ID устройства или анонимного посетителя. Используйте randomizationUnits с type: "visitor_id".
Одновременная передача participant и randomizationUnits

Оба поля можно передавать в одном запросе - ошибки не будет. Splitter объединяет их по следующим правилам:

  • При совпадении типа (например, user_id) значение из randomizationUnits имеет приоритет над participant.
  • При отсутствии пересечений типы суммируются: participant.userId + randomizationUnits: [{type: "phone_hash", ...}] дадут оба идентификатора.

В новых интеграциях передавайте идентификаторы только через randomizationUnits.

Формирование запроса​

URL:

POST https://<host>/getFeaturesByTag/

Заголовки:

Authorization: Bearer <ваш_токен>
Content-Type: application/json
User-Agent: <ваш-сервис>/<версия>
X-Source: local

Тело запроса (рекомендуемый способ - randomizationUnits):

{
"tag": "<ваш_тег>",
"platform": {
"id": 1,
"version": "2.15.0"
},
"randomizationUnits": [
{
"type": "user_id",
"value": "123456"
},
{
"type": "phone_hash",
"value": "33AFF380-6289-4B76-BB19-46EB8B7D8998"
},
{
"type": "age",
"value": "30"
}
]
}
Тело запроса (устаревший способ - participant, оставлен для совместимости)
{
"tag": "<ваш_тег>",
"platform": {
"id": 1,
"version": "2.15.0"
},
"participant": {
"userId": 123456
}
}

Пример успешного ответа​

{
"result": {
"features": [
{
"label": "test_group",
"experimentLabel": "demo_experiment",
"exposureParams": "1:2:12345"
}
]
}
}

Расшифровка ответа:

ПараметрТипПримерОписание
labelstring"test_group"Группа, в которую попал пользователь.
experimentLabelstring"demo_experiment"Лейбл эксперимента, который задается при создании в Trisigma.
exposureParamsstring"1:2:12345"Внутренний параметр. Устарел, запланирован к удалению.

SLA Splitter описан здесь.

Регистрация участия пользователя (exposeManyV2)​

Метод exposeManyV2 фиксирует факт показа фичи пользователю в рамках эксперимента (exposure). Без этих событий пользователи не попадают в отчёт - аналитика по эксперименту не строится.

Алгоритм работы​

Splitter не запоминает, какую группу он выдал пользователю в getFeaturesByTag. Для каждого exposure он считает группу заново. Отсюда всё поведение метода:

  1. Splitter сразу отвечает ok: true и только потом разбирает пачку. Клиент не ждёт обработки, но по ответу нельзя понять, засчитано ли событие.
  2. Для каждого события Splitter заново определяет группу по experimentLabel, platform и randomizationUnits из этого события.
  3. Если группа определилась, событие попадает в отчёт. Если нет, событие пропускается без ошибки.
Когда событие теряется без ошибки
  • experimentLabel указан с ошибкой или эксперимент уже завершён: Splitter не находит активный эксперимент.
  • Данные пользователя в exposure отличаются от тех, что были в getFeaturesByTag. Splitter считает группу для другого пользователя: если он не проходит условия попадания в эксперимент, событие теряется.

Общие рекомендации​

  1. Передавайте те же данные пользователя, что и в getFeaturesByTag: platform и randomizationUnits (или устаревший participant). Тогда Splitter получит ту же группу, что выдал раньше.
  2. Отправляйте exposure в момент, когда пользователь увидел фичу, а не сразу после ответа getFeaturesByTag. Например, эксперимент меняет кнопку на экране оплаты. Фичи приложение запрашивает при старте, а exposure отправляет, когда пользователь открыл экран оплаты. Тогда в отчёт попадут только те, кто кнопку видел. Если отправлять exposure при старте, в отчёт попадут и те, кто до оплаты не дошёл, и эффект размоется.
  3. Копите события и отправляйте пачками. В одном запросе - до 2000 событий. Отправляйте накопленное не реже раза в сутки.

Параметры запроса​

ПараметрТипОбязательностьПримерОписание
exposuresarrayДа-Массив объектов, описывающих события показа фичи пользователю.

Структура объекта в массиве exposures:

ПараметрТипОбязательностьПримерОписание
experimentLabelstringДа"demo_experiment"Лейбл эксперимента, к которому относится событие.
platform.idintДа1ID платформы, на которой произошло событие.
platform.versionstringНет"2.15.0"Версия платформы (например, приложения) в момент события.
randomizationUnitslistУсловно[{"type": "user_id", "value": "12345"}]Параметры пользователя (рекомендуемый способ). Должны совпадать с теми, что передавались в getFeaturesByTag.
randomizationUnits.typestringДа"user_id"Тип параметра пользователя: "user_id", "visitor_id", кастомные типы.
randomizationUnits.valuestringДа"12345"Значение параметра пользователя. Всегда строка, даже для числовых типов.
participant.userIdintУсловно123456Устаревший. ID пользователя. Используйте randomizationUnits с type: "user_id".
participant.visitorIdstringУсловно"a1b2c3d4"Устаревший. ID устройства или анонимного посетителя. Используйте randomizationUnits с type: "visitor_id".

Формирование запроса​

URL:

POST https://<host>/exposeManyV2/

Заголовки:

Authorization: Bearer <ваш_токен>
Content-Type: application/json
User-Agent: <ваш-сервис>/<версия>
X-Source: local

Тело запроса (рекомендуемый способ - randomizationUnits):

{
"exposures": [
{
"experimentLabel": "new_checkout_flow_2023",
"platform": {
"id": 1,
"version": "2.5.1"
},
"randomizationUnits": [
{
"type": "user_id",
"value": "1234567"
},
{
"type": "visitor_id",
"value": "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8"
},
{
"type": "phone_hash",
"value": "33AFF380-6289-4B76-BB19-46EB8B7D8998"
}
]
}
]
}
Тело запроса (устаревший способ - participant, оставлен для совместимости)
{
"exposures": [
{
"experimentLabel": "homepage_banner_test_Q4",
"platform": {
"id": 5,
"version": "4.12.0"
},
"participant": {
"userId": 9876543,
"visitorId": "z9y8x7w6-v5u4-t321-s9r8-q7p6o5n4m3l2"
}
}
]
}

Пример успешного ответа​

{
"result": {
"ok": true
}
}

Обработка ошибок​

Статусы ответа:

  1. 400 Bad Request - некорректные данные в теле запроса.
  2. 500 Internal Server Error - серверная ошибка.

При ошибке тело ответа содержит JSON:

{
"error": {
"kind": "<error_kind>",
"message": "<error_message>"
}
}
  1. kind. тип ошибки, повторяющий логику HTTP-статусов.
  2. message. текстовое описание ошибки.

Примеры распространенных ошибок:

СтатусСообщениеПояснение и действия
400"decode input DTO: Decode: field 'tag' is required..."Ошибка валидации. Обязательный параметр tag не был передан.
Решение: Убедитесь, что в теле запроса указан параметр tag.
400"decode input DTO: Decode: field 'id' is required..."Ошибка валидации. В объекте platform отсутствует обязательный параметр id.
Решение: Добавьте в объект platform параметр id.
400"bad request: все возможные параметры сплитования не заполнены"Ошибка валидации. Не передан ни один идентификатор пользователя.
Решение: Передайте хотя бы один параметр пользователя в randomizationUnits (например, {"type": "user_id", "value": "12345"}).

Ключевые понятия: tag и experimentLabel​

При работе со Splitter Trisigma используются два понятия: Тег и Лейбл. Разница между ними важна для корректной интеграции.

Что такое tag?​

tag - это средство группировки экспериментов. Он ограничивает набор экспериментов, которые возвращаются для конкретного сервиса, страницы или компонента. Тег задаётся при создании эксперимента в интерфейсе Trisigma.

Назначение тегов:

  1. Группировка по сервисам. Каждый сервис может использовать свой уникальный тег для получения только релевантных ему экспериментов.
  2. Оптимизация запросов. Вместо получения всех активных экспериментов сервис запрашивает данные только по нужному тегу.
  3. Гибкое управление. Теги позволяют подключать новые эксперименты к разным сервисам без изменения их кода.

Пример:

Карточка товара (PDP): использует тег "product_page".

Сервис рекомендаций: использует тег "recommendations".

Эксперименты распределены следующим образом:

  1. Эксперимент A связан с тегами "product_page" и "recommendations".
  2. Эксперимент B связан только с тегом "product_page".

При запросе сервиса рекомендаций с тегом "recommendations", он получит только эксперимент A.

Что такое experimentLabel?​

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

Назначение лейблов:

  1. Управление функциональностью. Лейблы позволяют управлять логикой в коде: if (experimentLabel === 'new_blue_button') { ... }.
  2. Тестирование и отчетность. Лейблы помогают точно отслеживать, в каком эксперименте участвует пользователь, и собирать данные для аналитики.

Пример:

Эксперимент A с лейблом "test_banner" тестирует новый баннер. Сервис, получив этот лейбл, включает баннер для пользователей в тестовой группе.

Ключевые различия между tag и experimentLabel​

ХарактеристикаtagexperimentLabel
НазначениеГруппировка экспериментовУникальный идентификатор эксперимента
ПрименениеФильтрация списка экспериментов при запросеУправление логикой в коде
УникальностьМожет быть одинаковым для нескольких экспериментовУникален в рамках системы
Пример"product_page", "recommendations""blue_button_2024", "test_banner_Q1"
  1. Установите тег для каждого сервиса, компонента или контекста, где проводится эксперимент.
  2. Используйте лейблы для управления функциональностью в коде в зависимости от экспериментов.
  3. При создании экспериментов в админке присваивайте им нужные теги, чтобы ограничить выдачу только для тех сервисов, которые их используют.

Сводная таблица параметров​

Все параметры API, сгруппированные по методам. «Условно» - в запросе обязателен хотя бы один идентификатор пользователя: randomizationUnits (рекомендуемый способ) или устаревший participant.

Параметры getFeaturesByTag​

ПараметрТипОбязательностьПримерОписание
tagstringДа"product_page"Тэг эксперимента для группировки и фильтрации.
platform.idintДа1ID платформы, идентифицирует устройство или среду.
platform.versionstringНет"2.15.0"Версия платформы (например, версия приложения).
randomizationUnitslistУсловно[{"type": "user_id", "value": "12345"}]Параметры пользователя (рекомендуемый способ).
randomizationUnits.typestringДа"user_id"Тип параметра пользователя ("user_id", "visitor_id", кастомные).
randomizationUnits.valuestringДа"12345"Значение параметра (всегда строка, даже для числовых типов).
participant.userIdintУсловно123456Устаревший. ID пользователя. Используйте randomizationUnits.
participant.visitorIdstringУсловно"a1b2c3d4"Устаревший. ID устройства/посетителя. Используйте randomizationUnits.

В ответе метод возвращает label (string) - лейбл фичи, группа, в которую попал пользователь.

Параметры exposeManyV2​

ПараметрТипОбязательностьПримерОписание
experimentLabelstringДа"demo_experiment"Лейбл эксперимента для идентификации.
platform.idintДа1ID платформы, идентифицирует устройство или среду.
platform.versionstringНет"2.15.0"Версия платформы (например, версия приложения).
randomizationUnitslistУсловно[{"type": "user_id", "value": "12345"}]Параметры пользователя (рекомендуемый способ). Должны совпадать с переданными в getFeaturesByTag.
randomizationUnits.typestringДа"user_id"Тип параметра пользователя ("user_id", "visitor_id", кастомные).
randomizationUnits.valuestringДа"12345"Значение параметра (всегда строка, даже для числовых типов).
participant.userIdintУсловно123456Устаревший. ID пользователя. Используйте randomizationUnits.
participant.visitorIdstringУсловно"a1b2c3d4"Устаревший. ID устройства/посетителя. Используйте randomizationUnits.

Маппинг платформ (platform)​

ПлатформаID
Desktop1
iOS4
Android5
Mobile (мобильный веб)6