跳到内容

Native in-app templates syntax

此内容尚未提供您的语言版本。

Native in-apps are rendered directly by the SDK. No WebView is involved. Instead of an index.html page, the ZIP resource carries a native-config.json file that describes the message as structured data (layout type, texts, colors, images, buttons). The SDK reads this file and draws the matching native view, which gives smoother animations and better performance than an embedded web page.

This guide documents the native-config.json schema: fields, types, and examples for each display type. For the classic HTML-based format, see Rich media templates syntax.

Prerequisites

Anchor link to

Native in-apps require:

  • iOS: SDK 7.2.0 or later (7.2.1+ for banner, carousel, and sheet)
  • Android: SDK 6.10.0 or later (6.10.1+ for banner, carousel, and sheet)

Not every display type is available on both platforms yet. Check Platform support before you rely on a specific format.

Platform support

Anchor link to
Display type
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+
videoNot yet available
pipNot yet available
scratchcardNot yet available
spinwheelNot yet available

Template structure

Anchor link to

A native in-app template is a ZIP archive, same as a regular Rich Media template, except the root contains a native-config.json file instead of index.html:

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

Images and videos referenced from native-config.json (image, poster, fallback, url on pip/video) must be absolute HTTPS URLs. The SDK loads them over the network. It does not read local files from the archive.

The config itself is a single JSON object:

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

displayType selects one of the ten formats below. The object under the matching key holds that format’s content. A config with an unknown displayType, a missing content block, or an empty required list (items for carousel/stories, segments for spinwheel) is invalid. The SDK skips showing it rather than rendering a broken layout.

Delivery settings (start/end dates and frequency capping) are not part of native-config.json. They’re configured the same way as for any other in-app, in the campaign’s Display settings step.

Frequency capping additionally needs an explicit SDK-side opt-in to take effect on native in-apps. See SDK integration.

Every color value is a CSS hex string: #RGB, #RGBA, #RRGGBB, or #RRGGBBAA. The leading # is required in all four forms.

Shared building blocks

Anchor link to

These smaller objects are reused across several display types.

FieldTypeRequiredDescription
textstringyesThe text content
colorstringyesText color
{ "text": "Spin for a garage perk", "color": "#FFFFFFFF" }
FieldTypeRequiredDescription
colorstringyesBorder color
radiusnumberyesCorner radius, in points
{ "color": "#0E72E5FF", "radius": 12 }

An optional image over a background color. Used by fullscreen and scratchcard.

FieldTypeRequiredDescription
imagestringnoCover image URL
backgroundstringyesBackground color shown under (or instead of) the image
{ "image": "https://example.com/cover.jpg", "background": "#1A1A1EFF" }

A discriminated union on type:

VariantFieldsDescription
{ "type": "close" }NoneCloses the in-app
{ "type": "url", "url": string }url requiredOpens a URL or deep link
{ "type": "url", "url": "pushwoosh://sale" }
FieldTypeRequiredDescription
textTextyesButton label
backgroundstringyesButton fill color
borderBorderyesButton border
actionActionyesAction fired on tap

spinButton (spinwheel) and revealButton (scratchcard) use the same shape without action. Their behavior (spin the wheel, reveal the card) is built in.

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

The prize panel shown by scratchcard and spinwheel. A valid reward has a title or a code.

FieldTypeRequiredDescription
titleTextnoReward headline
messageTextnoReward description
codestringnoPromo code, rendered with a copy button
buttonButtonnoConfirmation button with its own action
{
"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" }
}
}

Display types

Anchor link to

A compact bar docked to the top or bottom edge of the screen.

FieldTypeRequiredDescription
showClosebooleanyesShow a close (✕) button
positiontop | bottomyesScreen edge
backgroundstringyesBar background color
imagestringnoThumbnail on the left
titleTextnoSingle-line title, truncated with an ellipsis
messageTextnoBody text, up to 2 lines
actionActionyesFired when the bar itself is tapped
autoDismissnumbernoAuto-close after this many seconds. Omit to keep it until closed
{
"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
}
}

A full-screen, swipeable set of cards with page-indicator dots.

FieldTypeRequiredDescription
showClosebooleanyesShow a close (✕) button
itemsItem[]yesCards (at least 1)

Carousel item:

FieldTypeRequiredDescription
titleTextnoCard title
messageTextnoCard subtitle
imagestringnoCard image
actionActionnoFired when the card is tapped
{
"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

An edge-to-edge cover image with text and buttons on top.

FieldTypeRequiredDescription
showClosebooleanyesShow a close (✕) button
coverCoveryesBackground image and color
titleTextnoTitle
messageTextnoBody text
buttonsButton[]yesButtons at the bottom (can be empty)
{
"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" }
}
]
}
}

A centered card.

FieldTypeRequiredDescription
showClosebooleanyesShow a close (✕) button
dimBackgroundbooleanyesDim the screen behind the card
backgroundstringyesCard background color
imagestringnoCover image
titleTextnoTitle
messageTextnoBody text
buttonsButton[]yesButtons below the text (can be empty)
{
"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" }
}
]
}
}

A floating picture-in-picture video window docked to a screen corner.

