Перейти к содержанию

Синтаксис нативных шаблонов In-App сообщений

Нативные In-App сообщения отображаются непосредственно SDK. WebView не используется. Вместо страницы index.html ZIP-ресурс содержит файл native-config.json, который описывает сообщение в виде структурированных данных (тип макета, тексты, цвета, изображения, кнопки). SDK считывает этот файл и отрисовывает соответствующее нативное представление, что обеспечивает более плавную анимацию и лучшую производительность по сравнению со встроенной веб-страницей.

В этом руководстве задокументирована схема native-config.json: поля, типы и примеры для каждого типа отображения. Информацию о классическом формате на основе HTML см. в разделе Синтаксис шаблонов Rich Media.

Предварительные требования

Anchor link to

Для нативных In-App сообщений требуется:

  • iOS: SDK 7.2.0 или новее (7.2.1+ для banner, carousel и sheet)
  • Android: SDK 6.10.0 или новее (6.10.1+ для banner, carousel и sheet)

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

Поддержка платформ

Anchor link to
Тип отображения
iOS
Android
modal✅ 7.2.0+✅ 6.10.0+
fullscreen✅ 7.2.0+✅ 6.10.0+
stories✅ 7.2.0+✅ 6.10.0+
banner✅ 7.2.1+✅ 6.10.1+
carousel✅ 7.2.1+✅ 6.10.1+
sheet✅ 7.2.1+✅ 6.10.1+
videoПока недоступно
pipПока недоступно
scratchcardПока недоступно
spinwheelПока недоступно

Структура шаблона

Anchor link to

Шаблон нативного In-App сообщения — это ZIP-архив, такой же, как и обычный шаблон Rich Media, за исключением того, что в корневом каталоге вместо index.html содержится файл native-config.json:

<template>.zip
├── native-config.json ← required, layout and content
├── pushwoosh.json ← optional, localization (see below)

Изображения и видео, на которые есть ссылки в native-config.json (image, poster, fallback, url в pip/video), должны быть абсолютными URL-адресами HTTPS. SDK загружает их по сети. Он не считывает локальные файлы из архива.

Сама конфигурация представляет собой единый объект JSON:

{ "displayType": "<type>", "<type>": { /* content block for this type */ } }

displayType выбирает один из десяти форматов, описанных ниже. Объект под соответствующим ключом содержит контент этого формата. Конфигурация с неизвестным displayType, отсутствующим блоком контента или пустым обязательным списком (items для carousel/stories, segments для spinwheel) является недействительной. SDK пропустит ее отображение, чтобы не отрисовывать некорректный макет.

Настройки доставки (даты начала/окончания и ограничение частоты показов) не являются частью native-config.json. Они настраиваются так же, как и для любого другого In-App сообщения, на шаге Настройки отображения кампании.

Кроме того, для ограничения частоты показов нативных In-App сообщений требуется явное согласие на стороне SDK. См. раздел Интеграция SDK.

Цвета

Anchor link to

Каждое значение цвета представляет собой шестнадцатеричную строку CSS: #RGB, #RGBA, #RRGGBB или #RRGGBBAA. Начальный символ # обязателен во всех четырех формах.

Общие строительные блоки

Anchor link to

Эти небольшие объекты повторно используются в нескольких типах отображения.

Текст

Anchor link to
ПолеТипОбязательноОписание
textstringдаТекстовое содержимое
colorstringдаЦвет текста
{ "text": "Spin for a garage perk", "color": "#FFFFFFFF" }

Граница

Anchor link to
ПолеТипОбязательноОписание
colorstringдаЦвет границы
radiusnumberдаРадиус скругления углов в пунктах
{ "color": "#0E72E5FF", "radius": 12 }

Обложка

Anchor link to

Необязательное изображение поверх фонового цвета. Используется в fullscreen и scratchcard.

ПолеТипОбязательноОписание
imagestringнетURL изображения обложки
backgroundstringдаЦвет фона, отображаемый под изображением (или вместо него)
{ "image": "https://example.com/cover.jpg", "background": "#1A1A1EFF" }

Действие

Anchor link to

Различаемое объединение по type:

ВариантПоляОписание
{ "type": "close" }NoneЗакрывает In-App сообщение
{ "type": "url", "url": string }url requiredОткрывает URL или диплинк
{ "type": "url", "url": "pushwoosh://sale" }

Кнопка

