# SDK Gravity Field (Android)

Gravity Field SDK — это лёгкий клиент для интеграции мобильных приложений (iOS / Android) с платформой персонализации и A/B-тестирования. Он позволяет запускать кампании без необходимости реализовывать собственную логику таргетинга, выбора и аналитики.

SDK работает по принципу "тонкого клиента": все решения принимает сервер (бекенд Gravity Field), а SDK:

  • передаёт контекст текущего экрана,
  • получает кампании и их содержимое в виде JSON или встроенных шаблонов,
  • активирует показ inline и in-app кампаний
  • трекает взаимодействия пользователя (просмотры, клики, покупки и т.д.),
  • и помогает фиксировать конверсии для аналитики и обучения моделей.

📦 Эта документация предназначена для мобильных разработчиков и инженеров, которые интегрируют SDK в приложение.

Gravity Field SDK

# Добавление библиотеки в проект

  1. Добавить в свой проект модуль gravity_sdk
  2. После добавления модуля в файле build.gradle.kts добавить зависимость:
dependencies {
	implementation(project(":gravity_sdk"))
}
  1. Добавьте импорт:
import ai.gravityfield.gravity_sdk.GravitySDK

# Инициализация SDK

Для работы SDK необходимо провести базовую инициализацию, которая включает регистрацию секции и авторизацию через API-ключ. Дальнейшее взаимодействие с SDK осуществлячется через GravitySDK.instance

# GravitySDK.initialize(...)

Метод принимает параметры:

Параметр Описание
context Android контекст
apiKey API-ключ (выдаётся системой)
section ID секции (выдаётся системой)
productViewBuilder Билдер карточек продуктов (Context, Slot) -> View, позволяет сконфигурировать view карточки продукта на стороне приложения
productFilter Фильтр продуктов (Slot) -> Boolean возвращает Boolean значение должен ли быть отображен данный slot, позволяет фильтровать продукты в списках на стороне приложения
gravityEventCallback Глобальный callback всех событий взаимодействия с кампаниями и контентом в SDK

Вызывается при:

  • загрузке кампаний (ContentLoadEvent)
  • показе(закрытии) контента (ContentImpressionEvent, ContentVisibleImpressionEvent, ContentCloseEvent)
  • пользовательских действиях (CopyEvent, CancelEvent, FollowUrlEvent и др.)
  • взаимодействии с товарными слотами (ProductImpressionEvent)

Вот полный список типов, которые могут прилетать в gravityEventCallback:

Тип события Класс Когда вызывается
Загрузка кампании ContentLoadEvent после вызова метода SDK trackView / triggerEvent система проверяет наличие кампании на данное событие и в случае наличия происходит загрузка кампании
Отрисовка контента ContentImpressionEvent когда соответствующая кампании view создана (но при этом может находиться за областью видимости экрана)
Попадание в экран ContentVisibleImpressionEvet когда контент стал видимым для пользователя (находится в зоне видимости на экране)
Закрытие контента ContentCloseEvent по нажатию на кнопку, действием которой является закрытие контента, либо при нажатии вне области таких ui элементов как Popup, BottomSheet (что так же приводит к их закрытию)
Копирование кода CopyEvent при нажатии на кнопку, действием которой является копирование, данное действие обрабатывает SDK (происходит копирование кода в clipboard)
Отмена CancelEvent при нажатии на кнопку, действием которой является отмена, данное действие обрабатывает SDK (происходит закрытие контента)
Навигация по ссылке FollowUrlEvent при нажатии на кнопку, действием которой является переход по URL, данное действие необходимо обработать на стороне приложения при получении этого event в callback
Навигация по диплинку FollowDeeplinkEvent при нажатии на кнопку, действием которой является переход по deeplink, данное действие необходимо обработать на стороне приложения при получении этого event в callback
Запрос на пуш-уведомления RequestPushEvent при нажатии на кнопку, действием которой является запрос на включение push-уведомлений, данное действие обрабатывает SDK (происходит переход в настройки push-уведомлений приложения в системе Android)
Взаимодействие с товарами ProductImpressionEvent показ конкретного товара в списке товаров

Используйте, если вам нужно:

  • Вручную показывать или скрывать кампании, тип которых не обрабатывает SDK (json кампании)
  • Обрабатывать действия пользователя, которые не обрабатывает SDK (FollowUrlEvent и др.)
  • Отслеживать активность (например, для аналитики или логирования)

# GravitySDK.instance.setOptions(...)

