# SDK Gravity Field (Android)

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

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

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

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

Репозиторий Gravity Field SDK для Android

# 1. Установка

  1. Добавьте модуль gravity_sdk в ваш проект. Скопируйте модуль gravity_sdk из репозитория в корневую директорию вашего проекта.

  2. Подключите модуль в файле settings.gradle.kts вашего проекта:

    include(":gravity_sdk")
  3. Добавьте зависимость в файле build.gradle.kts вашего app-модуля:

    dependencies {
        implementation(project(":gravity_sdk"))
    }

# 2. Быстрый старт

Этот раздел проведет вас через основные шаги интеграции SDK, от инициализации до запуска вашей первой кампании.

# Шаг 1: Инициализация SDK

Сначала необходимо инициализировать SDK с вашим apiKey и section. Это лучше всего делать в классе Application или в MainActivity. Критически важно подключить gravityEventCallback для обработки навигации и других действий.

import android.app.Application
import android.content.Intent
import android.net.Uri
import ai.gravityfield.gravity_sdk.GravitySDK
import ai.gravityfield.gravity_sdk.models.FollowDeeplinkEvent
import ai.gravityfield.gravity_sdk.models.FollowUrlEvent
import ai.gravityfield.gravity_sdk.models.TrackingEvent
import ai.gravityfield.gravity_sdk.models.UISettings

class App : Application() {
    override fun onCreate() {
        super.onCreate()

        GravitySDK.initialize(
            context = this,
            apiKey = "YOUR_API_KEY",
            section = "YOUR_SECTION_ID",
            gravityEventCallback = ::handleGravityEvent,
            uiSettings = UISettings(fontResId = R.font.your_custom_font) // Опционально: для кастомизации UI
        )
    }

    private fun handleGravityEvent(event: TrackingEvent) {
        println("Gravity SDK Event: ${event.javaClass.simpleName}")

        when (event) {
            is FollowUrlEvent -> {
                val intent = Intent(Intent.ACTION_VIEW, Uri.parse(event.url))
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                startActivity(intent)
            }
            is FollowDeeplinkEvent -> {
                // Здесь ваша логика навигации по диплинкам
                println("Follow Deeplink: ${event.deeplink}")
            }
            else -> {
                // Другие события
            }
        }
    }
}

# Почему важен gravityEventCallback?

SDK не выполняет навигацию самостоятельно. Когда пользователь нажимает на кнопку в кампании, SDK генерирует событие (например, FollowUrlEvent) и передает его в gravityEventCallback. Ваше приложение должно «поймать» это событие и выполнить соответствующее действие (открыть ссылку, перейти на другой экран). Без этого интерактивные элементы работать не будут.

Подробнее о событиях см. раздел Обработка обратных вызовов (Callbacks).

# Шаг 2: Идентификация пользователя

Когда пользователь входит в систему, важно связать его действия, совершенные анонимно, с его постоянным профилем. Для этого после авторизации отправляется LoginEvent.

import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
// ...

// Вызывается после успешной авторизации пользователя
fun onUserLoggedIn(context: Context, userCustomId: String) {
    lifecycleScope.launch {
        val loginEvent = LoginEvent(cuid = userCustomId, cuidType = "mySystemUserId")

        GravitySDK.instance.triggerEvent(
            events = listOf(loginEvent),
            pageContext = PageContext(
                type = ContextType.OTHER,
                data = emptyList(),
                location = "app://login"
            ),
            activityContext = context
        )
    }
}

Отправка LoginEvent "склеивает" анонимный профиль с профилем авторизованного пользователя, сохраняя всю историю его действий.

Подробнее о различных способах идентификации читайте в разделе Идентификация пользователя.

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

Gravity Field принимает решение о показе персонализированного контента на основе контекста страницы. Давайте отследим просмотр главной страницы.

// В коде вашей Activity или Fragment
fun trackHomepageView(context: Context) {
    lifecycleScope.launch {
        GravitySDK.instance.trackView(
            pageContext = PageContext(
                type = ContextType.HOMEPAGE,
                data = emptyList(),
                location = "app://homepage"
            ),
            activityContext = context
        )
    }
}

Если для этого события настроена in-app кампания, SDK автоматически покажет ее.

# Шаг 4: Отслеживание событий

Теперь отследим добавление товара в корзину. Это событие может запустить кампанию с товарными рекомендациями (например, "с этим товаром покупают").

