# 🧪 Руководство: Гибридное A/B-тестирование

В этом руководстве описан пошаговый процесс внедрения и проведения A/B-тестирования в рамках гибридной модели интеграции. Эта модель предполагает, что бэкенд вашего сайта запрашивает вариации кампании через API-вызов во время серверного рендеринга (SSR), что позволяет исключить мерцание контента и улучшить производительность.

# Преимущества гибридного подхода

  • Отсутствие мерцания (flickering): Вариация встраивается в HTML на стороне сервера, поэтому пользователь видит финальную версию страницы мгновенно.
  • Высокая производительность: Критически важный контент загружается сразу, без задержек на выполнение JavaScript в браузере.
  • Надежность: Логика выбора вариации находится на бэкенде, что снижает зависимость от клиентской среды.

# Предварительные требования

Перед началом убедитесь, что у вас настроено следующее:

  1. Рабочая гибридная интеграция: Ваш бэкенд должен уметь взаимодействовать с API Gravity Field. Подробнее о гибридной интеграции.
  2. API-ключи: У вас должен быть доступ к API-ключам для аутентификации запросов. Подробнее об управлении API-ключами.

# Шаг 1: Настройка кампании в интерфейсе

Сначала необходимо создать API-кампанию, которая будет содержать варианты для A/B-теста.

  1. Перейдите в раздел Campaigns → API Campaigns и нажмите Создать кампанию.
  2. Выберите тип кампании Custom JSON. Этот тип позволяет вернуть данные в произвольном JSON-формате, который ваш бэкенд сможет обработать.
  3. Задайте API-селектор (например, homepage_cta_test). Этот селектор будет использоваться в API-запросе для получения кампании.
  4. Создайте как минимум две вариации (например, "Вариация А" и "Вариация Б").
  5. В каждой вариации определите JSON-объект, который описывает контент. Например:

    Вариация А (Контрольная):

    {
      "button_text": "Узнать больше",
      "button_color": "#007bff"
    }

    Вариация Б (Тестовая):

    {
      "button_text": "Купить сейчас",
      "button_color": "#28a745"
    }
  6. Настройте распределение трафика (например, 50/50) и сохраните кампанию.

Подробнее о создании API-кампаний.


# Шаг 2: Реализация на бэкенде

Это ключевой этап, на котором происходит запрос вариации и рендеринг страницы. Логика должна выполняться на вашем сервере при каждом запросе страницы, где проводится тест.

# 1. Чтение cookie пользователя

Для корректной идентификации пользователя и сессии необходимо прочитать cookie _slid_server и _sl_session из входящего HTTP-запроса.

plaintext
// Псевдокод
userId = getCookie('_slid_server');
sessionId = getCookie('_sl_session');

Если cookie отсутствуют (например, это новый пользователь), передавайте null в API-запрос. Gravity Field автоматически создаст новые идентификаторы и вернет их для установки.

# 2. Запрос вариации через API /choose

Отправьте POST-запрос на эндпоинт /ssapi/choose, передав идентификаторы пользователя, сессии и селектор кампании.

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

curl --request POST \
--url 'https://evs-01.gravityfield.ai/ssapi/choose' \
--header 'content-type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
    "user": {
        "slid": "USER_ID_FROM_COOKIE"
    },
    "session": {
        "sl": "SESSION_ID_FROM_COOKIE"
    },
    "context": {
        "page": {
            "type": "HOMEPAGE",
            "location": "https://your-site.com/"
        },
        "device": {
            "userAgent": "USER_AGENT_FROM_REQUEST",
            "ip": "USER_IP_FROM_REQUEST"
        }
    },
    "selector": {
        "names": [
            "homepage_cta_test"
        ]
    }
}'

⚠️ Важно: Установите для этого API-вызова строгий таймаут (например, 150-200 мс). Если ответ не получен вовремя, рендерьте страницу с контентом по умолчанию, чтобы не замедлять загрузку для пользователя.

Подробнее об API /choose.

# 3. Обработка ответа

API вернет JSON с выбранной вариацией и, возможно, новыми cookie для установки.

Пример ответа:

{
    "choices": [
        {
            "name": "Homepage CTA Test",
            "variations": [
                {
                    "name": "Вариация Б",
                    "payload": {
                        "type": "CUSTOM_JSON",
                        "data": {
                            "custom": {
                                "button_text": "Купить сейчас",
                                "button_color": "#28a745"
                            }
                        }
                    }
                }
            ],
            "decisionId": "65cde...:65cdf...:65cde...:65cdf..."
        }
    ],
    "cookies": [
        {
            "name": "_slid_server",
            "value": "NEW_OR_EXISTING_USER_ID",
            "maxAge": "31556926"
        },
        {
            "name": "_slsession",
            "value": "NEW_OR_EXISTING_SESSION_ID",
            "maxAge": "1800"
        }
    ]
}