Метод позволяет настроить дополнительные параметры, которые влияют на то, как сервер возвращает кампании и как SDK их обрабатывает.

fun setOptions(
    options: Options?,
    contentSettings: ContentSettings?,
    proxyUrl: String?
)

data class Options(
    val isReturnCounter: Boolean = false,
    val isReturnUserInfo: Boolean = false,
    val isReturnAnalyticsMetadata: Boolean = false,
    val isImplicitPageview: Boolean = false,
    val isImplicitImpression: Boolean = true,
)

data class ContentSettings(
    val skusOnly: Boolean = false,
    val fields: List<String>? = null
)

options

Параметр Тип По умолчанию Описание
isReturnCounter Boolean false Вернуть сработавшие условия и сегменты пользователя
isReturnUserInfo Boolean false Вернуть объект detailedUser с дополнительной информацией о пользователе
isReturnAnalyticsMetadata Boolean false Вернуть аналитику: ID и названия сущностей (кампаний, стратегий, плейсментов)
isImplicitPageview Boolean false Если включено true, SDK автоматически зарегистрирует просмотр страницы при вызове getCampaign(...), без отдельного вызова trackView(...). Это полезно, если вы хотите запрашивать кампании и одновременно зафиксировать pageview.
isImplicitImpression Boolean true Если включено true, SDK сам отправит событие показа контента IMP при получении кампании. Если вы рендерите UI самостоятельно, установите false, чтобы зафиксировать отображение вручную через trackIMP() и т.д.

contentSettings настройки товарного контента

Параметр Тип По умолчанию Описание
maxProducts Int — (на стороне сервера) Максимальное количество возвращаемых товаров (от 1 до 50)
fields List null Явный список полей, которые нужно вернуть для товаров, например: ["name", "price", "image"]
skusOnly Boolean false Вернуть только SKU без описаний, изображений и цен (для экономии трафика)

Таким образом, configureCampaignOptions позволяет заранее определить структуру и поведение всех кампаний, которые будут получены через SDK

proxyUrl

Базовый URL вашего backend-прокси, через который SDK будет отправлять все запросы. Если не задан — используется endpoint Gravity Field.

# Идентификация пользователей

Идентификация пользователя — фундамент для персонализации, аналитики и построения омниканальных профилей в Gravity Field.

Без корректной идентификации невозможно:

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

# Варианты идентификации

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

Gravity Field UID (автоматическая идентификация)

Когда использовать:

  • Когда нет собственного механизма учёта пользователей и сессий

Как работает:

  • При первом запросе к Gravity Field (например, trackView(...)), если нет сохранённых идентификаторов, Gravity Field автоматически создаёт уникальные идентификаторы:
    • uid — уникальный идентификатор пользователя, автоматически сгенерированный Gravity Field
    • ses — ID сессии, автоматически сгенерированный Gravity Field
  • Эти значения возвращаются в ответе и сохраняются.
  • SDK будет использовать их во всех следующих запросах.
  • Сессия живёт 30 минут и продлевается при активности пользователя.

После авторизации:

  • Чтобы связать анонимный профиль с авторизованным, вызовите событие LoginEvent через triggerEvent(...).
  • Gravity Field объединит поведение до и после логина.

Custom user id (идентификация через ID приложения)

Когда использовать:

  • Если у пользователя в приложении есть собственный ID и логика управления сессиями.

Как работает:

  • Разработчик вызывает setUser(...).
    • userId — ваш собственный ID пользователя (custom ID);
    • sessionId — ID текущей сессии.
  • SDK использует эти значения в каждом запросе.

# GravitySDK.instance.**setUser(...)**

Позволяет явно установить параметры пользователя и сессии, которые будут автоматически включаться во все запросы SDK к API (/visit, /event, /choose, /engagement).

// Собственный ID пользователя и сессия
fun setUser(userId: String, sessionId: String)

# Как SDK работает с идентификаторами

SDK автоматически управляет идентификаторами пользователя и сессии, опираясь на то, что уже сохранено локально. Используется следующая логика:

  1. Если вызван setUser(...) — SDK использует переданные userId и sessionId (режим: custom user ID).
  2. Если setUser(...) не вызывался, но уже есть uid и ses — SDK использует их (режим: Gravity Field UID).
  3. Если ни один ID не сохранён — SDK отправляет запрос без идентификаторов. Gravity Field создаёт uid и ses, SDK сохраняет их и использует в дальнейшем.

