Saltar al contenido

Sintaxis de plantillas nativas in-app

Los in-apps nativos son renderizados directamente por el SDK. No se utiliza ningún WebView. En lugar de una página index.html, el recurso ZIP lleva un archivo native-config.json que describe el mensaje como datos estructurados (tipo de diseño, textos, colores, imágenes, botones). El SDK lee este archivo y dibuja la vista nativa correspondiente, lo que proporciona animaciones más fluidas y un mejor rendimiento que una página web incrustada.

Esta guía documenta el esquema de native-config.json: campos, tipos y ejemplos para cada tipo de visualización. Para el formato clásico basado en HTML, consulte Sintaxis de plantillas de Rich Media.

Requisitos previos

Anchor link to

Los in-apps nativos requieren:

  • iOS: SDK 7.2.0 o posterior (7.2.1+ para banner, carrusel y hoja)
  • Android: SDK 6.10.0 o posterior (6.10.1+ para banner, carrusel y hoja)

No todos los tipos de visualización están disponibles en ambas plataformas todavía. Consulte Soporte de plataforma antes de depender de un formato específico.

Soporte de plataforma

Anchor link to
Tipo de visualización
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✅✅ 6.11.0+
pip✅Aún no disponible
scratchcard✅Aún no disponible
spinwheel✅Aún no disponible

Estructura de la plantilla

Anchor link to

Una plantilla nativa in-app es un archivo ZIP, igual que una plantilla de Rich Media normal, excepto que la raíz contiene un archivo native-config.json en lugar de index.html:

<template>.zip
├── native-config.json ← requerido, diseño y contenido
├── pushwoosh.json ← opcional, localización (ver más abajo)

Las imágenes y videos referenciados desde native-config.json (image, poster, fallback, url en pip/video) deben ser URLs HTTPS absolutas. El SDK los carga a través de la red. No lee archivos locales del archivo.

La configuración en sí es un único objeto JSON:

{ "displayType": "<type>", "<type>": { /* bloque de contenido para este tipo */ } }

displayType selecciona uno de los diez formatos a continuación. El objeto bajo la clave correspondiente contiene el contenido de ese formato. Una configuración con un displayType desconocido, un bloque de contenido faltante o una lista requerida vacía (items para carousel/stories, segments para spinwheel) no es válida. El SDK omite mostrarla en lugar de renderizar un diseño roto.

Los ajustes de entrega (fechas de inicio/fin y limitación de frecuencia) no forman parte de native-config.json. Se configuran de la misma manera que para cualquier otro in-app, en el paso de Ajustes de visualización de la campaña.

La limitación de frecuencia necesita adicionalmente una activación explícita del lado del SDK para tener efecto en los in-apps nativos. Consulte Integración del SDK.

Cada valor de color es una cadena hexadecimal de CSS: #RGB, #RGBA, #RRGGBB o #RRGGBBAA. El # inicial es obligatorio en las cuatro formas.

Bloques de construcción compartidos

Anchor link to

Estos objetos más pequeños se reutilizan en varios tipos de visualización.

CampoTipoRequeridoDescripción
textstringsíEl contenido del texto
colorstringsíColor del texto
{ "text": "Spin for a garage perk", "color": "#FFFFFFFF" }
CampoTipoRequeridoDescripción
colorstringsíColor del borde
radiusnumbersíRadio de la esquina, en puntos
{ "color": "#0E72E5FF", "radius": 12 }

Una imagen opcional sobre un color de fondo. Usado por fullscreen y scratchcard.

CampoTipoRequeridoDescripción
imagestringnoURL de la imagen de cubierta
backgroundstringsíColor de fondo que se muestra debajo (o en lugar de) la imagen
{ "image": "https://example.com/cover.jpg", "background": "#1A1A1EFF" }

Una unión discriminada en type:

VarianteCamposDescripción
{ "type": "close" }NingunoCierra el in-app
{ "type": "url", "url": string }url requeridoAbre una URL o un deep link
{ "type": "url", "url": "pushwoosh://sale" }
CampoTipoRequeridoDescripción
textTextsíEtiqueta del botón
backgroundstringsíColor de relleno del botón
borderBordersíBorde del botón
actionActionsíAcción que se activa al tocar

spinButton (spinwheel) y revealButton (scratchcard) usan la misma forma sin action. Su comportamiento (girar la rueda, revelar la tarjeta) está incorporado.

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

El panel de premios que muestran scratchcard y spinwheel. Una recompensa válida tiene un title o un code.

