Pular para o conteúdo

Sintaxe de modelos nativos de in-app

In-apps nativos são renderizados diretamente pelo SDK. Nenhum WebView está envolvido. Em vez de uma página index.html, o recurso ZIP carrega um arquivo native-config.json que descreve a mensagem como dados estruturados (tipo de layout, textos, cores, imagens, botões). O SDK lê este arquivo e desenha a visualização nativa correspondente, o que proporciona animações mais suaves e melhor desempenho do que uma página da web incorporada.

Este guia documenta o esquema native-config.json: campos, tipos e exemplos para cada tipo de exibição. Para o formato clássico baseado em HTML, consulte Sintaxe de modelos de Rich Media.

Pré-requisitos

Anchor link to

In-apps nativos exigem:

  • iOS: SDK 7.2.0 ou posterior (7.2.1+ para banner, carrossel e folha)
  • Android: SDK 6.10.0 ou posterior (6.10.1+ para banner, carrossel e folha)

Nem todos os tipos de exibição estão disponíveis em ambas as plataformas ainda. Verifique o Suporte de plataforma antes de depender de um formato específico.

Suporte de plataforma

Anchor link to
Tipo de exibição
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+
videoAinda não disponível
pipAinda não disponível
scratchcardAinda não disponível
spinwheelAinda não disponível

Estrutura do modelo

Anchor link to

Um modelo de in-app nativo é um arquivo ZIP, o mesmo que um modelo de Rich Media regular, exceto que a raiz contém um arquivo native-config.json em vez de index.html:

<template>.zip
├── native-config.json ← obrigatório, layout e conteúdo
├── pushwoosh.json ← opcional, localização (veja abaixo)

Imagens e vídeos referenciados de native-config.json (image, poster, fallback, url em pip/video) devem ser URLs HTTPS absolutas. O SDK os carrega pela rede. Ele não lê arquivos locais do arquivo.

A configuração em si é um único objeto JSON:

{ "displayType": "<type>", "<type>": { /* bloco de conteúdo para este tipo */ } }

displayType seleciona um dos dez formatos abaixo. O objeto sob a chave correspondente contém o conteúdo desse formato. Uma configuração com um displayType desconhecido, um bloco de conteúdo ausente ou uma lista obrigatória vazia (items para carousel/stories, segments para spinwheel) é inválida. O SDK ignora a exibição em vez de renderizar um layout quebrado.

As configurações de entrega (datas de início/fim e limite de frequência) não fazem parte do native-config.json. Elas são configuradas da mesma forma que para qualquer outro in-app, na etapa de Configurações de exibição da campanha.

O limite de frequência adicionalmente precisa de uma adesão explícita do lado do SDK para ter efeito em in-apps nativos. Consulte Integração com o SDK.

Cada valor de cor é uma string hexadecimal CSS: #RGB, #RGBA, #RRGGBB ou #RRGGBBAA. O # inicial é obrigatório em todas as quatro formas.

Blocos de construção compartilhados

Anchor link to

Esses objetos menores são reutilizados em vários tipos de exibição.

CampoTipoObrigatórioDescrição
textstringsimO conteúdo do texto
colorstringsimCor do texto
{ "text": "Spin for a garage perk", "color": "#FFFFFFFF" }
CampoTipoObrigatórioDescrição
colorstringsimCor da borda
radiusnumbersimRaio do canto, em pontos
{ "color": "#0E72E5FF", "radius": 12 }

Uma imagem opcional sobre uma cor de fundo. Usado por fullscreen e scratchcard.

CampoTipoObrigatórioDescrição
imagestringnãoURL da imagem de capa
backgroundstringsimCor de fundo mostrada sob (ou em vez de) a imagem
{ "image": "https://example.com/cover.jpg", "background": "#1A1A1EFF" }

Uma união discriminada em type:

VarianteCamposDescrição
{ "type": "close" }NenhumFecha o in-app
{ "type": "url", "url": string }url obrigatórioAbre uma URL ou deep link
{ "type": "url", "url": "pushwoosh://sale" }
CampoTipoObrigatórioDescrição
textTextsimRótulo do botão
backgroundstringsimCor de preenchimento do botão
borderBordersimBorda do botão
actionActionsimAção disparada ao tocar

spinButton (spinwheel) e revealButton (scratchcard) usam a mesma forma sem action. O comportamento deles (girar a roda, revelar o cartão) é embutido.

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

Recompensa

Anchor link to

O painel de prêmios mostrado por scratchcard e spinwheel. Uma recompensa válida tem um title ou um code.

