# Контекст экранов и события Android

## PageContext

`PageContext` описывает, где находится пользователь в приложении и в каком бизнес-контексте выполняется запрос.

Этот объект используется во всех основных интеграционных вызовах:

- [`trackView(...)`](#trackview) для передачи просмотров экранов;
- [`triggerEvent(...)`](#triggerevent) для передачи пользовательских действий;
- [`getContentBySelector(...)`](./custom_ui.md#getcontentbyselector) для ручного получения контента.

Корректное заполнение `PageContext` влияет и на аналитику, и на подбор контента, и на активацию кампаний.

### Поля PageContext

[Конструктор и типы полей](./api_reference.md#pagecontext).

| Поле | Обязательность | Описание |
| :--- | :--- | :--- |
| `type` | Обязательно | Тип экрана. |
| `data` | Обязательно | Контекстные данные для выбранного типа экрана. |
| `location` | Обязательно | Уникальный идентификатор экрана или deeplink. |
| `lng` | Опционально | Региональный код для мультирегиональности. |
| `pageNumber` | Опционально | Номер страницы в пагинации. |
| `referrer` | Опционально | Источник перехода. |
| `utm` | Опционально | UTM-метки. |
| `attributes` | Опционально | Дополнительные атрибуты таргетинга. |

Бизнес-логика заполнения `PageContext` соответствует [Page context](/Integration/web_integration/page_context.md).

Рекомендуемая схема:

- `HOMEPAGE`: `data = emptyList()`.
- `PRODUCT`: в `data` передается SKU товара ровно как в товарном фиде, без нормализации и с тем же регистром.
- `CART`: в `data` передаются SKU всех товаров, находящихся в корзине, ровно как в товарном фиде, без нормализации и с тем же регистром.
- `CATEGORY`: в `data` передается полная иерархия категорий от самой широкой до самой узкой ровно как в товарном фиде, без нормализации и с тем же регистром.
- `SEARCH`: в `data` передается поисковый запрос одной строкой. Для пустого поиска передается пустой список.
- `OTHER`: используется только для экранов, которые не подходят под остальные типы, например для статических страниц или категорий, не включенных в товарный фид.

Для любых значений в `PageContext`, которые должны матчиться с товарным фидом, действует единое правило: передавайте их идентично фиду. Нельзя менять написание, переименовывать значения или приводить их к upper/lower case.

`lng` используется в первую очередь для мультирегиональности. Это позволяет отдавать пользователю корректные региональные данные по товарам: цены, доступность и остатки.

Например, если пользователь находится в Новосибирске, значение `lng` может использоваться для того, чтобы в рекомендациях участвовали только товары, реально доступные для Новосибирска.

Важно:

- значения `lng` в контексте и в товарном фиде должны совпадать полностью, включая регистр;
- `lng`, как и любые другие feed-derived значения, нужно передавать без преобразования к upper/lower case;
- `lng` нужно передавать только если проект использует региональные варианты данных в фиде.

`utm` и `attributes` технически не обязательны. Передавайте их, если эти поля используются в правилах таргетинга или аналитике вашего проекта.

Дополнительно:

- SDK автоматически дополняет `attributes` служебными значениями `app_version`, `sdk_version` и `app_platform` (`android`); при совпадении ключей служебное значение заменяет переданное приложением;
- `sdk_version` берётся из строкового ресурса AAR, для `1.0.4` это `"1.0.4"`;
- `pageNumber`, `referrer` и `utm` сохраняются при сборке запросов;
- блок `device` формируется самим SDK, вручную его заполнять не нужно.

Настройка кампаний по этим значениям описана в разделе [Таргетинг SDK-кампаний по платформе и версиям](/personalization/Campaigns/targeting_schedule.md#таргетинг-sdk-кампаний-по-платформе-и-версиям).

См. также:

- [`trackView(...)`](#trackview)
- [`triggerEvent(...)`](#triggerevent)
- [`getContentBySelector(...)`](./custom_ui.md#getcontentbyselector)

## Отслеживание просмотров экранов

### `trackView(...)`

Метод отправляет событие просмотра экрана. В Android SDK этот вызов асинхронный, но сам метод не является `suspend`.

Для `trackView(...)` требуется корректно заполненный [`PageContext`](#pagecontext).

Пример:

```kotlin
GravitySDK.instance.trackView(
    pageContext = PageContext(
        type = ContextType.PRODUCT,
        data = listOf("product-sku-123"),
        location = "app://product/123",
    ),
    activityContext = this,
)
```

`trackView(...)` выполняет две задачи:

- передает в Gravity Field информацию о просмотре экрана;
- может инициировать загрузку и показ кампании, если для этого контекста настроен соответствующий сценарий.

Если для переданного контекста настроена in-app-кампания, SDK может сразу после запроса загрузить и показать ее.

## Трекинг событий

События описывают действия пользователя: покупку, добавление в корзину, авторизацию и другие сценарии, которые должны попадать в аналитику или запускать кампании.

Бизнес-логика заполнения событий соответствует [Настройке передачи событий](/Integration/web_integration/events.md), а Android SDK предоставляет типы и методы для их отправки.

Для e-commerce сценариев события `PurchaseEvent` и `AddToCartEvent` обязательны. Дополнительно рекомендуется внедрять остальные релевантные преднастроенные события, которые поддерживаются вашим сценарием интеграции.

Для всех полей событий, которые должны матчиться с товарным фидом, действует то же правило, что и для `PageContext`: передавайте значения идентично фиду. Это относится к `productId`, `cart[*].productId` и другим feed-derived значениям. Регистр является частью значения.

### `triggerEvent(...)`

В Android SDK этот вызов асинхронный, но сам метод не является `suspend`.

Для `triggerEvent(...)` требуется корректно заполненный [`PageContext`](#pagecontext).

`triggerEvent(...)` выполняет две задачи:

- передает в Gravity Field пользовательские действия для аналитики, сегментации и построения профиля;
- может инициировать загрузку и показ кампании, если событие используется как триггер в настройках платформы.

Пример:

```kotlin
GravitySDK.instance.triggerEvent(
    events = listOf(
        AddToCartEvent(
            value = 1500.0,
            productId = "sku-abc-1",
            quantity = 1,
            currency = "RUB",
        )
    ),
    pageContext = PageContext(
        type = ContextType.PRODUCT,
        data = listOf("sku-abc-1"),
        location = "app://product/sku-abc-1",
    ),
    activityContext = this,
)
```

### Покупка (`PurchaseEvent`)

Отправляется после успешного завершения заказа.

```kotlin
val purchaseEvent = PurchaseEvent(
    uniqueTransactionId = "ORDER-12345",
    value = 2550.75,
    currency = "RUB",
    cart = listOf(
        CartItem(productId = "sku-123", quantity = 1, itemPrice = 100.50),
        CartItem(productId = "sku-456", quantity = 2, itemPrice = 1225.125),
    ),
)
```

Правила заполнения:

- `uniqueTransactionId` должен быть уникальным для каждой покупки.
- `value` - полная сумма заказа.
- `currency` опциональна, но обязательна для мультивалютных проектов.
- `cart` содержит фактический состав заказа.
- каждый `cart[*].productId` должен совпадать со SKU в товарном фиде полностью, включая регистр.
- товары в `cart` рекомендуется передавать в порядке добавления: от самых старых к самым новым.
- каждый `CartItem.itemPrice` - стоимость одной единицы товара после применения скидок.

### Добавление в корзину (`AddToCartEvent`)

Отправляйте событие в момент фактического добавления товара в корзину.

```kotlin
val addToCartEvent = AddToCartEvent(
    value = 1500.0,
    productId = "sku-abc-1",
    quantity = 1,
    currency = "RUB",
)
```

Правила заполнения:

- `value` - сумма, добавляемая в корзину этим действием. Если добавляется несколько единиц одного товара, передается `quantity * itemPrice`.
- `quantity` - количество единиц, добавленных именно этим действием, а не итоговое количество товара в корзине.
- `productId` должен совпадать со SKU в товарном фиде полностью, включая регистр.
- `currency` опциональна, но обязательна для мультивалютных проектов.
- `cart`, если передается, должен содержать актуальное состояние корзины, включая только что добавленный товар. Все `cart[*].productId` должны совпадать со SKU в товарном фиде полностью, включая регистр. Товары рекомендуется передавать в порядке добавления: от самых старых к самым новым.

### Удаление из корзины (`RemoveFromCartEvent`) и синхронизация корзины (`SyncCartEvent`)

- `RemoveFromCartEvent` отправляйте в момент удаления товара из корзины или уменьшения количества.
- `value` в `RemoveFromCartEvent` - сумма удаляемых единиц товара.
- `quantity` в `RemoveFromCartEvent` - количество единиц, удаленных этим действием.
- `productId` в `RemoveFromCartEvent` должен совпадать со SKU в товарном фиде полностью, включая регистр.
- `SyncCartEvent` используйте, когда нужно передать актуальное состояние корзины целиком: например, при пакетном изменении корзины, очистке корзины, объединении корзин после логина или серверном обновлении состава корзины.
- в Android SDK `SyncCartEvent` также требует `value`, поэтому передавайте общую стоимость актуального состава корзины.
- `cart` в `SyncCartEvent` должен содержать полное текущее состояние корзины. Все `cart[*].productId` должны совпадать со SKU в товарном фиде полностью, включая регистр.
- товары в `cart` для `RemoveFromCartEvent` и `SyncCartEvent` рекомендуется передавать в порядке добавления: от самых старых к самым новым.
- `currency` для `RemoveFromCartEvent` и `SyncCartEvent` опциональна, но обязательна для мультивалютных проектов.

### Авторизация

Формирование CUID и пример LoginEvent — в [Идентификации пользователя](./identity.md).

### Добавление в избранное (`AddToWishlistEvent`)

```kotlin
val addToWishlistEvent = AddToWishlistEvent(
    value = 1500.0,
    productId = "sku-abc-1",
)
```

`productId` должен совпадать со SKU в товарном фиде полностью, включая регистр.

### Кастомное событие (`CustomEvent`)

```kotlin
val customEvent = CustomEvent(
    type = "survey-completed-v1",
    name = "Survey completed",
    customProps = mapOf(
        "surveyId" to "summer-2025-feedback",
        "rating" to "5",
    ),
)
```

Параметры всех типов событий собраны в [справочнике API](./api_reference.md#события-triggerevent). При ошибке сети SDK не сохраняет событие в очередь: см. [Сеть и жизненный цикл](./network.md).