# 4. Рендеринг вариации и установка cookie

  1. Извлеките данные вариации: Получите JSON из choices[0].variations[0].payload.data.custom.
  2. Извлеките decisionId: Сохраните значение choices[0].decisionId. Этот идентификатор понадобится на фронтенде для отслеживания взаимодействий.
  3. Передайте данные в шаблонизатор: Передайте данные вариации (текст кнопки, цвет) и decisionId в ваш движок шаблонов (например, Twig, EJS, Pug).
  4. Установите cookie: Если в ответе есть массив cookies, установите их в заголовки HTTP-ответа (Set-Cookie), чтобы обновить их в браузере пользователя.

Подробнее об обработке cookie в гибридной интеграции.


# Шаг 3: Реализация на фронтенде

На этом этапе страница уже приходит в браузер с отрендеренной вариацией. Единственная задача фронтенда — отследить взаимодействие пользователя с этой вариацией.

# 1. Передача decisionId на фронтенд

Ваш бэкенд должен встроить decisionId в HTML, например, в data- атрибут элемента, с которым будет взаимодействовать пользователь.

Пример HTML от сервера:

<button
  id="cta-button"
  style="background-color: #28a745;"
  data-decision-id="65cde...:65cdf...:65cde...:65cdf..."
>
  Купить сейчас
</button>

# 2. Отслеживание клика

Напишите небольшой JavaScript-код, который при клике на кнопку будет считывать decisionId и отправлять событие взаимодействия.

document.addEventListener('DOMContentLoaded', function() {
  const ctaButton = document.getElementById('cta-button');

  if (ctaButton) {
    ctaButton.addEventListener('click', function() {
      const decisionId = this.getAttribute('data-decision-id');

      if (decisionId && window.SL && window.SL.ServerUtils) {
        // Отправляем событие клика
        window.SL.ServerUtils.reportEngagement(decisionId, 'CLICK');
        console.log('Engagement reported for decisionId:', decisionId);
      }
    });
  }
});

Этот код использует метод из JS SDK Gravity Field для отправки события. Убедитесь, что основной скрипт Gravity Field подключен на странице.

Подробнее о клиентском API для отслеживания.


# Шаг 4: Анализ результатов

После запуска кампании и сбора данных вы можете анализировать результаты в интерфейсе Gravity Field.

Перейдите в отчет по вашей кампании и изучите метрики для каждой вариации, чтобы определить победителя.

Подробнее об анализе отчетов по кампаниям.


# Полная диаграмма рабочего процесса

sequenceDiagram
    participant Browser as Браузер
    participant Client Backend as Бэкенд клиента
    participant Gravity Field API as Gravity Field API

    Browser->>+Client Backend: GET /page (Пользователь переходит на страницу)
    Note over Client Backend: Чтение cookie (_slid_server, _sl_session)
    Client Backend->>+Gravity Field API: POST /ssapi/choose (с ID пользователя/сессии и селектором)
    Gravity Field API-->>-Client Backend: 200 OK (JSON с вариацией и cookie для установки)
    Note over Client Backend: 1. Парсинг данных вариации<br/>2. Рендеринг вариации в HTML<br/>3. Установка заголовков ответа для обновления cookie пользователя
    Client Backend-->>-Browser: 200 OK (HTML с отрендеренной вариацией)
    Note over Browser: Пользователь видит страницу мгновенно, без мерцания.

    Browser->>Browser: Пользователь взаимодействует с вариацией (например, кликает на кнопку)
    Note over Browser: JS на фронтенде читает decisionId из data-атрибута
    Browser->>+Gravity Field API: POST /ssapi/engagement (или использует JS SDK) с decisionId
    Gravity Field API-->>-Browser: 200 OK (Взаимодействие отслежено)

# FAQ

Q: Что делать, если API /choose отвечает слишком долго?
A: Всегда реализуйте запасной вариант (fallback) с контентом по умолчанию. Установите агрессивный таймаут на API-запрос (150-200 мс), чтобы не замедлять рендеринг страницы для пользователя.

Q: Как обрабатывать новых пользователей, у которых нет cookie?
A: Передавайте null в полях user.slid и session.sl. API Gravity Field сгенерирует новые идентификаторы и вернет их в поле cookies ответа. Ваша задача — установить эти cookie пользователю.

Q: Почему важно отслеживать взаимодействия (engagement)?
A: Без отслеживания взаимодействий A/B-тест не сможет собрать данные о действиях пользователей (кликах, конверсиях). Это сделает результаты теста недействительными, так как вы не сможете определить, какая вариация была более эффективной.