CampoTipoObrigatórioDescrição
titleTextnãoTítulo da recompensa
messageTextnãoDescrição da recompensa
codestringnãoCódigo promocional, renderizado com um botão de cópia
buttonButtonnãoBotão de confirmação com sua própria ação
{
"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" }
}
}

Tipos de exibição

Anchor link to

Uma barra compacta ancorada na borda superior ou inferior da tela.

CampoTipoObrigatórioDescrição
showClosebooleansimMostrar um botão de fechar (✕)
positiontop | bottomsimBorda da tela
backgroundstringsimCor de fundo da barra
imagestringnãoMiniatura à esquerda
titleTextnãoTítulo de uma linha, truncado com reticências
messageTextnãoTexto do corpo, até 2 linhas
actionActionsimDisparado quando a própria barra é tocada
autoDismissnumbernãoFechar automaticamente após este número de segundos. Omita para mantê-lo até ser fechado
{
"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
}
}

Um conjunto de cartões deslizáveis em tela cheia com pontos indicadores de página.

CampoTipoObrigatórioDescrição
showClosebooleansimMostrar um botão de fechar (✕)
itemsItem[]simCartões (pelo menos 1)

Item do carrossel:

CampoTipoObrigatórioDescrição
titleTextnãoTítulo do cartão
messageTextnãoSubtítulo do cartão
imagestringnãoImagem do cartão
actionActionnãoDisparado quando o cartão é tocado
{
"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

Uma imagem de capa de ponta a ponta com texto e botões por cima.

CampoTipoObrigatórioDescrição
showClosebooleansimMostrar um botão de fechar (✕)
coverCoversimImagem e cor de fundo
titleTextnãoTítulo
messageTextnãoTexto do corpo
buttonsButton[]simBotões na parte inferior (pode estar vazio)
{
"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" }
}
]
}
}

Um cartão centralizado.

CampoTipoObrigatórioDescrição
showClosebooleansimMostrar um botão de fechar (✕)
dimBackgroundbooleansimEscurecer a tela atrás do cartão
backgroundstringsimCor de fundo do cartão
imagestringnãoImagem de capa
titleTextnãoTítulo
messageTextnãoTexto do corpo
buttonsButton[]simBotões abaixo do texto (pode estar vazio)
{
"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" }
}
]
}
}

Uma janela de vídeo picture-in-picture flutuante ancorada a um canto da tela.

CampoTipoObrigatórioDescrição
showClosebooleansimMostrar um botão de fechar (✕)
positionbottom-right | bottom-left | top-right | top-leftsimCanto da tela
loopbooleansimRepetir a reprodução
mutedbooleansimIniciar sem som
urlstringsimURL do vídeo
posterstringnãoPôster mostrado antes do início da reprodução
fallbackstringnãoImagem mostrada se o vídeo falhar ao reproduzir
widthnumbersimLargura da janela como porcentagem da largura da tela, limitada entre 15–70
aspectRationumbersimProporção altura/largura da janela
borderRadiusnumbernãoRaio do canto da janela, em pontos
actionActionnãoDisparado quando a própria janela é tocada

Não há botões configuráveis em pip. Os controles da janela (expandir para tela cheia, silenciar, fechar) são fornecidos pelo sistema.

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

Um cartão com a recompensa escondida sob uma camada de folha raspável.

CampoTipoObrigatórioDescrição
showClosebooleansimMostrar um botão de fechar (✕)
backgroundstring | string[]simCor de fundo do cartão, ou paradas de gradiente
revealThresholdnumbersimFração da folha que deve ser raspada (0–1) antes que a recompensa seja revelada
coverCoversimA camada de folha. Sem uma image, uma dica “raspe aqui” é mostrada na cor de fundo
revealButtonButton (sem action)nãoBotão “Revelar instantaneamente”
titleTextnãoTítulo
messageTextnãoTexto do corpo
rewardRewardsimO prêmio escondido sob a folha
{
"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" }
}
}
}
}

Um cartão fixado na borda inferior, com uma alça de arrasto.

CampoTipoObrigatórioDescrição
showClosebooleansimMostrar um botão de fechar (✕)
dimBackgroundbooleansimEscurecer a tela atrás da folha
backgroundstringsimCor de fundo da folha
imagestringnãoImagem de capa
titleTextnãoTítulo
messageTextnãoTexto do corpo
buttonsButton[]simBotões abaixo do texto (pode estar vazio)
{
"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" }
}
]
}
}

Uma roda da fortuna com segmentos ponderados e um botão central.

