Для рекламной платформы важно передавать не только факт запроса плейсмента, но и взаимодействия пользователя с рекламным местом, креативом и товарами. Эти события используются для расчёта показов, видимых показов, CTR, эффективности товарных слотов и последующей оптимизации кампаний.

В API V2 tracking URL рекомендуется брать из ответа [`/choose`](./choose.md). Для этого передайте `options.isBuildEngagementUrl: true`.

![](/images/retail_media/engagement.avif)

---

## engagement: передача взаимодействий с рекламой

!!!contrast API reference
[:icon-terminal: GET /engagement](https://openapi-v2.gravityfield.ai/engagement-14151113e0)
!!!

### Порядок действий после запроса рекламы

1. Когда пользователь открывает страницу или экран с рекламным плейсментом, вызовите [`/choose`](./choose.md), передав `placementId`.
2. Если вы передали `options.isImplicitImpression: false`, обработайте `variables.onImpression`, если этот handler есть в ответе. Обычно ему соответствует **Ad Impression (AIMP)**.
3. Когда рекламное место попало в область видимости как минимум на `50%` в течение `1` секунды, обработайте `variables.onVisibleImpression`, если этот handler есть в ответе. Обычно ему соответствует **Visible Impression (WRIMP)**.
4. Когда пользователь кликает по рекламному блоку, баннеру или CTA, обработайте `variables.onClick`, если этот handler есть в ответе. Обычно ему соответствует **Ad Click (ADCLICK)**. У креатива может не быть кликовой ссылки, тогда click-handler может отсутствовать.
5. Для товарных кампаний дополнительно используйте product-level события из `products.slots[].events[]`: `visible_impression` для видимых товарных слотов и `click` для кликов по конкретному товару.

### Где брать tracking URL

Tracking URL приходят в ответе `/choose`, если включён `options.isBuildEngagementUrl`.

| Уровень | Где искать | Когда использовать |
| :--- | :--- | :--- |
| Рекламный блок | `content.events[].urls[]` | AIMP, WRIMP, ADCLICK и другие события всего рекламного юнита. |
| Товарный слот | `products.slots[].events[].urls[]` | `visible_impression` и `click` конкретного товара. |

Клиенту не нужно вручную собирать query-параметры tracking URL. Вызовите все URL из подходящего `urls[]`.

### Content-level события

Content-level события связаны с handler-ами из `variables`. Объект `variables` и любой ключ `variables.on*` опциональны: если handler отсутствует, не отправляйте соответствующее content-level событие.

Не привязывайтесь к значению `action` внутри `variables`. Используйте имя handler-а:

| Handler | Какой `content.events[].type` искать |
| :--- | :--- |
| `onImpression` | `AIMP` |
| `onVisibleImpression` | `WRIMP` |
| `onClick` | `ADCLICK` |

```json
{
  "variables": {
    "onImpression": {
      "action": "AIMP"
    },
    "onVisibleImpression": {
      "action": "WRIMP"
    },
    "onClick": {
      "action": "ADCLICK"
    }
  },
  "events": [
    {
      "type": "AIMP",
      "urls": ["https://evs-01.gravityfield.ai/v2/engagement?..."]
    },
    {
      "type": "WRIMP",
      "urls": ["https://evs-01.gravityfield.ai/v2/engagement?..."]
    },
    {
      "type": "ADCLICK",
      "urls": ["https://evs-01.gravityfield.ai/v2/engagement?..."]
    }
  ]
}
```

Принцип работы:

1. Проверьте наличие нужного handler-а в `variables`.
2. По имени handler-а выберите ожидаемый `content.events[].type`.
3. Найдите событие с таким `type` в `content.events[]`.
4. Вызовите все URL из найденного `events[].urls[]`.

Если `variables` отсутствует, нужного handler-а нет или в `content.events[]` нет подходящего `type`, ничего не отправляйте для этого content-level события.

=== Пример включения tracking URL в `/choose`:
```json
{
  "options": {
    "isBuildEngagementUrl": true
  }
}
```
===

=== Пример вызова tracking URL:
```jsx
curl --request GET
--url 'https://evs-01.gravityfield.ai/v2/engagement?eventId=EVENT_ID&type=WRIMP&sec=YOUR_SECTION_ID'
```
===

### Какие события отправлять

| Что отправлять | Когда |
| :--- | :--- |
| `variables.onImpression` -> `AIMP` | После запроса рекламного плейсмента, если `isImplicitImpression: false` и handler вернулся в ответе. |
| `variables.onVisibleImpression` -> `WRIMP` | Один раз, когда рекламный блок стал видим пользователю как минимум на `50%` в течение `1` секунды. |
| `variables.onClick` -> `ADCLICK` | Когда пользователь взаимодействует с кликабельным рекламным блоком, если handler вернулся в ответе. |
| `slot.visible_impression` | Для товарных кампаний: когда конкретная карточка товара попала в область видимости. Это не показ всего товарного виджета. |
| `slot.click` | Для товарных кампаний: когда пользователь совершил любое осмысленное действие с карточкой товара: переход на карточку товара, добавление в корзину, добавление в избранное и т.п. |

!!!
Для товарной рекламы не заменяйте product-level события из `products.slots[].events[]` только событием рекламного блока. Иначе статистика по конкретным SKU и слотам будет неполной.
!!!

### Рекомендации по отправке

- отправляйте событие видимого показа только один раз для одного фактического показа блока;
- не повторяйте impression при каждом повторном render cycle;
- при клике отправьте tracking URL и затем выполните действие интерфейса, если это не ухудшает UX;
- не блокируйте UI из-за ошибки tracking-запроса;
- сохраняйте `slotId` вместе с карточкой товара до момента клика.

### Если URL не пришли

Если в ответе `/choose` нет tracking URL, проверьте:

- передан ли `options.isBuildEngagementUrl: true`;
- возвращается ли в UI-слой исходный `events[]`, а не преобразованная модель без tracking URL;
- настроены ли рекламный плейсмент, кампания и формат креатива;
- не отправляете ли вы product-level события по баннерной кампании без товарных слотов.

### Лимиты по количеству запросов

[!ref icon=":icon-tab:"](../../rate_limits.md)