fun trackAddToCart(context: Context, productId: String) {
    lifecycleScope.launch {
        val event = AddToCartEvent(
            value = 99.99,
            productId = productId,
            quantity = 1,
            currency = "RUB"
        )

        GravitySDK.instance.triggerEvent(
            events = listOf(event),
            pageContext = PageContext(
                type = ContextType.PRODUCT,
                data = listOf(productId),
                location = "app://product/$productId"
            ),
            activityContext = context
        )
    }
}

# Шаг 5: Отображение inline-кампаний

Для отображения рекомендаций прямо в верстке страницы (например, блок "Персональные рекомендации") используйте GravityInlineView для XML-разметки или GravityInlineCompose для Jetpack Compose.

XML Layout:

<ai.gravityfield.gravity_sdk.ui.GravityInlineView
    android:layout_width="match_parent"
    android:layout_height="250dp"
    app:selector="homepage-recommendations" />

Jetpack Compose:

import ai.gravityfield.gravity_sdk.ui.GravityInlineCompose
// ...

GravityInlineCompose(
    modifier = Modifier.height(250.dp),
    selector = "homepage-recommendations",
    pageContext = PageContext(
        type = ContextType.HOMEPAGE,
        data = emptyList(),
        location = "app://homepage"
    )
)

Виджет сам загрузит и отобразит релевантный контент по селектору homepage-recommendations.

# 3. Инициализация и конфигурация

# initialize()

Основной метод для настройки SDK. Вызывается один раз при старте приложения.

fun initialize(
    context: Context,
    apiKey: String,
    section: String,
    gravityEventCallback: GravityEventCallback,
    productViewBuilder: ProductViewBuilder? = null,
    productFilter: ProductFilter? = null,
    uiSettings: UISettings? = null,
)
Параметр Тип Описание
context Context Обязательный. Контекст приложения.
apiKey String Обязательный. Ваш уникальный ключ API.
section String Обязательный. Идентификатор секции вашего проекта.
gravityEventCallback (TrackingEvent) -> Unit Обязательный. Колбэк для обработки событий SDK (навигация, действия).
productViewBuilder ProductViewBuilder? Опциональный билдер для кастомизации виджетов продуктов.
productFilter ((Slot) -> Boolean)? Опциональный фильтр для исключения продуктов из рекомендаций на клиенте.
uiSettings UISettings? Опциональные настройки для кастомизации UI, отображаемого SDK. Позволяет, например, задать кастомный шрифт.

# setOptions()

Позволяет задать глобальные настройки для всех последующих запросов.

fun setOptions(
    options: Options?,
    contentSettings: ContentSettings?,
    proxyUrl: String?
)
  • options: Настройки для управления поведением запросов.
  • contentSettings: Настройки для управления получаемым контентом.
  • proxyUrl: URL прокси-сервера для отправки запросов.

Пример:

GravitySDK.instance.setOptions(
    options = Options(
        isReturnUserInfo = true // Возвращать информацию о пользователе в ответах
    ),
    contentSettings = ContentSettings(
        skusOnly = false, // Возвращать полную информацию о продуктах
        fields = listOf("name", "price", "imageUrl") // Запросить конкретные поля
    ),
    proxyUrl = "https://my-proxy.com"
)

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

SDK поддерживает два подхода к идентификации: автоматический (управляется SDK) и ручной (управляется вашим приложением).

# Автоматическая идентификация

Это подход по умолчанию. При первом запросе SDK получает от сервера уникальный uid (user ID) и ses (session ID) и сохраняет их на устройстве. Все последующие запросы будут использовать эти идентификаторы.

Чтобы связать анонимный профиль с профилем авторизованного пользователя, после входа в систему отправьте LoginEvent.

// Вызывается после успешной авторизации
fun onUserLoggedIn(context: Context, userCustomId: String) {
    lifecycleScope.launch {
        val loginEvent = LoginEvent(
            cuid = userCustomId,
            cuidType = "mySystemUserId" // Укажите тип вашего идентификатора
        )

        GravitySDK.instance.triggerEvent(
            events = listOf(loginEvent),
            pageContext = PageContext(
                type = ContextType.OTHER,
                data = emptyList(),
                location = "app://login"
            ),
            activityContext = context
        )
    }
}

# Ручная идентификация (setUser)

Если ваше приложение уже управляет ID пользователей и сессий, вы можете передавать их в SDK напрямую.

fun setUser(userId: String, sessionId: String)

Пример:

// Вызывается при старте сессии, если ID уже известны
GravitySDK.instance.setUser("user-from-my-system-42", "session-from-my-system-xyz")

В этом режиме SDK не будет использовать автоматически сгенерированный uid.

# 5. Передача контекста (trackView)

Отправляет событие просмотра экрана. В ответ может прийти кампания для показа.

suspend fun trackView(
    pageContext: PageContext,
    activityContext: Context
)
  • pageContext: Контекст страницы, который описывает, где находится пользователь.
  • activityContext: Контекст Activity, необходимый для отображения In-App кампаний.

Пример:

// На экране продукта
lifecycleScope.launch {
    GravitySDK.instance.trackView(
        pageContext = PageContext(
            type = ContextType.PRODUCT,
            data = listOf("product-sku-123"), // SKU продукта
            location = "app://product/123"
        ),
        activityContext = this@ProductActivity
    )
}

# PageContext

Ключевая модель для описания местоположения и контекста пользователя.

Свойство Тип Описание
type ContextType Тип страницы (HOMEPAGE, PRODUCT, CART и т.д.).
data List<String> Массив строк с данными, зависящими от типа (например, SKU для PRODUCT).
location String Уникальный идентификатор местоположения (URL, deeplink, название экрана).
lng String? Язык или регион.
utm Map<String, String>? UTM-метки.
attributes Map<String, String> Дополнительные атрибуты для таргетинга.

# 6. Трекинг событий (triggerEvent)

Отправляет одно или несколько событий о действиях пользователя. Может запустить кампанию.

suspend fun triggerEvent(
    events: List<TriggerEvent>,
    pageContext: PageContext,
    activityContext: Context
)
  • events: Список событий для отправки.
  • pageContext: Контекст страницы.
  • activityContext: Контекст Activity.

Подробное описание всех доступных событий — в разделе Справочник по событиям TriggerEvent.

# 7. Передача статуса Push-уведомлений

Чтобы платформа могла таргетировать кампании на пользователей в зависимости от статуса подписки на push-уведомления, необходимо передавать этот статус в SDK.

# setNotificationPermissionStatus()

Устанавливает текущий статус разрешения на push-уведомления.

fun setNotificationPermissionStatus(status: NotificationPermissionStatus)
  • status: NotificationPermissionStatus.GRANTED, NotificationPermissionStatus.DENIED или NotificationPermissionStatus.UNKNOWN.

Пример получения и установки статуса:

import androidx.core.app.NotificationManagerCompat
// ...

val areNotificationsEnabled = NotificationManagerCompat.from(context).areNotificationsEnabled()
val status = if (areNotificationsEnabled) {
    NotificationPermissionStatus.GRANTED
} else {
    NotificationPermissionStatus.DENIED
}
GravitySDK.instance.setNotificationPermissionStatus(status)

# 8. Работа с контентом

# In-App кампании (автоматический показ)

SDK автоматически отображает In-App кампании (модальные окна, bottom sheet, полноэкранные экраны, снэкбары), когда они приходят в ответ на вызовы trackView или triggerEvent.

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

# XML Layouts: GravityInlineView

Используйте этот View для встраивания кампаний в XML-разметку.

<ai.gravityfield.gravity_sdk.ui.GravityInlineView
    android:layout_width="match_parent"
    android:layout_height="250dp"
    app:selector="homepage-recs"
    app:color="#FFF1F1F1"
    app:cornerRadius="20dp" />

# Jetpack Compose: GravityInlineCompose

Используйте эту Composable-функцию для встраивания кампаний в Jetpack Compose.

GravityInlineCompose(
    modifier = Modifier.fillMaxWidth().height(250.dp),
    selector = "homepage-recs",
    pageContext = PageContext(
        type = ContextType.HOMEPAGE,
        data = emptyList(),
        location = "app://homepage"
    )
)

Виджет сам загрузит и отобразит релевантный контент по селектору homepage-recommendations.

# Кастомный рендеринг товаров (ProductViewBuilder)

Для полного контроля над внешним видом карточек товаров в рекомендациях, вы можете реализовать интерфейс ProductViewBuilder. SDK предоставляет два способа интеграции: современный с использованием Jetpack Compose (рекомендуемый) и для Legacy Android Views.

⚠️ Важно: При использовании любого кастомного рендеринга вы обязаны самостоятельно реализовать отправку события клика по товару (ProductClickEngagement). SDK автоматически отслеживает только показ (ProductVisibleImpressionEngagement) кастомных виджетов, но не может отследить клики внутри вашей верстки.

