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

Импорт для примеров: package:gravity_sdk/gravity_sdk.dart. Методы с автопоказом дополнительно используют BuildContext из Flutter.

PageContext

const productContext = PageContext(
  type: ContextType.product,
  data: ['sku-123'],
  location: 'app://product/sku-123',
  attributes: {'screen_variant': 'standard'},
);
Поле Тип Как передавать
type ContextType Обязательно; тип текущего экрана
data List<String> Обязательно; значения для типа контекста, например SKU товара; [], если неприменимо
location String Обязательно; адрес/идентификатор экрана, согласованный с таргетингом
lng String? Региональное значение из фида, если проект его использует
pageNumber int? Номер страницы выдачи
referrer String? Предыдущий адрес
utm Map<String, String>? Метки источника
attributes Map<String, Object> Дополнительные атрибуты контекста; по умолчанию {}

Типы: homepage, product, cart, category, search, other. SDK сериализует их как HOMEPAGE, PRODUCT, CART, CATEGORY, SEARCH и OTHER.

data задаёт контекст выбора/таргетинга и не заменяет состав корзины в событии. Общие правила для каждого типа: Контекст страницы. Не меняйте регистр SKU, категорий и lng относительно товарного фида.

SDK добавляет в attributes служебные app_version, sdk_version и app_platform. Для iOS значение платформы — iOS. Таргетинг по платформе и версиям.

Просмотр экрана

trackView() передаёт просмотр и может автоматически показать in-app кампанию:

await GravitySDK.instance.trackView(
  context: context,
  pageContext: productContext,
);

Вызывайте после появления экрана, например через addPostFrameCallback, как в быстром старте. Не отправляйте просмотр из build(): перестроение виджета не означает новый визит.

BuildContext должен относиться к актуальному экрану внутри MaterialApp/Navigator; для SnackBar нужен ScaffoldMessenger. SDK проверяет context.mounted, но уход на другой маршрут не всегда размонтирует старый экран. Управляйте моментом вызова в логике навигации приложения.

Чтобы отправить просмотр без встроенного показа:

final details = await GravitySDK.instance.trackViewNoShow(
  pageContext: productContext,
);

details — nullable-ответ headless. Если нужно только собирать просмотры/события, задайте isFetchContentOnTrack: false; влияние флага описано в Конфигурации.

Пользовательские действия

Отправляйте событие после успешного действия: изменения корзины, завершения заказа или авторизации. triggerEvent() может показывать in-app; triggerEventNoShow() не показывает UI и не требует BuildContext.

Добавление и удаление товара

await GravitySDK.instance.triggerEventNoShow(
  events: [
    AddToCartEvent(
      value: 1990,
      productId: 'sku-123',
      quantity: 1,
      currency: 'RUB',
      cart: [
        CartItem(productId: 'sku-123', quantity: 1, itemPrice: 1990),
      ],
      customProps: {'list': 'recommendations'},
    ),
  ],
  pageContext: productContext,
);

RemoveFromCartEvent принимает те же поля. value и itemPrice — денежные значения, quantity — целое количество. Используйте согласованный с аналитикой проекта смысл value. Не подменяйте SKU внутренним ID приложения, если фид использует другой идентификатор.

Покупка

await GravitySDK.instance.triggerEventNoShow(
  events: [
    PurchaseEvent(
      uniqueTransactionId: 'ORDER-2026-1001-42',
      value: 3980,
      currency: 'RUB',
      cart: [
        CartItem(productId: 'sku-123', quantity: 2, itemPrice: 1990),
      ],
      customProps: {'delivery': 'pickup'},
      eventTime: DateTime.utc(2026, 10, 1, 10, 15),
    ),
  ],
  pageContext: const PageContext(
    type: ContextType.other,
    data: [],
    location: 'app://order/success',
  ),
);

uniqueTransactionId — устойчивый уникальный ID конкретного заказа. При повторной попытке доставки одного заказа не создавайте новый ID. Это особенно важно для офлайн-доставки.

Синхронизация корзины

final cartEvent = SyncCartEvent(
  value: 3980,
  currency: 'RUB',
  cart: [
    CartItem(productId: 'sku-123', quantity: 2, itemPrice: 1990),
  ],
);

Передавайте актуальный состав корзины; пустая корзина — cart: [].

Вход и регистрация

LoginEvent и SignUpEvent используют cuid/cuidType или hashedEmail. Полный пример хеширования и отправки — в Идентификации пользователя.

Произвольное событие

final customEvent = CustomEvent(
  type: 'delivery-selected-v1',
  name: 'Delivery selected',
  customProps: {'method': 'pickup', 'store_id': 'store-12'},
);

type и name согласуйте с настройкой событий/кампаний проекта. CustomEvent также принимает cuid, cuidType и cart. Не используйте его для повторного клика по встроенной кнопке SDK, который уже учтён её tracking.

customProps и eventTime

Эти поля доступны всем типам TriggerEvent в 0.24.0:

  • customProps — Map<String, String>?. Числа и boolean преобразуйте в строки; вложенные объекты полем не поддерживаются.
  • eventTime — DateTime?. SDK отправляет время в UTC. Если оно не задано, SDK фиксирует время вызова события, в том числе до ожидания сессии и доставки из очереди.

Не присваивайте событию время очередной попытки отправки. Для сохранённых ранее действий передавайте их фактическое время.

Ошибки и результат вызова

Возврат triggerEvent()/triggerEventNoShow() не подтверждает доставку: при временной ошибке запрос может остаться в очереди. NoShow возвращает null также при отсутствии контента, выключенной его загрузке, устаревшем ответе или обработанной ошибке.

Методы трекинга обрабатывают ошибки запроса внутри SDK. Вызов до initialize() выбрасывает исключение. Для запросов getContentBy* приложение отдельно обрабатывает сетевые ошибки и fallback.