CampoTipoRequeridoDescripción
titleTextnoTítulo de la recompensa
messageTextnoDescripción de la recompensa
codestringnoCódigo promocional, renderizado con un botón de copiar
buttonButtonnoBotón de confirmación con su propia acción
{
"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 visualización

Anchor link to

Una barra compacta anclada al borde superior o inferior de la pantalla.

CampoTipoRequeridoDescripción
showClosebooleansíMostrar un botón de cierre (✕)
positiontop | bottomsíBorde de la pantalla
backgroundstringsíColor de fondo de la barra
imagestringnoMiniatura a la izquierda
titleTextnoTítulo de una sola línea, truncado con puntos suspensivos
messageTextnoTexto del cuerpo, hasta 2 líneas
actionActionsíSe activa cuando se toca la propia barra
autoDismissnumbernoCerrar automáticamente después de este número de segundos. Omitir para mantenerlo hasta que se cierre
{
"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
}
}

Un conjunto de tarjetas a pantalla completa que se pueden deslizar con puntos indicadores de página.

CampoTipoRequeridoDescripción
showClosebooleansíMostrar un botón de cierre (✕)
itemsItem[]síTarjetas (al menos 1)

Elemento del carrusel:

CampoTipoRequeridoDescripción
titleTextnoTítulo de la tarjeta
messageTextnoSubtítulo de la tarjeta
imagestringnoImagen de la tarjeta
actionActionnoSe activa cuando se toca la tarjeta
{
"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

Una imagen de cubierta de borde a borde con texto y botones encima.

CampoTipoRequeridoDescripción
showClosebooleansíMostrar un botón de cierre (✕)
coverCoversíImagen y color de fondo
titleTextnoTítulo
messageTextnoTexto del cuerpo
buttonsButton[]síBotones en la parte inferior (puede estar vacío)
{
"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" }
}
]
}
}

Una tarjeta centrada.

CampoTipoRequeridoDescripción
showClosebooleansíMostrar un botón de cierre (✕)
dimBackgroundbooleansíAtenuar la pantalla detrás de la tarjeta
backgroundstringsíColor de fondo de la tarjeta
imagestringnoImagen de cubierta
titleTextnoTítulo
messageTextnoTexto del cuerpo
buttonsButton[]síBotones debajo del texto (puede estar vacío)
{
"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" }
}
]
}
}

Una ventana de video flotante de imagen en imagen anclada a una esquina de la pantalla.

CampoTipoRequeridoDescripción
showClosebooleansíMostrar un botón de cierre (✕)
positionbottom-right | bottom-left | top-right | top-leftsíEsquina de la pantalla
loopbooleansíRepetir la reproducción
mutedbooleansíEmpezar silenciado
urlstringsíURL del video
posterstringnoPóster que se muestra antes de que comience la reproducción
fallbackstringnoImagen que se muestra si el video no se puede reproducir
widthnumbersíAncho de la ventana como porcentaje del ancho de la pantalla, limitado a 15–70
aspectRationumbersíRelación altura-ancho de la ventana
borderRadiusnumbernoRadio de la esquina de la ventana, en puntos
actionActionnoSe activa cuando se toca la propia ventana

No hay botones configurables en pip. Los controles de la ventana (expandir a pantalla completa, silenciar, cerrar) son proporcionados por el 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

Una tarjeta con la recompensa oculta bajo una capa de lámina rascable.

CampoTipoRequeridoDescripción
showClosebooleansíMostrar un botón de cierre (✕)
backgroundstring | string[]síColor de fondo de la tarjeta, o paradas de gradiente
revealThresholdnumbersíFracción de la lámina que debe rascarse (0–1) antes de que se revele la recompensa
coverCoversíLa capa de lámina. Sin una image, se muestra una pista de “rasca aquí” en el color de fondo
revealButtonButton (no action)noBotón “Revelar instantáneamente”
titleTextnoTítulo
messageTextnoTexto del cuerpo
rewardRewardsíEl premio oculto bajo la lámina
{
"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" }
}
}
}
}

Una tarjeta fijada al borde inferior, con un asa para arrastrar.

CampoTipoRequeridoDescripción
showClosebooleansíMostrar un botón de cierre (✕)
dimBackgroundbooleansíAtenuar la pantalla detrás de la hoja
backgroundstringsíColor de fondo de la hoja
imagestringnoImagen de cubierta
titleTextnoTítulo
messageTextnoTexto del cuerpo
buttonsButton[]síBotones debajo del texto (puede estar vacío)
{
"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" }
}
]
}
}

Una rueda de la fortuna con segmentos ponderados y un botón central.