Anchor link to
ПолеТипОбязательноОписание
textTextдаНадпись на кнопке
backgroundstringдаЦвет заливки кнопки
borderBorderдаГраница кнопки
actionActionдаДействие, выполняемое при нажатии

spinButton (spinwheel) и revealButton (scratchcard) имеют ту же форму, но без action. Их поведение (вращать колесо, открыть карту) встроено.

{
"text": { "text": "Book a test drive", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://sale" }
}

Награда

Anchor link to

Панель с призом, отображаемая в scratchcard и spinwheel. Действительная награда имеет title или code.

ПолеТипОбязательноОписание
titleTextнетЗаголовок награды
messageTextнетОписание награды
codestringнетПромокод, отображаемый с кнопкой копирования
buttonButtonнетКнопка подтверждения с собственным действием
{
"title": { "text": "20% off detailing", "color": "#111111FF" },
"message": { "text": "Valid for any full-detail booking this month.", "color": "#555555FF" },
"code": "APEX20",
"button": {
"text": { "text": "Book detailing", "color": "#FFFFFFFF" },
"background": "#B3227CFF",
"border": { "color": "#B3227CFF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://detailing" }
}
}

Типы отображения

Anchor link to

Компактная панель, закрепленная у верхнего или нижнего края экрана.

ПолеТипОбязательноОписание
showClosebooleanдаПоказывать кнопку закрытия (✕)
positiontop | bottomдаКрай экрана
backgroundstringдаЦвет фона панели
imagestringнетМиниатюра слева
titleTextнетОднострочный заголовок, усеченный многоточием
messageTextнетОсновной текст, до 2 строк
actionActionдаВыполняется при нажатии на саму панель
autoDismissnumberнетАвтоматически закрыть через указанное количество секунд. Опустите, чтобы оставить до закрытия вручную
{
"displayType": "banner",
"banner": {
"showClose": true,
"position": "bottom",
"background": "#4B5057FF",
"image": "https://example.com/thumb.jpg",
"title": { "text": "Alpine A110 just dropped", "color": "#FFFFFFFF" },
"message": { "text": "The featherweight icon — tap to see the build", "color": "#FFFFFFFF" },
"action": { "type": "url", "url": "pushwoosh://product/x6f" },
"autoDismiss": 6
}
}

Полноэкранный набор карточек с возможностью пролистывания и точками-индикаторами страниц.

ПолеТипОбязательноОписание
showClosebooleanдаПоказывать кнопку закрытия (✕)
itemsItem[]даКарточки (не менее 1)

Элемент карусели:

ПолеТипОбязательноОписание
titleTextнетЗаголовок карточки
messageTextнетПодзаголовок карточки
imagestringнетИзображение карточки
actionActionнетВыполняется при нажатии на карточку
{
"displayType": "carousel",
"carousel": {
"showClose": true,
"items": [
{
"image": "https://example.com/card-1.jpg",
"title": { "text": "AMG GT R", "color": "#FFFFFFFF" },
"message": { "text": "585 hp biturbo V8 — just landed", "color": "#FFFFFFFF" },
"action": { "type": "url", "url": "pushwoosh://product/n6fx" }
},
{
"image": "https://example.com/card-2.jpg",
"title": { "text": "Alpine A110", "color": "#FFFFFFFF" },
"message": { "text": "Featherweight icon — limited allocation", "color": "#FFFFFFFF" },
"action": { "type": "url", "url": "pushwoosh://product/x6f" }
}
]
}
}

fullscreen

Anchor link to

Изображение обложки от края до края с текстом и кнопками поверх него.

ПолеТипОбязательноОписание
showClosebooleanдаПоказывать кнопку закрытия (✕)
coverCoverдаФоновое изображение и цвет
titleTextнетЗаголовок
messageTextнетОсновной текст
buttonsButton[]даКнопки внизу (может быть пустым)
{
"displayType": "fullscreen",
"fullscreen": {
"showClose": true,
"cover": { "image": "https://example.com/hero.jpg", "background": "#1A1A1EFF" },
"title": { "text": "Pure Maranello", "color": "#FFFFFFFF" },
"message": { "text": "The prancing horse, reimagined.", "color": "#EBEBEBFF" },
"buttons": [
{
"text": { "text": "Reserve now", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 8 },
"action": { "type": "url", "url": "pushwoosh://sale" }
},
{
"text": { "text": "Not now", "color": "#FFFFFFFF" },
"background": "#00000000",
"border": { "color": "#FFFFFF99", "radius": 8 },
"action": { "type": "close" }
}
]
}
}

Карточка по центру.

ПолеТипОбязательноОписание
showClosebooleanдаПоказывать кнопку закрытия (✕)
dimBackgroundbooleanдаЗатемнить экран за карточкой
backgroundstringдаЦвет фона карточки
imagestringнетИзображение обложки
titleTextнетЗаголовок
messageTextнетОсновной текст
buttonsButton[]даКнопки под текстом (может быть пустым)
{
"displayType": "modal",
"modal": {
"showClose": true,
"dimBackground": true,
"background": "#FFFFFFFF",
"image": "https://example.com/cover.jpg",
"title": { "text": "The GT R has landed", "color": "#4B5057FF" },
"message": { "text": "585 hp — now in the showroom.", "color": "#4B5057FF" },
"buttons": [
{
"text": { "text": "Book a test drive", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://sale" }
},
{
"text": { "text": "Not now", "color": "#4B5057FF" },
"background": "#FFFFFFFF",
"border": { "color": "#4B5057FF", "radius": 12 },
"action": { "type": "close" }
}
]
}
}

Плавающее окно видео «картинка в картинке», закрепленное в углу экрана.

ПолеТипОбязательноОписание
showClosebooleanдаПоказывать кнопку закрытия (✕)
positionbottom-right | bottom-left | top-right | top-leftдаУгол экрана
loopbooleanдаЗациклить воспроизведение
mutedbooleanдаНачать с выключенным звуком
urlstringдаURL видео
posterstringнетПостер, отображаемый до начала воспроизведения
fallbackstringнетИзображение, отображаемое, если видео не удалось воспроизвести
widthnumberдаШирина окна в процентах от ширины экрана, в диапазоне 15–70
aspectRationumberдаСоотношение высоты и ширины окна
borderRadiusnumberнетРадиус скругления углов окна в пунктах
actionActionнетВыполняется при нажатии на само окно

На pip нет настраиваемых кнопок. Элементы управления окном (развернуть на весь экран, выключить звук, закрыть) предоставляются системой.

{
"displayType": "pip",
"pip": {
"showClose": true,
"position": "bottom-right",
"loop": true,
"muted": true,
"url": "https://example.com/teaser.mp4",
"poster": "https://example.com/poster.jpg",
"width": 40,
"aspectRatio": 0.5625,
"action": { "type": "url", "url": "pushwoosh://product/x6f" }
}
}

scratchcard

Anchor link to

Карточка с наградой, скрытой под стираемым слоем фольги.

ПолеТипОбязательноОписание
showClosebooleanдаПоказывать кнопку закрытия (✕)
backgroundstring | string[]даЦвет фона карточки или точки градиента
revealThresholdnumberдаДоля фольги, которую необходимо стереть (0–1), прежде чем откроется награда
coverCoverдаСлой фольги. Без image на фоновом цвете отображается подсказка «сотрите здесь»
revealButtonButton (no action)нетКнопка «Открыть сразу»
titleTextнетЗаголовок
messageTextнетОсновной текст
rewardRewardдаПриз, скрытый под фольгой
{
"displayType": "scratchcard",
"scratchcard": {
"showClose": true,
"background": ["#3A1C71FF", "#B3227CFF", "#E0503AFF"],
"revealThreshold": 0.55,
"cover": { "background": "#C9CDD6FF" },
"revealButton": {
"text": { "text": "Reveal without scratching", "color": "#3A1C71FF" },
"background": "#F2DFF5FF",
"border": { "color": "#F2DFF5FF", "radius": 10 }
},
"title": { "text": "Your loyalty reward", "color": "#FFFFFFFF" },
"message": { "text": "Scratch the foil to reveal this week's garage perk.", "color": "#F2DFF5FF" },
"reward": {
"title": { "text": "20% off detailing", "color": "#111111FF" },
"message": { "text": "Valid for any full-detail booking this month.", "color": "#555555FF" },
"code": "APEX20",
"button": {
"text": { "text": "Book detailing", "color": "#FFFFFFFF" },
"background": "#B3227CFF",
"border": { "color": "#B3227CFF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://detailing" }
}
}
}
}

Карточка, закрепленная у нижнего края, с маркером для перетаскивания.

ПолеТипОбязательноОписание
showClosebooleanдаПоказывать кнопку закрытия (✕)
dimBackgroundbooleanдаЗатемнить экран за карточкой
backgroundstringдаЦвет фона карточки
imagestringнетИзображение обложки
titleTextнетЗаголовок
messageTextнетОсновной текст
buttonsButton[]даКнопки под текстом (может быть пустым)
{
"displayType": "sheet",
"sheet": {
"showClose": true,
"dimBackground": true,
"background": "#FFFFFFFF",
"image": "https://example.com/cover.jpg",
"title": { "text": "Your quote is ready", "color": "#000000FF" },
"message": { "text": "Guaranteed buyout for your A110: $68,500.", "color": "#000000FF" },
"buttons": [
{
"text": { "text": "Get guaranteed quote", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://sale" }
}
]
}
}

Колесо фортуны со взвешенными сегментами и центральной кнопкой.

ПолеТипОбязательноОписание
showClosebooleanдаПоказывать кнопку закрытия (✕)
backgroundstring | string[]даЦвет фона карточки или точки градиента
winIndexnumberдаИндекс (начиная с 0) выигрышного сегмента
spinButtonButton (no action)даЦентральная кнопка
titleTextнетЗаголовок
messageTextнетОсновной текст
rewardRewardдаНаграда за выигрышное вращение (резервный вариант для сегментов без собственной награды)
loseTitleTextнетЗаголовок, отображаемый при проигрыше
segmentsSegment[]даСегменты колеса (SDK ожидает 2–12)

Сегмент:

ПолеТипОбязательноОписание
messageTextдаНадпись на сегменте
colorstringнетЦвет сегмента. Опустите, чтобы использовать резервную палитру, применяемую по всему колесу
weightnumberдаОтносительный размер сегмента
rewardRewardнетНаграда для конкретного сегмента
{
"displayType": "spinwheel",
"spinwheel": {
"showClose": true,
"background": ["#1B1B46FF", "#5B2B8FFF", "#B0338AFF"],
"winIndex": 1,
"spinButton": {
"text": { "text": "SPIN", "color": "#1B1B46FF" },
"background": "#F2C94CFF",
"border": { "color": "#D9A02BFF", "radius": 36 }
},
"title": { "text": "Spin for a garage perk", "color": "#FFFFFFFF" },
"message": { "text": "One spin — every slice wins this week.", "color": "#E3D9F2FF" },
"reward": {
"title": { "text": "You won a garage perk!", "color": "#FFFFFFFF" },
"code": "APEXPERK",
"button": {
"text": { "text": "Claim", "color": "#FFFFFFFF" },
"background": "#5B2B8FFF",
"border": { "color": "#5B2B8FFF", "radius": 12 },
"action": { "type": "close" }
}
},
"segments": [
{ "message": { "text": "5% off", "color": "#FFFFFFFF" }, "color": "#5856D6FF", "weight": 1 },
{
"message": { "text": "20% off", "color": "#FFFFFFFF" },
"color": "#30B0C7FF",
"weight": 1,
"reward": {
"title": { "text": "20% off your next service", "color": "#FFFFFFFF" },
"code": "SPIN20",
"button": {
"text": { "text": "Claim service deal", "color": "#FFFFFFFF" },
"background": "#30B0C7FF",
"border": { "color": "#30B0C7FF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://service" }
}
}
},
{ "message": { "text": "Free wash", "color": "#FFFFFFFF" }, "color": "#FF2D55FF", "weight": 1 }
]
}
}

Полноэкранные слайды с индикаторами выполнения вверху, похожие на истории в социальных сетях.

ПолеТипОбязательноОписание
showClosebooleanдаПоказывать кнопку закрытия (✕)
loopbooleanдаНачать с первого слайда после последнего
itemsItem[]даСлайды (не менее 1)

Элемент историй:

ПолеТипОбязательноОписание
titleTextнетЗаголовок
messageTextнетПодзаголовок
imagestringнетФоновое изображение слайда
buttonsButton[]даКнопки призыва к действию внизу (может быть пустым)
durationnumberдаПродолжительность слайда в секундах
{
"displayType": "stories",
"stories": {
"showClose": true,
"loop": false,
"items": [
{
"image": "https://example.com/slide-1.jpg",
"title": { "text": "AMG GT R", "color": "#FFFFFFFF" },
"message": { "text": "The Green Hell special", "color": "#FFFFFFFF" },
"buttons": [
{
"text": { "text": "Configure yours", "color": "#FFFFFFFF" },
"background": "#0F0F0FFF",
"border": { "color": "#0F0F0FFF", "radius": 26 },
"action": { "type": "url", "url": "pushwoosh://product/n6fx" }
}
],
"duration": 4
},
{
"image": "https://example.com/slide-2.jpg",
"title": { "text": "Alpine A110", "color": "#FFFFFFFF" },
"message": { "text": "The featherweight legend, reborn", "color": "#FFFFFFFF" },
"buttons": [],
"duration": 4
}
]
}
}

Полноэкранное видео с текстом и кнопками поверх него.

ПолеТипОбязательноОписание
showClosebooleanдаПоказывать кнопку закрытия (✕)
loopbooleanдаЗациклить воспроизведение
mutedbooleanдаНачать с выключенным звуком
urlstringдаURL видео (HLS или MP4)
posterstringнетПостер, отображаемый до начала воспроизведения
fallbackstringнетИзображение, отображаемое, если видео не удалось воспроизвести
titleTextнетЗаголовок
messageTextнетОсновной текст
buttonsButton[]даКнопки призыва к действию внизу (может быть пустым)
{
"displayType": "video",
"video": {
"showClose": true,
"loop": true,
"muted": true,
"url": "https://example.com/reveal.mp4",
"poster": "https://example.com/poster.jpg",
"title": { "text": "The reveal", "color": "#FFFFFFFF" },
"message": { "text": "Watch it move before anyone else.", "color": "#EBEBEBFF" },
"buttons": [
{
"text": { "text": "Shop the lineup", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 14 },
"action": { "type": "url", "url": "pushwoosh://sale" }
}
]
}
}

Локализация

Anchor link to

Нативные In-App сообщения используют тот же механизм локализации, что и HTML Rich Media: строковые значения в native-config.json могут содержать плейсхолдеры {{key|type|default}}, а переводы находятся в файле pushwoosh.json рядом с ним, в том же формате, который описан в разделе Добавление pushwoosh.json. Плейсхолдер может находиться в любом строковом поле на любой глубине (заголовок, надпись на кнопке, URL изображения, URL действия).

Динамический контент

Anchor link to

Текстовые поля — title, message, text кнопки, reward.title/reward.message и message элемента/сегмента — также принимают Динамический контент и синтаксис Liquid: те же сокращения {Tag|modifier|default} и теги Liquid {% %}/{{ }}, которые используются в push-уведомлениях и email-сообщениях. Pushwoosh обрабатывает их для каждого получателя перед отправкой сообщения, так же, как и для push-уведомлений и email.

При создании шаблона в редакторе нативных In-App сообщений в Control Panel вставленные токены отображаются в виде чипов в предпросмотре, а кнопка Сохранить блокируется, если Liquid в текстовом поле не может быть проанализирован.

Интеграция SDK

Anchor link to

После добавления модуля SDK для нативных In-App сообщений в ваше приложение, сообщения будут отображаться автоматически. Не требуется дополнительный код для показа сообщений, вызванных push-уведомлением, Customer Journey, postEvent или из папки «Входящие».

SDK также предоставляет небольшой API для ручного управления:

  • iOS: Pushwoosh.inApp (модуль PushwooshInApp)
  • Android: PushwooshInAppUi (модуль pushwoosh-inapp-ui)
ВозможностьiOSAndroid
Показать конфигурацию напрямую (тестирование/ручное использование)Pushwoosh.inApp.present(config)PushwooshInAppUi.present(configJson)
Наблюдать за жизненным циклом и кликамиdelegate (PWInAppMessageDelegate)delegate (InAppMessageDelegate)
Проверить, отображается ли что-либо на экранеisPresentingisPresenting
Закрыть то, что отображается в данный моментdismiss()dismiss()
Приостановить / возобновить отображениеisPausedisPaused
Применить ограничение maxDisplays / cooldownsetFrequencyCapEnabled(_:)setFrequencyCapEnabled(...)

Колбэки делегата (все вызываются в основном потоке): shouldDisplay (верните false, чтобы скрыть одно сообщение до его показа, например, на экране оформления заказа), willPresent, didPresent, didClose и clickedAction (вызывается, когда пользователь нажимает на действие url, перед открытием URL).

iOS дополнительно сообщает о rewardRevealed и rewardClaimed для геймифицированных шаблонов scratchcard и spinwheel.

// iOS
Pushwoosh.inApp.delegate = self
Pushwoosh.inApp.setFrequencyCapEnabled(true)
// Android
PushwooshInAppUi.delegate = this
PushwooshInAppUi.setFrequencyCapEnabled(true)