# Реализация с Jetpack Compose (Рекомендуемый подход)

Создайте класс, реализующий интерфейс ProductViewBuilder, и в методе Build опишите вашу Composable-функцию. Для обработки нажатий используйте модификатор clickable.

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import ai.gravityfield.gravity_sdk.GravitySDK
import ai.gravityfield.gravity_sdk.models.CampaignContent
import ai.gravityfield.gravity_sdk.models.ProductClickEngagement
import ai.gravityfield.gravity_sdk.models.Slot
import ai.gravityfield.gravity_sdk.network.Campaign
import ai.gravityfield.gravity_sdk.ui.product_view_builder.ProductViewBuilder

// 1. Создайте свой билдер
class MyComposeProductViewBuilder : ProductViewBuilder {
    @Composable
    override fun Build(slot: Slot, content: CampaignContent, campaign: Campaign) {
        // Ваша кастомная верстка карточки товара
        Box(
            modifier = Modifier.clickable {
                // 2. Отправляем событие клика по товару (PCLICK)
                GravitySDK.instance.sendProductEngagement(
                    ProductClickEngagement(slot, content, campaign)
                )
                // 3. Здесь ваша логика навигации на экран товара
                // yourNavigationLogic(slot.item["url"])
            }
        ) {
            Text(text = slot.item["name"] as? String ?: "Unknown Product")
        }
    }
}

// 3. Передайте экземпляр билдера в initialize
GravitySDK.initialize(
    // ...
    productViewBuilder = MyComposeProductViewBuilder(),
)

# Реализация с Legacy Android Views

Если ваше приложение использует традиционную систему View, создайте класс, реализующий LegacyProductViewBuilder. В методе createView верните вашу кастомную View и установите на нее onClickListener.

import android.content.Context
import android.view.View
import android.widget.TextView
import ai.gravityfield.gravity_sdk.GravitySDK
import ai.gravityfield.gravity_sdk.models.CampaignContent
import ai.gravityfield.gravity_sdk.models.ProductClickEngagement
import ai.gravityfield.gravity_sdk.models.Slot
import ai.gravityfield.gravity_sdk.network.Campaign
import ai.gravityfield.gravity_sdk.ui.product_view_builder.LegacyProductViewBuilder

// 1. Создайте свой билдер
class MyLegacyProductViewBuilder : LegacyProductViewBuilder {
    override fun createView(
        context: Context,
        slot: Slot,
        content: CampaignContent,
        campaign: Campaign
    ): View {
        // Ваша кастомная верстка карточки товара
        val productView = TextView(context).apply {
            text = slot.item["name"] as? String ?: "Unknown Product"
            // ... другие настройки View
        }

        // 2. Установите обработчик клика
        productView.setOnClickListener {
            // 3. Отправляем событие клика по товару (PCLICK)
            GravitySDK.instance.sendProductEngagement(
                ProductClickEngagement(slot, content, campaign)
            )
            // 4. Здесь ваша логика навигации на экран товара
            // yourNavigationLogic(slot.item["url"])
        }

        return productView
    }
}

// 4. Передайте экземпляр билдера в initialize
GravitySDK.initialize(
    // ...
    productViewBuilder = MyLegacyProductViewBuilder(),
)

# JSON-кампании (ручной рендеринг)

Для максимальной гибкости вы можете получать кампании в виде чистого JSON и рендерить их самостоятельно.

# getContentBy...()

Запрашивает кампанию по селектору или ID и возвращает ее данные.

suspend fun getContentBySelector(selector: String, pageContext: PageContext): ContentResponse
suspend fun getContentByCampaignId(campaignId: String, pageContext: PageContext): ContentResponse

Пример:

lifecycleScope.launch {
    val response = GravitySDK.instance.getContentBySelector(
        selector = "homepage-banner-json",
        pageContext = PageContext(type = ContextType.HOMEPAGE, data = emptyList(), location = "app://home")
    )
    // ... ваша логика отображения на основе response.data
}

# 9. Кастомизация UI

SDK позволяет настраивать внешний вид отображаемых In-App кампаний, чтобы они соответствовали стилю вашего приложения.

# Настройка шрифта

Вы можете передать собственный шрифт, который будет использоваться во всех текстовых элементах, отображаемых SDK (в модальных окнах, bottom sheet и т.д.).

Шаг 1: Добавьте файл шрифта в ресурсы