💡 Если вы передаёте userId, вы обязаны также передать sessionId. SDK не может создать sessionId автоматически в этом режиме.

# Передача контекста

Gravity Field принимает решение о показе персонализированного контента на основе контекста страницы, который с помощью метода trackView(...).

Контекст страницы позволяет Gravity Field понять:

  • Где сейчас находится пользователь в приложении
  • Какие товары или категории он просматривает
  • В каком регионе или в каких условиях пользователь находится

# GravitySDK.instance.trackView(...)

Метод отправляет событие /visit, фиксируя просмотр экрана пользователем. Он формирует тело запроса на основе параметров, переданных клиентом, и автоматически добавленных данных от SDK.

fun trackView(
    pageContext: PageContext,
    activityContext: Context
)

| Поле | Тип | Описание | | pageContext | PageContext | Контекст страницы, на которой произошло событие. | | activityContext | Context | Android activity context |

# PageContext

Для унификации передачи контекста страницы во все методы SDK предлагается использовать отдельную модель:

data class PageContext(val type: ContextType)

💡 Типы контекста и соответсвующие для них data описаны здесь: Page context

Поле Тип Описание
type String Тип страницы (HOMEPAGE, PRODUCT, CART, CATEGORY, SEARCH, OTHER)
data List<String> Идентификаторы сущностей (например, SKU, ID категории, ключевое слово поиска)
location String Полный URL или ID текущего экрана в приложении. передается разработчиком приложения
lng String? Код региона или склада, связанный с пользователем или товаром
referrer String? Источник перехода (если есть). Используется для аналитики и определения канала трафика.
utm Map<String, String>? UTM-метки маркетинговой кампании
attributes Map<String, String>? Дополнительные параметры, например сегмент пользователя

# Как активируются кампании на основе контекста страницы

Когда приложение отправляет событие просмотра страницы через trackView(...), SDK передаёт информацию о текущем контексте в Gravity Field. На основе этой информации кампании могут активироваться:

  • Если в Gravity Field настроена кампания, которая должна запускаться на определённый pageView (например, просмотр корзины, карточки товара и т.д.),
  • И условия кампании совпадают с отправленным контекстом страницы (type, data, location и другие параметры),
  • Тогда Gravity Field выберет подходящую кампанию и формирует её содержимое (например, баннер, всплывающее окно или блок рекомендаций), SDK получает готовый контент и отображает в приложение

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

Трекинг событий позволяет отправлять информацию о действиях пользователя — таких как покупка, добавление товара в корзину, авторизация и другие события, происходит происходит с помощью метода triggerEvent(...). Эти данные используются Gravity Field для аналитики, построения сегментов и запуска кампаний, активируемых по событиям.

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

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

Платформа поддерживает как системные (предопределённые) события, так и произвольные пользовательские события.

  • Системные события — это события с зафиксированными type, которые платформа распознаёт и может использовать для активации кампаний или анализа (например, purchase, add_to_cart, login).
  • Пользовательские события — разработчик может отправлять любые события с кастомным type. Такие события будут использоваться для аналитики и построения собственных отчётов или логики в Gravity Field.

# GravitySDK.instance.triggerEvent(...)

fun triggerEvent(
    events: List<TriggerEvent>,
    pageContext: PageContext,
    activityContext: Context
)
Параметр Тип Описание
events List<TrackedEvent> Список событий, которые нужно зафиксировать.
pageContext PageContext Контекст страницы, на которой произошло событие.
activityContext Context Android activity context

Пример:

GravitySDK.instance.triggerEvent(
    events = listOf(
        AddToCartEvent(
            value = 10.0,
            currency = "currency_code",
            productId = "product_id",
            quantity = 2,
            cart = emptyList()
        ),
        CustomEvent(
            type = "custom_type",
            name = "custom_event_name",
        )
    ),
    pageContext = PageContext(type = ContextType.CART),
    context = context
)
       

# TriggerEvent

💡 Соответствие типов эвентов и параметров: https://docs.gravityfield.ai/integration/web_integration/events/

Поле Тип Описание
type string Системное имя события (например, "purchase", "add_to_cart", "login").
name string Человеко-читаемое название события. Используется для аналитики.
currency string Валюта события (например, "USD"). Если не указано — используется валюта секции.
value number Суммарная стоимость добавленных товаров.
quantity integer Количество товаров, участвовавших в событии.
productId string SKU товара, если событие связано с конкретным продуктом.
cart array Массив объектов CartItem, представляющий содержимое корзины.
eventTime string Время события (ISO 8601). Полезно при отправке задним числом.
customProps object Кастомные поля события.
uniqueTransactionId string Уникальный ID события. Защищает от повторной отправки (например, при покупке).
cuid string Внешний идентификатор пользователя (например, customer_id).
cuidType string Тип поля cuid.
hashedEmail string SHA256-хеш email пользователя.