CampoTipoObrigatórioDescrição
showClosebooleansimMostrar um botão de fechar (✕)
backgroundstring | string[]simCor de fundo do cartão, ou paradas de gradiente
winIndexnumbersimÍndice (base 0) do segmento vencedor
spinButtonButton (sem action)simBotão central
titleTextnãoTítulo
messageTextnãoTexto do corpo
rewardRewardsimRecompensa pela rodada vencedora (fallback para segmentos sem a sua própria)
loseTitleTextnãoTítulo mostrado em uma perda
segmentsSegment[]simSegmentos da roda (SDK espera 2–12)

Segmento:

CampoTipoObrigatórioDescrição
messageTextsimRótulo do segmento
colorstringnãoCor do segmento. Omita para uma paleta de fallback aplicada ao redor da roda
weightnumbersimTamanho relativo do segmento
rewardRewardnãoRecompensa específica do segmento
{
"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 }
]
}
}

Slides em tela cheia com barras de progresso no topo, semelhantes às histórias de redes sociais.

CampoTipoObrigatórioDescrição
showClosebooleansimMostrar um botão de fechar (✕)
loopbooleansimReiniciar do primeiro slide após o último
itemsItem[]simSlides (pelo menos 1)

Item de stories:

CampoTipoObrigatórioDescrição
titleTextnãoTítulo
messageTextnãoSubtítulo
imagestringnãoImagem de fundo do slide
buttonsButton[]simBotões de CTA na parte inferior (pode estar vazio)
durationnumbersimDuração do slide, em segundos
{
"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
}
]
}
}

Vídeo em tela cheia com texto e botões por cima.

CampoTipoObrigatórioDescrição
showClosebooleansimMostrar um botão de fechar (✕)
loopbooleansimRepetir a reprodução
mutedbooleansimIniciar sem som
urlstringsimURL do vídeo (HLS ou MP4)
posterstringnãoPôster mostrado antes do início da reprodução
fallbackstringnãoImagem mostrada se o vídeo falhar ao reproduzir
titleTextnãoTítulo
messageTextnãoTexto do corpo
buttonsButton[]simBotões de CTA na parte inferior (pode estar vazio)
{
"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" }
}
]
}
}

Localização

Anchor link to

In-apps nativos reutilizam o mesmo mecanismo de localização que o Rich Media HTML: valores de string em native-config.json podem carregar placeholders {{key|type|default}}, e as traduções ficam em um arquivo pushwoosh.json ao lado dele, no mesmo formato descrito em Adicionando pushwoosh.json. Um placeholder pode aparecer em qualquer campo de string, em qualquer profundidade (um título, um rótulo de botão, uma URL de imagem, uma URL de ação).

Conteúdo dinâmico

Anchor link to

Campos de texto — title, message, text do botão, reward.title/reward.message e message de item/segmento — também aceitam Conteúdo dinâmico e sintaxe Liquid: a mesma abreviação {Tag|modifier|default} e tags Liquid {% %}/{{ }} usadas no conteúdo de push e e-mail. O Pushwoosh resolve isso por destinatário antes que a mensagem seja enviada, da mesma forma que faz para push e e-mail.

Ao construir um modelo no editor de in-app nativo do Painel de Controle, os tokens inseridos são renderizados como chips na visualização ao vivo, e Salvar é bloqueado se o Liquid de um campo de texto não for analisado corretamente.

Integração com o SDK

Anchor link to

Depois de adicionar o módulo SDK de in-app nativo ao seu aplicativo, as mensagens são exibidas automaticamente. Nenhum código extra é necessário para mostrar mensagens acionadas por um push, Customer Journey, postEvent ou a caixa de entrada.

O SDK também expõe uma pequena API para controle manual:

  • iOS: Pushwoosh.inApp (módulo PushwooshInApp)
  • Android: PushwooshInAppUi (módulo pushwoosh-inapp-ui)
CapacidadeiOSAndroid
Mostrar uma configuração diretamente (teste/uso manual)Pushwoosh.inApp.present(config)PushwooshInAppUi.present(configJson)
Observar ciclo de vida e cliquesdelegate (PWInAppMessageDelegate)delegate (InAppMessageDelegate)
Verificar se algo está na telaisPresentingisPresenting
Dispensar o que estiver sendo exibido no momentodismiss()dismiss()
Pausar / retomar exibiçãoisPausedisPaused
Aplicar limite de maxDisplays / cooldownsetFrequencyCapEnabled(_:)setFrequencyCapEnabled(...)

Callbacks do delegate (todos disparados na thread principal): shouldDisplay (retorne false para suprimir uma mensagem antes que ela seja exibida, por exemplo, em uma tela de checkout), willPresent, didPresent, didClose e clickedAction (disparado quando o usuário toca em uma ação url, antes que a URL seja aberta).

O iOS adicionalmente relata rewardRevealed e rewardClaimed para os modelos gamificados scratchcard e spinwheel.

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