Поместите ваш файл шрифта (например, my_custom_font.ttf) в директорию res/font вашего Android-проекта.

Шаг 2: Передайте шрифт при инициализации SDK

При вызове GravitySDK.initialize используйте параметр uiSettings, чтобы указать ID вашего ресурса шрифта.

import android.app.Application
import ai.gravityfield.gravity_sdk.GravitySDK
import ai.gravityfield.gravity_sdk.models.UISettings
// ...

class App : Application() {
    override fun onCreate() {
        super.onCreate()

        // Создаем объект настроек UI
        val uiSettings = UISettings(fontResId = R.font.my_custom_font)

        GravitySDK.initialize(
            context = this,
            apiKey = "YOUR_API_KEY",
            section = "YOUR_SECTION_ID",
            gravityEventCallback = ::handleGravityEvent,
            uiSettings = uiSettings // Передаем настройки в SDK
        )
    }
    // ...
}

После этого все текстовые элементы в UI-компонентах SDK будут использовать указанный вами шрифт.

# 10. Трекинг взаимодействий (Engagement)

Трекинг взаимодействий (engagement) в Android SDK организован на двух уровнях, чтобы обеспечить гибкий сбор аналитики как по виджетам в целом, так и по отдельным товарам внутри них. Понимание этой иерархии — ключ к правильной интеграции и достоверным отчетам.

# Иерархия событий в кампании

Чтобы понять, какое событие за что отвечает, важно видеть их место в структуре данных кампании.

graph TD
  subgraph Структура Кампании
    A[Кампания / Виджет] --> B(content.events)
    B --> C["WRIMP (Показ всего виджета)"]
    B --> D["WCLICK (Клик по виджету/контенту)"]
    A --> E[products]
    E -- содержит --> F{products.slots}
    subgraph Уровень Товара
      F --> G{Slot 1}
      F --> H{Slot 2}
      F --> I[...]
      G --> J(products.slots.events)
      J --> K["PIMP (Показ товара)"]
      J --> L["PCLICK (Клик по товару)"]
    end
  end

# Диаграмма последовательности событий взаимодействия

sequenceDiagram
  participant User as Пользователь
  participant App as Приложение (UI)
  participant SDK as Gravity SDK
  participant Server as Gravity Field

  User->>App: Скролл до виджета / экран показан
  App->>SDK: Виджет стал видимым (>=50%)
  SDK->>Server: WRIMP (ContentVisibleImpression)
  SDK->>Server: PIMP для каждого видимого товара
  User->>App: Клик по товару
  App->>SDK: sendProductEngagement(ProductClickEngagement)
  SDK->>Server: PCLICK

  opt Дополнительно для A/B (опционально)
    App->>SDK: sendContentEngagement(ContentClickEngagement)
    SDK->>Server: WCLICK
  end

  Server-->>SDK: 200 OK

# Назначение и использование событий

Каждый тип события служит для определенных аналитических целей.

# События уровня виджета (WRIMP и WCLICK)

Эти события отслеживают взаимодействие со всей кампанией (виджетом).

  • WRIMP (Widget Real Impression): Фиксирует показ всего виджета, когда он попадает в зону видимости пользователя. Это базовое событие для отслеживания видимости кампании.
  • WCLICK (Widget Click): Используется для отслеживания кликов по не-рекомендательным виджетам, таким как баннеры, in-app, кнопки и т.д.

# События уровня товара (PIMP и PCLICK)

Эти события необходимы для сбора статистики по рекомендательным кампаниям.

  • PIMP (Product Impression): Фиксирует показ отдельного товара в рекомендательном блоке, когда он становится видимым.
  • PCLICK (Product Click): Ключевое событие для аналитики рекомендаций. Оно содержит информацию о конкретном товаре и рекомендательной стратегии. Отправка PCLICK обязательна для того, чтобы в отчете по рекомендательным стратегиям появилась аналитика по кликам на товары.

💡 Продвинутый сценарий: WCLICK для A/B-тестов рекомендаций

В случае рекомендательных кампаний, разработчик может опционально отправлять событие WCLICK при клике на любую область виджета (включая клик по товару, одновременно с PCLICK).

Зачем это нужно? Это полезно для A/B-тестирования, когда требуется сравнить общий CTR (Click-Through Rate) разных рекомендательных алгоритмов. WCLICK позволяет измерить кликабельность всего виджета как единого целого, в то время как PCLICK измеряет интерес к конкретным товарам.

# Функции SDK для ручной отправки событий