# CartItem

Поле Тип Описание
productId string Идентификатор товара (SKU)
quantity integer Количество единиц товара
itemPrice number Цена за единицу товара

# Как активируются кампании по событию

Когда приложение отправляет событие через triggerEvent(...), SDK передаёт информацию о событии и текущем контексте в Gravity Field. На основе этой информации кампании могут активироваться:

  • Если в Gravity Field настроена кампания, которая должна запускаться на определённый TriggerEvent (например, добавление в корзину, покупку и т.д.),
  • И условия кампании совпадают с отправленным контекстом страницы (type, data, location и другие параметры),
  • Тогда Gravity Field выберет подходящую кампанию и формирует её содержимое (например, баннер, всплывающее окно или блок рекомендаций), SDK получает готовый контент и отображает в приложение

# Активация кампаний

# Inline-блоки (встраиваемые кампании в UI)

Кампания встраивается в существующую структуру экрана приложения — но только если условия показа, заданные на платформе Gravity Field, выполнены.

GravityInlineView

SDK запрашивает кампанию по selector, передаёт контекст текущей страницы, и если сервер вернёт релевантный контент — он будет отображён в заданном UI-элементе.

<ai.gravityfield.gravity_sdk.ui.GravityInlineView
		android:layout_width="match_parent"
		android:layout_height="250dp"
		app:selector="selector"
</androidx.constraintlayout.widget.ConstraintLayout>
Параметр Тип Описание
selector String Уникальный идентификатор кампании, используемый для запроса контента
width layout_width Начальная ширина должна быть определена
height layout_width Начальная высота должна быть определена
placeholderId String ID места в интерфейсе, куда вставляется виджет, в мультивиджет кампании

selector задается в настройках кампании, в личном кабинете Gravity Field.

placeholderId задается в настройках вариации кампании, в личном кабинете Gravity Field

💡 Если условия показа не выполнены (например, пользователь не входит в целевую группу), блок не будет отрисован.

📌 Подходит для: баннеров, товарных рекомендаций, УТП блоков.

# Кастомизация внешнего вида товарных рекомендаций

Кастомизация внешнего вида карточки товаров в ленте рекоммендаций осуществляется с помошью productViewBuilder, который передается при инициализации SDK, билдер должен возвращать Android view, для которой LayoutParams имеют фиксированные высоту и ширину. В случае отображения кампании с лентой рекоммендаций продуктов SDK отображает эту view для карточки продукта.

# In-app кампании (всплывающие окна, модальные экраны)

Кампания отображается поверх интерфейса — это может быть snackbar, bottom sheet, или модальное окно. Такие кампании активируются автоматически, если условия показа, настроенные в платформе Gravity Field, выполнены.

Когда и как происходит активация:

  • SDK отправляет запрос через trackView(...) или triggerEvent(...) с текущим контекстом страницы и события
  • Сервер Gravity Field анализирует условия:
    • Целевая страница (pageContext.data)
    • Условия сегментации (аудитория, сегменты, сессия, гео и т.д.)
    • Частота показов, лимиты, включённость в эксперимент
  • Если кампания активна и все условия выполнены — сервер возвращает кампанию
  • SDK автоматически отображает in-app сообщение через встроенные шаблоны

📌 Подходит для:**

  • Всплывающих предложений (например, «вернитесь в корзину»)
  • Промо после события (purchase, login, logout)
  • Модальных сообщений при входе на экран
  • A/B-тестов с воронками входа / выхода

# Отображение JSON-кампаний на стороне приложения

В отличие от in-app и inline кампаний, которые SDK может отрисовать автоматически (например, баннеры, модалки, ленты товаров по шаблонам), JSON-кампании не имеют визуального шаблона. Gravity Field возвращает только структурированные данные, и отображение полностью реализуется на стороне приложения.

Есть два способа получить кампанию:

Вариант 1: Через getCampaign(...)

Метод getCampaign(...) используется, когда кампания нужна по конкретному selector или groupSelector.

