Гибридная интеграция
Гибридная интеграция сочетает возможности API и Web-интеграции. Критичные кампании можно запрашивать через API на сервере и включать персонализированный контент в HTML-разметку до загрузки страницы. При этом web-скрипт остаётся доступен для клиентских кампаний, сбора событий и быстрых гипотез.
Для новых server-side и headless-сценариев используйте API V2. Если у вас уже работает интеграция через /ssapi/*, её можно оставить на API V1 и переносить сценарии постепенно.
Как это работает
В гибридной модели главный путь выбора вариации проходит через backend сайта. Web-скрипт подключается уже на клиенте и закрывает клиентские сценарии: cookie, web-кампании и события.
Такой подход нужен, когда важно показать персонализированный контент без задержки и мерцания, но при этом сохранить возможности Web-интеграции: сбор событий, web-кампании, клиентские взаимодействия и единые идентификаторы пользователя.
sequenceDiagram
participant Browser as Браузер
participant Backend as Backend сайта
participant GFAPI as Gravity Field API
participant WebScript as Web-скрипт Gravity Field
participant Tracking as Gravity Field tracking
Browser->>Backend: GET /page<br/>Cookie: _slid_server, _slid, _slsession
Backend->>Backend: Читает cookie из HTTP-запроса
Backend->>GFAPI: POST /v2/choose или /ssapi/choose
GFAPI-->>Backend: Возвращает вариацию, идентификаторы и tracking-данные
Backend->>Backend: Подставляет вариацию в серверный шаблон
Backend-->>Browser: HTML с готовым блоком<br/>Set-Cookie при необходимости
Browser->>WebScript: Загружает web-скрипт
Browser->>Tracking: Отправляет показы, visible impression и кликиВ результате пользователь получает готовую страницу с выбранной вариацией, а Gravity Field продолжает связывать показы, клики и события с тем же профилем пользователя.
Идентификация пользователей
Если Web-интеграция уже завершена, то в браузере пользователя в корневом домене сайта есть cookie:
_slid- внутренний ID пользователя, выданный платформой. Устанавливается скриптомcore.js._slsession- внутренний ID сессии, выданный платформой. Устанавливается скриптомcore.js._slid_server- копия внутреннего ID пользователя. Устанавливается сервером клиента и имеет длительный срок жизни в отличие от_slid. Подробнее
Если вы ещё не выставляете cookie _slid_server, завершите настройку 1st-party cookie.
API V1
Перед запросом V1 прочитайте cookie _slid_server или _slid, а также _slsession.
user.slid:
- значение cookie
_slid_server, если оно есть; - иначе значение cookie
_slid, если оно есть; - иначе
null.
session.sl:
- значение cookie
_slsession, если оно есть; - иначе
null.
<?php
$user_id = $_COOKIE['_slid_server'] ?? $_COOKIE['_slid'] ?? null;
$session_id = $_COOKIE['_slsession'] ?? null;
$requestParams = [
"user" => [
"slid" => $user_id,
],
"session" => [
"sl" => $session_id,
],
];
?>
Если платформа сгенерировала новый ID пользователя или сессии, в ответе V1 будут значения для установки cookie. Обновляйте значения и срок жизни cookie при каждом получении cookies[]. Для этих cookie не должен быть установлен параметр HttpOnly, если они должны быть доступны web-скрипту.
{
"user": {
"slid": "6495a07d71568849c607a6ed"
},
"session": {
"sl": "43F9AD00-2D33-4AA3-8EE4-5638E8EB5976"
},
"cookies": [
{
"name": "_slid_server",
"value": "6495a07d71568849c607a6ed",
"maxAge": "31556926"
},
{
"name": "_slsession",
"value": "43F9AD00-2D33-4AA3-8EE4-5638E8EB5976",
"maxAge": "1800"
}
]
}
<?php
if (isset($data['cookies']) && is_array($data['cookies'])) {
foreach ($data['cookies'] as $cookie) {
if (isset($cookie['name'], $cookie['value'], $cookie['maxAge'])) {
setcookie(
$cookie['name'],
$cookie['value'],
time() + (int)$cookie['maxAge'],
"/",
$site_root_domain
);
}
}
}
?>
API V2
В web-hybrid сценарии V2 использует те же идентификаторы пользователя и сессии, которые уже живут в web-cookie. Отличается только название полей в API-запросе:
const uid = getCookie('_slid_server') || getCookie('_slid') || null;
const ses = getCookie('_slsession') || null;
const requestBody = {
user: {
uid,
ses
}
};
В V2 пользователь и сессия передаются в одном объекте user:
{
"user": {
"uid": "USER_UID",
"ses": "SESSION_ID"
}
}
Храните uid между сессиями пользователя, а ses - для текущей browser session. На сайте это означает, что uid нужно сохранять в _slid_server, а ses - в _slsession. Если пользователь новый, первый запрос можно отправить без uid и ses: Gateway создаст идентификаторы и вернёт их в response.user.
После ответов /user, /visit, /event или /choose обновляйте сохранённые значения, если они пришли в ответе:
if (response.user?.uid) {
setCookie('_slid_server', response.user.uid, { maxAge: 31556926, path: '/' });
}
if (response.user?.ses) {
setCookie('_slsession', response.user.ses, { maxAge: 1800, path: '/' });
}
Если в hybrid-сценарии одновременно используется web-скрипт и V2, web-идентификаторы остаются общими для обоих слоёв: web-скрипт продолжает работать с cookie _slid, _slid_server и _slsession, а backend мапит их значения в поля user.uid и user.ses для V2-запросов.
Получение кампаний
API V1: /ssapi/choose
V1-запрос использует selector.names[], context.page, user.slid и session.sl.
{
"user": {
"slid": "6495a07d71568849c607a6ed"
},
"session": {
"sl": "43F9AD00-2D33-4AA3-8EE4-5638E8EB5976"
},
"context": {
"page": {
"type": "HOMEPAGE",
"location": "https://shop.ru/"
}
},
"selector": {
"names": ["homepage_cta_test"]
}
}
В ответе V1 используйте choices[].variations[].payload для рендера контента, choices[].decisionId для tracking и cookies[] для обновления cookie.
API V2: /v2/choose
V2-запрос использует sec, user.uid, user.ses, ctx, device, options и data[].selector.
{
"sec": "YOUR_SECTION_ID",
"user": {
"uid": "VALUE_FROM__slid_server_OR__slid",
"ses": "VALUE_FROM__slsession"
},
"ctx": {
"type": "HOMEPAGE",
"data": [],
"location": "https://shop.ru/"
},
"device": {
"ua": "Mozilla/5.0",
"ip": "54.100.200.255"
},
"options": {
"isImplicitPageview": true,
"isBuildEngagementUrl": true
},
"data": [
{
"selector": "homepage_cta_test"
}
]
}
Для ручного рендера обычно включайте options.isBuildEngagementUrl: true. Тогда Gateway вернёт готовые tracking URL:
content.events[].urls[]- для tracking контентного блока;products.slots[].events[].urls[]- для tracking отдельных товарных карточек.
Эти URL нужно вызвать в момент показа, видимого показа, клика или другого действия, которое описано в ответе кампании.
Обработка ошибок
Для server-side запроса задайте короткий timeout. Если API не ответил вовремя или вернул ошибку, рендерьте безопасный fallback: базовый баннер, стандартный CTA, обычную выдачу товаров или другой контент по умолчанию. Tracking отправляйте только для реально показанной вариации.