FieldTypeRequiredDescription
showClosebooleanyesShow a close (✕) button
positionbottom-right | bottom-left | top-right | top-leftyesScreen corner
loopbooleanyesLoop playback
mutedbooleanyesStart muted
urlstringyesVideo URL
posterstringnoPoster shown before playback starts
fallbackstringnoImage shown if the video fails to play
widthnumberyesWindow width as a percentage of screen width, clamped 15–70
aspectRationumberyesWindow height-to-width ratio
borderRadiusnumbernoWindow corner radius, in points
actionActionnoFired when the window itself is tapped

There are no configurable buttons on pip. Window controls (expand to full screen, mute, close) are system-provided.

{
"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

A card with the reward hidden under a scratchable foil layer.

FieldTypeRequiredDescription
showClosebooleanyesShow a close (✕) button
backgroundstring | string[]yesCard background color, or gradient stops
revealThresholdnumberyesFraction of the foil that must be scratched off (0–1) before the reward reveals
coverCoveryesThe foil layer. Without an image, a “scratch here” hint is shown on the background color
revealButtonButton (no action)no”Reveal instantly” button
titleTextnoTitle
messageTextnoBody text
rewardRewardyesThe prize hidden under the foil
{
"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" }
}
}
}
}

A card pinned to the bottom edge, with a drag handle.

FieldTypeRequiredDescription
showClosebooleanyesShow a close (✕) button
dimBackgroundbooleanyesDim the screen behind the sheet
backgroundstringyesSheet background color
imagestringnoCover image
titleTextnoTitle
messageTextnoBody text
buttonsButton[]yesButtons below the text (can be empty)
{
"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" }
}
]
}
}

A wheel-of-fortune with weighted segments and a center hub button.

FieldTypeRequiredDescription
showClosebooleanyesShow a close (✕) button
backgroundstring | string[]yesCard background color, or gradient stops
winIndexnumberyesIndex (0-based) of the winning segment
spinButtonButton (no action)yesCenter hub button
titleTextnoTitle
messageTextnoBody text
rewardRewardyesReward for the winning spin (fallback for segments without their own)
loseTitleTextnoHeadline shown on a loss
segmentsSegment[]yesWheel segments (SDK expects 2–12)

Segment:

FieldTypeRequiredDescription
messageTextyesSegment label
colorstringnoSegment color. Omit for a fallback palette applied around the wheel
weightnumberyesRelative segment size
rewardRewardnoSegment-specific reward
{
"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 }
]
}
}

Full-screen slides with progress bars at the top, similar to social media stories.

FieldTypeRequiredDescription
showClosebooleanyesShow a close (✕) button
loopbooleanyesRestart from the first slide after the last one
itemsItem[]yesSlides (at least 1)

Stories item:

FieldTypeRequiredDescription
titleTextnoTitle
messageTextnoSubtitle
imagestringnoSlide background image
buttonsButton[]yesCTA buttons at the bottom (can be empty)
durationnumberyesSlide duration, in seconds
{
"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
}
]
}
}

Full-screen video with text and buttons on top.

FieldTypeRequiredDescription
showClosebooleanyesShow a close (✕) button
loopbooleanyesLoop playback
mutedbooleanyesStart muted
urlstringyesVideo URL (HLS or MP4)
posterstringnoPoster shown before playback starts
fallbackstringnoImage shown if the video fails to play
titleTextnoTitle
messageTextnoBody text
buttonsButton[]yesCTA buttons at the bottom (can be empty)
{
"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" }
}
]
}
}

Localization

Anchor link to

Native in-apps reuse the exact same localization mechanism as HTML Rich Media: string values in native-config.json can carry {{key|type|default}} placeholders, and translations live in a pushwoosh.json file next to it, in the same format described in Adding pushwoosh.json. A placeholder can appear in any string field, at any depth (a title, a button label, an image URL, an action URL).

SDK integration

Anchor link to

Once you add the native in-app SDK module to your app, messages display automatically. No extra code is required to show messages triggered by a push, Customer Journey, postEvent, or the inbox.

The SDK also exposes a small API for manual control:

  • iOS: Pushwoosh.inApp (module PushwooshInApp)
  • Android: PushwooshInAppUi (module pushwoosh-inapp-ui)
CapabilityiOSAndroid
Show a config directly (testing/manual use)Pushwoosh.inApp.present(config)PushwooshInAppUi.present(configJson)
Observe lifecycle and clicksdelegate (PWInAppMessageDelegate)delegate (InAppMessageDelegate)
Check if something is on screenisPresentingisPresenting
Dismiss whatever is currently showndismiss()dismiss()
Pause / resume displayisPausedisPaused
Enforce maxDisplays / cooldown cappingsetFrequencyCapEnabled(_:)setFrequencyCapEnabled(...)

Delegate callbacks (all fired on the main thread): shouldDisplay (return false to suppress one message before it shows, for example on a checkout screen), willPresent, didPresent, didClose, and clickedAction (fired when the user taps a url action, before the URL opens).

iOS additionally reports rewardRevealed and rewardClaimed for the gamified scratchcard and spinwheel templates.

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