fun getCampaign: List<Campaign>(
    selector: String? = null,
    groupSelector: String? = null,
    pageContext: PageContext? = null,
)
Параметр Тип Описание
selector String? Уникальный идентификатор кампании (например, "checkout_banner")
groupSelector String? Групповой селектор, объединяющий несколько кампаний
pageContext PageContext? Контекст страницы

📌 Подходит для:

  • Получения кампаний заранее (например, до отрисовки экрана)
  • Встраивания кампаний в кастомные блоки
  • Полного управления кампанией на стороне приложения (для данной кампании SDK вызовет только gravityEventCallback с событием ContentLoadEvent сразу после загрузки, дальнейшая отрисовка кампании и взаимодействие с ней на стороне приложения)

Вариант 2: Через gravityEvetCallback после события или просмотра экрана

В случае если SDK загружает кампанию с типом JSON SDK не обрабатывает ее на своей стороне, а вызывает gravityEventCallback с соботием ContentLoadEvent

GravityFieldSdk.initialize(
  sectionId: 'abc123',
  apiKey: 'gf_xyz...',
  actionsCallback: (event) {
    if (event.type == 'LoadEvent' && event.selector == 'custom_popup') {
      // кастомная логика показа кампании
      showCustomPopup(event.campaign);
    }
  },
);

📌 Такой подход позволяет:

  • Получать кампании в момент события или просмотра экрана
  • Гибко управлять отображением кампаний вручную
  • Тестировать варианты крупных блоков в приложении, например, новый дизайн карточки товара

# Campaign

Объект Campaign представляет собой активированную персонализированную кампанию, полученную от сервера Gravity Field через getCampaign(...), trackView(...) или triggerEvent(...)

data class Campaign(
    val selector: String,
    val payload: List<CampaignVariation>
)

data class CampaignVariation(
    val campaignId: String,
    val experienceId: String,
    val variationId: String,
    val decisionId: String,
    val contents: List<CampaignContent>
)
Поле Тип Описание
selector String Уникальный селектор кампании
groupSelector String? Общий селектор группы кампаний, например несколько виджетов на одной странице
decisionId String Уникальный ID назначения кампании этому пользователю
contents List<CampaignContent> Массив контентных элементов кампании (один или несколько)

Почему contents — это список

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

  • Баннер + товарная лента
  • Модальное окно + напоминание
  • Несколько последовательных шагов (например, туториал)

Каждый элемент описывается через CampaignContent.

# CampaignContent

data class CampaignContent(
    val contentId: String,
    val templateId: String,
    val deliveryMethod: DeliveryMethod,
    val contentType: String,
    val variables: Variables,
    val products: Products?,
    val events: List<Event>
)
Поле Тип Описание
contentId String Уникальный ID элемента внутри кампании
contentType String Тип контента: products, json
custom JSONObject JSON с UI-контентом: текст, стили, кнопки, действия
products Products? Опциональный блок с товарами
deliveryMethod String Способ доставки контента: bottom-sheet, snackbar, и тд
placeholderId String ID места в интерфейсе, куда вставляется виджет, в мультивиджет кампании
templateId String Идентификатор шаблона

# Products

data class Products(
    val strategyId: String,
    val name: String,
    val fallback: Boolean,
    val slots: List<Slot>
)
Поле Тип Описание
strategyId String ID стратегии рекомендаций, сгенерированной на сервере
name String? Название стратегии (например, "Похожие товары")
fallback Boolean Признак использования резервного алгоритма
slots List<ProductSlot> Список товарных позиций

# Slot

data class Slot(
    val item: Item,
    val fallback: Boolean,
    val strId: Int,
    val slotId: String,
)
Поле Тип Описание
item Item Полная информация о товаре (sku, цена, имя и т.д.)
fallback Boolean Был ли этот товар вставлен как fallback (если стратегия ничего не вернула)
strId Int Порядковый ID в стратегии (может использоваться для сортировки)
slotId String Уникальный ID товарного слота

# Трекинг взаимодействий (engagement) с кампанией

Engagement-события для кампаний позволяют Gravity Field анализировать поведение пользователя в деталях:

  • Какой контент был показан и как он повлиял на поведение
  • Какая вариация кампании эффективнее: какой баннер чаще просматривают, на какой товар чаще кликают, что влияет на покупку
  • Понимание того, какие элементы UI реально видны (WRIMP), позволяет фильтровать «слепые зоны» и улучшать UX
  • Фиксация кликов и показов даёт системе обратную связь: что работает, а что нет