CampoTipoRequeridoDescripción
showClosebooleansíMostrar un botón de cierre (✕)
backgroundstring | string[]síColor de fondo de la tarjeta, o paradas de gradiente
winIndexnumbersíÍndice (base 0) del segmento ganador
spinButtonButton (no action)síBotón central
titleTextnoTítulo
messageTextnoTexto del cuerpo
rewardRewardsíRecompensa por el giro ganador (alternativa para segmentos sin la suya propia)
loseTitleTextnoTítulo que se muestra en una pérdida
segmentsSegment[]síSegmentos de la rueda (el SDK espera 2–12)

Segmento:

CampoTipoRequeridoDescripción
messageTextsíEtiqueta del segmento
colorstringnoColor del segmento. Omitir para una paleta alternativa aplicada alrededor de la rueda
weightnumbersíTamaño relativo del segmento
rewardRewardnoRecompensa específica del 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 }
]
}
}

Diapositivas a pantalla completa con barras de progreso en la parte superior, similar a las historias de las redes sociales.

CampoTipoRequeridoDescripción
showClosebooleansíMostrar un botón de cierre (✕)
loopbooleansíReiniciar desde la primera diapositiva después de la última
itemsItem[]síDiapositivas (al menos 1)

Elemento de las historias:

CampoTipoRequeridoDescripción
titleTextnoTítulo
messageTextnoSubtítulo
imagestringnoImagen de fondo de la diapositiva
buttonsButton[]síBotones de CTA en la parte inferior (puede estar vacío)
durationnumbersíDuración de la diapositiva, en 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
}
]
}
}

Video a pantalla completa con texto y botones encima.

CampoTipoRequeridoDescripción
showClosebooleansíMostrar un botón de cierre (✕)
loopbooleansíRepetir la reproducción
mutedbooleansíEmpezar silenciado
urlstringsíURL del video (HLS o MP4)
posterstringnoPóster que se muestra antes de que comience la reproducción
fallbackstringnoImagen que se muestra si el video no se puede reproducir
titleTextnoTítulo
messageTextnoTexto del cuerpo
buttonsButton[]síBotones de CTA en la parte inferior (puede estar vacío)
{
"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" }
}
]
}
}

Localización

Anchor link to

Los in-apps nativos reutilizan exactamente el mismo mecanismo de localización que los Rich Media HTML: los valores de cadena en native-config.json pueden llevar marcadores de posición {{key|type|default}}, y las traducciones se encuentran en un archivo pushwoosh.json junto a él, en el mismo formato descrito en Añadir pushwoosh.json. Un marcador de posición puede aparecer en cualquier campo de cadena, a cualquier profundidad (un título, una etiqueta de botón, una URL de imagen, una URL de acción).

Contenido dinámico

Anchor link to

Los campos de texto — title, message, text del botón, reward.title/reward.message, y message del elemento/segmento — también aceptan Contenido dinámico y sintaxis Liquid: el mismo atajo {Tag|modifier|default} y las etiquetas Liquid {% %}/{{ }} utilizadas en el contenido de push y correo electrónico. Pushwoosh los resuelve por destinatario antes de que se envíe el mensaje, de la misma manera que lo hace para push y correo electrónico.

Al construir una plantilla en el editor nativo in-app del Panel de Control, los tokens insertados se renderizan como chips en la vista previa en vivo, y Guardar se bloquea si el Liquid de un campo de texto no se analiza correctamente.

Integración del SDK

Anchor link to

Una vez que agregue el módulo SDK nativo in-app a su aplicación, los mensajes se mostrarán automáticamente. No se requiere código adicional para mostrar mensajes activados por un push, Customer Journey, postEvent o la bandeja de entrada.

El SDK también expone una pequeña API para el control manual:

  • iOS: Pushwoosh.inApp (módulo PushwooshInApp)
  • Android: PushwooshInAppUi (módulo pushwoosh-inapp-ui)
CapacidadiOSAndroid
Mostrar una configuración directamente (pruebas/uso manual)Pushwoosh.inApp.present(config)PushwooshInAppUi.present(configJson)
Observar el ciclo de vida y los clicsdelegate (PWInAppMessageDelegate)delegate (InAppMessageDelegate)
Comprobar si algo está en pantallaisPresentingisPresenting
Descartar lo que se muestra actualmentedismiss()dismiss()
Pausar / reanudar la visualizaciónisPausedisPaused
Aplicar la limitación de maxDisplays / cooldownsetFrequencyCapEnabled(_:)setFrequencyCapEnabled(...)

Callbacks del delegado (todos se activan en el hilo principal): shouldDisplay (devuelve false para suprimir un mensaje antes de que se muestre, por ejemplo, en una pantalla de pago), willPresent, didPresent, didClose y clickedAction (se activa cuando el usuario toca una acción de url, antes de que se abra la URL).

iOS informa adicionalmente de rewardRevealed y rewardClaimed para las plantillas gamificadas scratchcard y spinwheel.

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