#
SDK Gravity Field (Android)
Gravity Field SDK — это лёгкий клиент для интеграции мобильных приложений (iOS / Android) с платформой персонализации и A/B-тестирования. Он позволяет запускать кампании без необходимости реализовывать собственную логику таргетинга, выбора и аналитики.
SDK работает по принципу "тонкого клиента": все решения принимает сервер (бекенд Gravity Field), а SDK:
- передаёт контекст текущего экрана,
- получает кампании и их содержимое в виде JSON или встроенных шаблонов,
- активирует показ
inline
иin-app
кампаний - трекает взаимодействия пользователя (просмотры, клики, покупки и т.д.),
- и помогает фиксировать конверсии для аналитики и обучения моделей.
📦 Эта документация предназначена для мобильных разработчиков и инженеров, которые интегрируют SDK в приложение.
#
Добавление библиотеки в проект
- Добавить в свой проект модуль gravity_sdk
- После добавления модуля в файле
build.gradle.kts
добавить зависимость:
dependencies {
implementation(project(":gravity_sdk"))
}
- Добавьте импорт:
import ai.gravityfield.gravity_sdk.GravitySDK
#
Инициализация SDK
Для работы SDK необходимо провести базовую инициализацию, которая включает регистрацию секции и авторизацию через API-ключ. Дальнейшее взаимодействие с SDK осуществлячется через GravitySDK.instance
#
GravitySDK.initialize(...)
Метод принимает параметры:
Вызывается при:
- загрузке кампаний (
ContentLoadEvent
) - показе(закрытии) контента (
ContentImpressionEvent
,ContentVisibleImpressionEvent
,ContentCloseEvent
) - пользовательских действиях (
CopyEvent
,CancelEvent
,FollowUrlEvent
и др.) - взаимодействии с товарными слотами (
ProductImpressionEvent
)
Вот полный список типов, которые могут прилетать в gravityEventCallback
:
Используйте, если вам нужно:
- Вручную показывать или скрывать кампании, тип которых не обрабатывает 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
contentSettings
настройки товарного контента
Таким образом, configureCampaignOptions
позволяет заранее определить структуру и поведение всех кампаний, которые будут получены через SDK
proxyUrl
Базовый URL вашего backend-прокси, через который SDK будет отправлять все запросы. Если не задан — используется endpoint Gravity Field.
#
Идентификация пользователей
Идентификация пользователя — фундамент для персонализации, аналитики и построения омниканальных профилей в Gravity Field.
Без корректной идентификации невозможно:
- Связывать действия пользователя между сеансами и устройствами,
- Персонализировать рекомендации,
- Точно собирать аналитику,
- Строить сценарии персонализации и сегментацию.
#
Варианты идентификации
Gravity Field позволяет автоматически или вручную управлять идентификацией, гибко подстраиваясь под архитектуру вашего проекта.
Gravity Field UID (автоматическая идентификация)
Когда использовать:
- Когда нет собственного механизма учёта пользователей и сессий
Как работает:
- При первом запросе к Gravity Field (например,
trackView(...)
), если нет сохранённых идентификаторов, Gravity Field автоматически создаёт уникальные идентификаторы:uid
— уникальный идентификатор пользователя, автоматически сгенерированный Gravity Fieldses
— 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 автоматически управляет идентификаторами пользователя и сессии, опираясь на то, что уже сохранено локально. Используется следующая логика:
- Если вызван
setUser(...)
— SDK использует переданныеuserId
иsessionId
(режим: custom user ID). - Если
setUser(...)
не вызывался, но уже естьuid
иses
— SDK использует их (режим: Gravity Field UID). - Если ни один 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
#
Как активируются кампании на основе контекста страницы
Когда приложение отправляет событие просмотра страницы через 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
)
Пример:
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/
#
CartItem
#
Как активируются кампании по событию
Когда приложение отправляет событие через 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
задается в настройках кампании, в личном кабинете 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,
)
📌 Подходит для:
- Получения кампаний заранее (например, до отрисовки экрана)
- Встраивания кампаний в кастомные блоки
- Полного управления кампанией на стороне приложения (для данной кампании 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>
)
Почему 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>
)
#
Products
data class Products(
val strategyId: String,
val name: String,
val fallback: Boolean,
val slots: List<Slot>
)
#
Slot
data class Slot(
val item: Item,
val fallback: Boolean,
val strId: Int,
val slotId: String,
)
#
Трекинг взаимодействий (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)