in-app и inline(баннерных) кампании — SDK автоматически отслеживает показ, клики и видимость блоков.

json кампании — SDK не знает, когда блок был показан, видим или кликнут. Поэтому вы должны вручную вызывать трекинг нужных событий c помощью методов sendContentEngagement и sendProductEngagement.

inline(товарные) кампании — SDK автоматически отслеживает показ, так как карточки отрисовывает приложение через productWidgetBuilder Поэтому вы должны вручную вызывать трекинг кликов по товарам: sendProductEngagement(ProductClickEngagement(slot)

SDK отдаёт готовые методы для их трекинга — вам не нужно вручную формировать запросы.

`fun sendProductEngagement(engagement: ProductEngagement)`

class ProductClickEngagement(
    slot: Slot,
    content: CampaignContent,
    campaign: Campaign
)

class ProductVisibleImpressionEngagement(
    slot: Slot,
    content: CampaignContent,
    campaign: Campaign
)

fun sendContentEngagement(engagement: ContentEngagement)

class ProductClickEngagement(
    slot: Slot,
    content: CampaignContent,
    campaign: Campaign
)

class ProductVisibleImpressionEngagement(
    slot: Slot,
    content: CampaignContent,
    campaign: Campaign
)

🔗 Все эти события привязаны к decisionId кампании и, при необходимости, к contentId и slotId товара.

Пример: отображение и трекинг УТП-блока

Шаг 1: Получение кампании

val campaigns = GravitySDK.instance.getCampaign(
    selector = "checkout_usp_banner",
    pageContext = PageContext.CART
)
campaigns.firstOrNull()?.let { campaign ->
    val content = campaign.contents.firstOrNull()
    if (content != null) {
        renderUspBlock(content)
    }
}

Пример JSON-контента кампании

{
  "title": "Бесплатная доставка сегодня!",
  "text": "Оформите заказ до 23:59 и получите бесплатную доставку.",
  "button": {
    "text": "Оформить заказ",
    "action": "navigate",
    "target": "app://checkout"
  }
}

Шаг 2: Рендер блока

fun renderUspBlock(content: CampaignContent) {
    val json = content.custom

    val title = json.optString("title")
    val text = json.optString("text")
    val buttonText = json.optJSONObject("button")?.optString("text")
    val target = json.optJSONObject("button")?.optString("target")

    uspTitleView.text = title
    uspDescriptionView.text = text
    uspButton.text = buttonText

    // Трекинг показа
    GravitySDK.instance.sendContentEngagement(ContentImpressionEngagement(content))

    // Отложенный трекинг видимости (> 1с на экране)
    if (isVisibleForMoreThan1Second(uspBlock)) {
        GravitySDK.instance.sendProductEngagement(ProductVisibleImpressionEngagement(content))
    }

    // Обработка нажатия
    uspButton.setOnClickListener {
        GravitySDK.instance.sendProductEngagement(ProductClickEngagement(content))
        navigateTo(target)
    }
}

Что в итоге делает разработчик:

  • Получает кампанию по selector
  • Отрисовывает JSON как UI
  • Вызывает engagement-трекинг вручную

# Все события gravityEventCallback

sealed class TrackingEvent(val campaign: Campaign)

class ContentLoadEvent(
    val content: CampaignContent, campaign: Campaign
) : TrackingEvent(campaign)

class ContentImpressionEvent(
    val content: CampaignContent, campaign: Campaign
) : TrackingEvent(campaign)

class ContentVisibleImpressionEvent(
    val content: CampaignContent, campaign: Campaign
) : TrackingEvent(campaign)

class ContentCloseEvent(
    val content: CampaignContent, campaign: Campaign
) : TrackingEvent(campaign)

class CopyEvent(
    val copiedValue: String, val content: CampaignContent, campaign: Campaign
) : TrackingEvent(campaign)

class CancelEvent(
    val content: CampaignContent, campaign: Campaign
) : TrackingEvent(campaign)

class FollowUrlEvent(
    val url: String, val content: CampaignContent, campaign: Campaign
) : TrackingEvent(campaign)

class FollowDeeplinkEvent(
    val deeplink: String, val content: CampaignContent, campaign: Campaign
) : TrackingEvent(campaign)

class RequestPushEvent(
    val content: CampaignContent, campaign: Campaign
) : TrackingEvent(campaign)

class ProductImpressionEvent(
    val slot: Slot, val content: CampaignContent, campaign: Campaign
) : TrackingEvent(campaign)