# Тестирование фич через API-кампании

Этот гайд помогает запустить A/B или мультивариативный тест для фичи, которую нельзя корректно протестировать обычной Web campaign. Например, если нужно сравнить несколько провайдеров поискового движка, алгоритмов ранжирования, серверных правил выдачи или другой backend-driven логики.

В таком сценарии Gravity Field отвечает за разделение трафика, стабильное закрепление пользователя за вариацией и отчетность, а сайт сам применяет выбранный вариант фичи.

## Когда использовать этот подход

Используйте API-кампанию, если:

- вариант теста должен применяться на backend сайта до рендера страницы или до выполнения бизнес-логики;
- фича не является визуальным блоком, который Gravity Field может вставить через Web campaign;
- нужно вернуть сайту конфигурацию, например `searchProvider`, `rankingModel`, `featureFlag` или набор параметров;
- сайт сам контролирует отображение результата и отправку продуктовых событий.

Для таких тестов обычно подходит кампания типа **Custom JSON**. Если вы тестируете рекомендательные стратегии и хотите получать товары из Gravity Field, используйте **Recommendations JSON**. Подробнее о типах API-кампаний: [API кампании](/personalization/Campaigns/api_campaigns.md).

## Как устроен поток

```mermaid
sequenceDiagram
    participant Browser as Браузер
    participant Site as Backend сайта
    participant GF as Gravity Field API

    Browser->>Site: Запрос страницы или поисковой выдачи
    Note over Site: Читает идентификаторы пользователя и сессии из cookie
    Site->>GF: POST /ssapi/choose с selector кампании
    GF-->>Site: Вариация, decisionId и cookies[] при необходимости
    Note over Site: Выбирает provider/конфиг фичи и выставляет cookie
    Site-->>Browser: Страница или данные с выбранным вариантом
    Browser->>GF: События поиска, кликов, корзины, покупки
```

Базовая техническая схема совпадает с гибридной интеграцией: backend передает Gravity Field идентификаторы пользователя и сессии, получает выбранную вариацию и обновляет cookie, если они пришли в ответе. Подробные правила чтения и установки cookie описаны в разделе [Гибридная интеграция](/Integration/hybrid_integration/hybrid_integrations.md).

## 1. Спроектируйте эксперимент

Перед настройкой кампании зафиксируйте:

- что является контрольной вариацией, например текущий поисковый провайдер;
- какие варианты сравниваются, например `provider_a`, `provider_b`, `provider_c`;
- на каком трафике запускается тест: все пользователи, только search page, только mobile, только определенный сегмент;
- как долго пользователь должен видеть один и тот же вариант;
- какая метрика определяет победителя.

Для теста поискового провайдера чаще всего нужна привязка вариации **к пользователю**, а не только к сессии. Так пользователь не будет видеть разные движки поиска при повторных визитах в рамках одной версии теста. Подробнее о распределении и закреплении вариаций: [Распределение трафика](/personalization/AB testing/traffic_allocation.md).

В качестве primary metric выбирайте ближайшее действие к тестируемой фиче. Для поиска это может быть цель на основе клика по результату, добавления в корзину после поиска, покупки после поиска или другого кастомного события. Подробнее: [Выбор основной метрики](/personalization/AB testing/primary_metric.md).

## 2. Создайте API-кампанию

1. Перейдите в **Campaigns → API Campaigns**.
2. Создайте кампанию типа **Custom JSON**.
3. Задайте понятный API-селектор, например `search_provider_test`.
4. Создайте сценарий с нужным таргетингом и расписанием.
5. Добавьте вариации для всех сравниваемых вариантов.
6. Настройте распределение трафика, например 33/33/34 для A/B/C теста.
7. Выберите primary metric и stickiness.
8. Активируйте сценарий и кампанию, затем опубликуйте изменения.

Пример содержимого вариаций:

=== Control
```json
{
  "searchProvider": "current",
  "searchConfigVersion": "baseline"
}
```
=== Provider A
```json
{
  "searchProvider": "provider_a",
  "searchConfigVersion": "a_v1"
}
```
=== Provider B
```json
{
  "searchProvider": "provider_b",
  "searchConfigVersion": "b_v1"
}
```
===

Содержимое вариации должно быть минимальным контрактом между Gravity Field и сайтом: только те поля, которые нужны backend или frontend для включения нужного варианта. Подробный процесс создания API-кампании описан в гайде [API кампании](/personalization/Campaigns/api_campaigns.md).

## 3. Подключите выбор вариации на backend

На стороне сайта добавьте вызов `/ssapi/choose` в тот участок, где принимается решение о варианте фичи. Для поиска это может быть backend-обработчик страницы поиска или API-метод, который возвращает результаты.

Backend должен:

- прочитать идентификаторы пользователя и сессии из cookie по правилам гибридной интеграции;
- отправить `/ssapi/choose` с selector кампании;
- взять конфиг из `choices[].variations[].payload.data.custom`;
- сохранить `decisionId`, если он нужен frontend для отправки взаимодействий;
- выставить пользователю cookie из `cookies[]`, если они пришли в ответе;
- применить вариант фичи, например выбрать нужный поисковый provider;
- использовать fallback, если Gravity Field не вернул кампанию или API не ответил вовремя.

Пример запроса:

```json
{
  "user": {
    "slid": "USER_ID_FROM_COOKIE"
  },
  "session": {
    "sl": "SESSION_ID_FROM_COOKIE"
  },
  "context": {
    "page": {
      "type": "SEARCH",
      "location": "https://example.com/search?q=boots"
    },
    "device": {
      "userAgent": "USER_AGENT_FROM_REQUEST",
      "ip": "USER_IP_FROM_REQUEST"
    }
  },
  "selector": {
    "names": [
      "search_provider_test"
    ]
  },
  "options": {
    "isImplicitPageview": true
  }
}
```

Подробные параметры запроса и варианты ответа описаны в разделе [Получение кампаний](/Integration/api_integration/personalization/choose.md).

!!!warning
Задайте короткий timeout для `/ssapi/choose` и заранее определите fallback. Для теста поискового провайдера fallback обычно должен вести на текущий production-провайдер, чтобы сбой API не ломал поиск.
!!!

## 4. Отправьте события для оценки результата

Gravity Field сможет сравнить вариации только по событиям, которые получает от сайта. Для кликов по элементам, связанным с выбранной вариацией, отправляйте `engagement CLICK` с `decisionId`: так клик будет привязан к кампании, версии теста и вариации.

Рекомендуемый набор:

- `CLICK` engagement — пользователь взаимодействовал с вариантом фичи, например кликнул по результату поисковой выдачи;
- `Keyword Search` — пользователь выполнил поиск;
- `Filter Items` и `Sort Items` — пользователь фильтровал или сортировал выдачу;
- кастомное событие `Search Results Viewed` — пользователь увидел выдачу;
- кастомное событие `Search Result Clicked` — дополнительная детализация клика по результату;
- кастомное событие `Search Zero Results` — поиск вернул пустую выдачу;
- `Add to Cart` и `Purchase` — если тест влияет на e-commerce воронку.

Пример отправки клика по выбранной вариации:

```jsx
window.SL.ServerUtils.reportEngagement(decisionId, "CLICK");
```

Если для анализа нужны параметры поиска, дополнительно отправьте кастомное событие:

```jsx
GF.API("event", {
  name: "Search Result Clicked",
  properties: {
    searchProvider: "provider_a",
    query: "boots",
    productId: "sku-123",
    position: 3
  }
});
```

Если клик по результату используется как CTR-метрика кампании, ориентируйтесь на `engagement CLICK`. Если нужна цель с поисковыми атрибутами, используйте кастомное событие как Goal и заранее проверьте, что оно корректно попадает в отчеты. Подробная схема событий описана в разделе [Настройка передачи событий](/Integration/web_integration/events.md), а методы engagement — в разделе [Клиентский API](/Integration/web_integration/client_side_api/other_helpful.md).

## 5. Проверьте перед запуском

Перед публикацией на боевой трафик проверьте:

- `/ssapi/choose` возвращает одну из ожидаемых вариаций по selector;
- backend корректно применяет `searchProvider` или другой конфиг фичи;
- cookie из ответа Gravity Field устанавливаются на домен сайта и доступны frontend-скрипту;
- у одного пользователя вариант остается стабильным согласно выбранному stickiness;
- при ошибке `/ssapi/choose` сайт использует fallback;
- события поиска, кликов, корзины и покупки приходят в Gravity Field;
- трафик распределяется между вариациями в ожидаемых долях.

Для отладки API-запросов используйте [API логи](/Integration/api_integration/api_logs.md).

## 6. Анализируйте как нерекомендательную кампанию

После запуска анализируйте тест в отчете кампании:

- сначала проверьте корректность эксперимента и распределение Users/Impressions;
- смотрите primary metric, uplift и Probability to be best;
- дополнительно анализируйте ближайшие метрики поиска, например клики по результатам, zero results, add to cart после поиска;
- проверяйте финальные бизнес-метрики: покупки, выручку, Revenue/User;
- смотрите сегменты, где поисковый провайдер мог сработать иначе: device, OS, city, traffic source, new/returning users.

Подробный порядок анализа описан в гайде [Как анализировать нерекомендательные кампании](/personalization/Reports/non_recs_campaigns_guide.md).

## Связанные материалы

- [API кампании](/personalization/Campaigns/api_campaigns.md)
- [Гибридная интеграция](/Integration/hybrid_integration/hybrid_integrations.md)
- [Получение кампаний](/Integration/api_integration/personalization/choose.md)
- [Настройка передачи событий](/Integration/web_integration/events.md)
- [Выбор основной метрики](/personalization/AB testing/primary_metric.md)
- [Как анализировать нерекомендательные кампании](/personalization/Reports/non_recs_campaigns_guide.md)
