# Октябрь '26. Обновление SDK: учёт показов, JSON и события

Вышли **Flutter SDK 0.25.0**, **iOS SDK 1.2.0** и **Android SDK 1.2.0**. Во всех трёх исправили учёт модальных in-app: быстрое закрытие после появления окна больше не отменяет показ, а при потере сети SDK сохраняет его для повторной отправки. В iOS и Android добавили исходный JSON кампаний, доступ к произвольным переменным и свойства событий.

## Модальный показ учитывается с первого кадра

Модальное окно, bottom sheet и полноэкранный in-app теперь фиксируют видимый показ — `visible impression` — при первом подтверждённом кадре содержимого в активном приложении. Ждать минимальное время просмотра не нужно. Если пользователь увидел окно и сразу закрыл его, показ учитывается. Если окно отменено до появления содержимого, показа нет.

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

Перед отправкой SDK сохраняет показ на устройстве. При временной сетевой ошибке повторяет доставку, в том числе после перезапуска приложения. SDK повторяет доставку до 7 дней после показа. Пока ожидается подтверждение, SDK защищает кампанию от повторного открытия для того же пользователя. Защита действует максимум 24 часа после показа и прекращается раньше при подтверждении или постоянной ошибке. После подтверждения частоту снова определяет сервер.

Это помогает учесть уже показанные сообщения, даже если связь пропала между открытием окна и отправкой аналитики. Для inline-блоков, товаров, SnackBar и собственного UI действуют отдельные правила видимости.

Управление доставкой: [Flutter](/Integration/SDK/flutter/offline.md#модальные-показы-wrimp), [iOS](/Integration/SDK/ios/network.md#учёт-модальных-показов), [Android](/Integration/SDK/android/network.md#учёт-модальных-показов).

## iOS и Android: исходный JSON для своего интерфейса

В native SDK появились `getContentBySelectorWithDetails(...)` и `getContentByCampaignIdWithDetails(...)`. Они возвращают модель контента и исходный JSON одного ответа сервера. Приложение читает поля, которых ещё нет в типизированных моделях SDK, и использует их в интерфейсе.

В `CampaignContent.rawVariables` доступен весь объект переменных кампании: строки, числа, boolean, вложенные объекты, массивы и `null`. Например, приложение получает из кампании подпись кнопки и параметры выбранного A/B-варианта, а отрисовывает их своими компонентами. Типизированные поля продолжают работать.

Загрузка данных сама не показывает интерфейс. SDK отправляет tracking загрузки, а фактическую видимость и клики собственного UI фиксирует приложение.

Примеры чтения JSON и переменных: [Swift](/Integration/SDK/ios/custom_ui.md#исходный-json-и-переменные-кампании) и [Kotlin](/Integration/SDK/android/custom_ui.md#исходный-json-и-переменные-кампании).

## iOS и Android: свойства и время у всех событий

Всем типам `TriggerEvent` можно передать `customProps` и `eventTime`. Например, к добавлению в корзину — название списка, из которого пришёл товар, и его позицию. Значения `customProps` должны быть строками.

`eventTime` задаёт фактическое время действия. Если его не передать, SDK фиксирует момент вызова `triggerEvent(...)` до асинхронной отправки. В `CustomEvent` также добавлены `cuid`, `cuidType` и `cart`.

Поля уже доступны во Flutter; теперь ими можно пользоваться и в native SDK. Примеры событий: [Swift](/Integration/SDK/ios/events.md#customprops-и-eventtime) и [Kotlin](/Integration/SDK/android/events.md#customprops-и-eventtime).

## Как обновить

| Платформа | Версия | Подключение |
|---|---|---|
| Flutter | `0.25.0` | [Зависимость в pubspec.yaml](/Integration/SDK/flutter/ask_flutter.md#установка) |
| iOS | `1.2.0` | [Swift Package Manager](/Integration/SDK/ios/overview.md#установка) |
| Android | `1.2.0` | [Maven-артефакт](/Integration/SDK/android/overview.md#готовый-maven-артефакт) |

После обновления проверьте быстрое закрытие in-app, переход между шагами и доставку показа после перезапуска без сети. Во Flutter модальные показы сохраняются даже при `OfflineQueueSettings(enabled: false)`, учитываются в `pendingDeliveries` и удаляются через `clearQueue()`.

В native SDK очередь в этом релизе относится к модальным показам. Для бизнес-событий из `triggerEvent(...)`, покупок и кликов общей постоянной очереди нет.