Когда SDK не может автоматически отследить взаимодействие (например, в кастомном UI), вы должны отправлять события вручную. Для этого в SDK предусмотрены два метода:

# sendContentEngagement()

Используется для отслеживания взаимодействий с виджетом в целом (события WRIMP/WCLICK). По умолчанию SDK автоматически отправляет эти события для встроенных форматов. Это актуально, когда вы получаете кампанию через getContentBy...(), где вы сами отвечаете за рендеринг.

// Пример отправки события показа виджета
GravitySDK.instance.sendContentEngagement(
    ContentVisibleImpressionEngagement(content, campaign)
)

Классы: ContentImpressionEngagement, ContentVisibleImpressionEngagement, ContentCloseEngagement.

# sendProductEngagement()

Используется для отслеживания взаимодействий с отдельными товарами внутри виджета (события PIMP/PCLICK). Отправка PCLICK обязательна при использовании ProductViewBuilder. PIMP (показ) отправляется автоматически.

// Пример отправки события клика по товару
GravitySDK.instance.sendProductEngagement(
    ProductClickEngagement(slot, content, campaign)
)

Классы: ProductClickEngagement, ProductVisibleImpressionEngagement.

# Сценарий: Клик по товару в кастомном ProductViewBuilder

Если вы реализуете свой ProductViewBuilder, вы обязаны вручную отправлять событие PCLICK при нажатии на товар. SDK автоматически отслеживает только показ (PIMP) кастомных виджетов.

// Пример для Jetpack Compose
Box(
    modifier = Modifier.clickable {
        // 1. Отправляем событие клика по товару (PCLICK)
        GravitySDK.instance.sendProductEngagement(
            ProductClickEngagement(slot, content, campaign)
        )
        // 2. Выполняем навигацию на страницу товара
        // yourNavigationLogic(slot.item["url"])
    }
) {
    // ... ваша верстка
}

// Пример для Legacy Android Views
productView.setOnClickListener {
    // 1. Отправляем событие клика по товару (PCLICK)
    GravitySDK.instance.sendProductEngagement(
        ProductClickEngagement(slot, content, campaign)
    )
    // 2. Выполняем навигацию на страницу товара
    // yourNavigationLogic(slot.item["url"])
}

# 11. Обработка обратных вызовов (Callbacks)

Подпишитесь на события SDK, передав функцию gravityEventCallback в initialize. Это критично для обработки навигации и запросов разрешений.

Пример обработки:

private fun handleGravityEvent(event: TrackingEvent) {
    when (event) {
        is FollowUrlEvent -> {
            // Открыть URL
        }
        is FollowDeeplinkEvent -> {
            // Выполнить навигацию по диплинку
        }
        is RequestPushEvent -> {
            // Запросить разрешение на push-уведомления
        }
        // ... другие события
        else -> {}
    }
}

# 12. Справочник по событиям TriggerEvent

В таблице ниже описаны основные классы событий, которые можно отправлять с помощью triggerEvent(...).

Событие Описание Ключевые параметры
AddToCartEvent Добавление товара в корзину value, productId, quantity, currency?, cart?
PurchaseEvent Успешная покупка uniqueTransactionId, value, cart, currency?
RemoveFromCartEvent Удаление товара из корзины value, productId, quantity, currency?, cart?
SyncCartEvent Синхронизация полного состава корзины value, currency?, cart?
AddToWishlistEvent Добавление в список желаний value, productId
SignUpEvent Регистрация нового пользователя hashedEmail?, cuid?, cuidType?
LoginEvent Вход пользователя в систему hashedEmail?, cuid?, cuidType?
CustomEvent Любое другое кастомное событие type, name, customProps?

# 13. Справочник по событиям TrackingEvent (для колбэков)

Событие Описание Требует обработки?
ContentLoadEvent Контент кампании загружен. Нет
ContentImpressionEvent Контент кампании показан. Нет
ContentVisibleImpressionEvent Контент стал видимым на экране. Нет
ContentCloseEvent Пользователь закрыл In-App. Нет
CopyEvent Пользователь скопировал данные (промокод). Нет
CancelEvent Пользователь отменил действие. Нет
FollowUrlEvent Пользователь нажал на внешнюю ссылку. Да
FollowDeeplinkEvent Пользователь нажал на внутреннюю ссылку. Да
RequestPushEvent Пользователь нажал кнопку запроса push-разрешений. Да
ProductImpressionEvent Карточка товара стала видимой. Нет