Passer au contenu

Syntaxe des modèles in-app natifs

Les in-apps natifs sont rendus directement par le SDK. Aucune WebView n’est impliquée. Au lieu d’une page index.html, la ressource ZIP contient un fichier native-config.json qui décrit le message sous forme de données structurées (type de mise en page, textes, couleurs, images, boutons). Le SDK lit ce fichier et dessine la vue native correspondante, ce qui offre des animations plus fluides et de meilleures performances qu’une page web intégrée.

Ce guide documente le schéma native-config.json : champs, types et exemples pour chaque type d’affichage. Pour le format classique basé sur HTML, consultez la Syntaxe des modèles Rich Media.

Prérequis

Anchor link to

Les in-apps natifs nécessitent :

  • iOS : SDK 7.2.0 ou version ultérieure (7.2.1+ pour bannière, carrousel et feuille)
  • Android : SDK 6.10.0 ou version ultérieure (6.10.1+ pour bannière, carrousel et feuille)

Tous les types d’affichage ne sont pas encore disponibles sur les deux plateformes. Vérifiez la Compatibilité des plateformes avant de vous fier à un format spécifique.

Compatibilité des plateformes

Anchor link to
Type d’affichage
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✅Pas encore disponible
scratchcard✅Pas encore disponible
spinwheel✅Pas encore disponible

Structure du modèle

Anchor link to

Un modèle in-app natif est une archive ZIP, identique à un modèle Rich Media classique, à l’exception que la racine contient un fichier native-config.json au lieu de index.html :

<template>.zip
├── native-config.json ← requis, mise en page et contenu
├── pushwoosh.json ← optionnel, localisation (voir ci-dessous)

Les images et vidéos référencées depuis native-config.json (image, poster, fallback, url sur pip/video) doivent être des URL HTTPS absolues. Le SDK les charge via le réseau. Il ne lit pas les fichiers locaux de l’archive.

La configuration elle-même est un objet JSON unique :

{ "displayType": "<type>", "<type>": { /* bloc de contenu pour ce type */ } }

displayType sélectionne l’un des dix formats ci-dessous. L’objet sous la clé correspondante contient le contenu de ce format. Une configuration avec un displayType inconnu, un bloc de contenu manquant ou une liste requise vide (items pour carousel/stories, segments pour spinwheel) est invalide. Le SDK ignore son affichage plutôt que de rendre une mise en page défectueuse.

Les paramètres de livraison (dates de début/fin et limitation de la fréquence) ne font pas partie de native-config.json. Ils sont configurés de la même manière que pour tout autre in-app, dans l’étape des Paramètres d’affichage de la campagne.

La limitation de la fréquence nécessite en outre une activation explicite côté SDK pour prendre effet sur les in-apps natifs. Voir Intégration SDK.

Chaque valeur de couleur est une chaîne hexadécimale CSS : #RGB, #RGBA, #RRGGBB ou #RRGGBBAA. Le # initial est requis dans les quatre formes.

Blocs de construction partagés

Anchor link to

Ces objets plus petits sont réutilisés dans plusieurs types d’affichage.

ChampTypeRequisDescription
textstringouiLe contenu textuel
colorstringouiCouleur du texte
{ "text": "Spin for a garage perk", "color": "#FFFFFFFF" }
ChampTypeRequisDescription
colorstringouiCouleur de la bordure
radiusnumberouiRayon des coins, en points
{ "color": "#0E72E5FF", "radius": 12 }

Couverture

Anchor link to

Une image optionnelle sur une couleur de fond. Utilisé par fullscreen et scratchcard.

ChampTypeRequisDescription
imagestringnonURL de l’image de couverture
backgroundstringouiCouleur de fond affichée sous (ou à la place de) l’image
{ "image": "https://example.com/cover.jpg", "background": "#1A1A1EFF" }

Une union discriminée sur type :

VarianteChampsDescription
{ "type": "close" }AucunFerme l’in-app
{ "type": "url", "url": string }url requisOuvre une URL ou un deep link
{ "type": "url", "url": "pushwoosh://sale" }
ChampTypeRequisDescription
textTextouiÉtiquette du bouton
backgroundstringouiCouleur de remplissage du bouton
borderBorderouiBordure du bouton
actionActionouiAction déclenchée lors de l’appui

spinButton (spinwheel) et revealButton (scratchcard) utilisent la même forme sans action. Leur comportement (faire tourner la roue, révéler la carte) est intégré.

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

Récompense

Anchor link to

Le panneau de récompense affiché par scratchcard et spinwheel. Une récompense valide a un title ou un code.

ChampTypeRequisDescription
titleTextnonTitre de la récompense
messageTextnonDescription de la récompense
codestringnonCode promo, affiché avec un bouton de copie
buttonButtonnonBouton de confirmation avec sa propre 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" }
}
}

Types d’affichage

Anchor link to

Une barre compacte ancrée en haut ou en bas de l’écran.

ChampTypeRequisDescription
showClosebooleanouiAfficher un bouton de fermeture (✕)
positiontop | bottomouiBord de l’écran
backgroundstringouiCouleur de fond de la barre
imagestringnonVignette à gauche
titleTextnonTitre sur une seule ligne, tronqué par des points de suspension
messageTextnonCorps du texte, jusqu’à 2 lignes
actionActionouiDéclenchée lorsque la barre elle-même est touchée
autoDismissnumbernonFermeture automatique après ce nombre de secondes. Omettre pour la conserver jusqu’à sa fermeture
{
"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 ensemble de cartes plein écran, balayables, avec des points indicateurs de page.

ChampTypeRequisDescription
showClosebooleanouiAfficher un bouton de fermeture (✕)
itemsItem[]ouiCartes (au moins 1)

Élément du carrousel :

ChampTypeRequisDescription
titleTextnonTitre de la carte
messageTextnonSous-titre de la carte
imagestringnonImage de la carte
actionActionnonDéclenchée lorsque la carte est touchée
{
"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

Une image de couverture bord à bord avec du texte et des boutons par-dessus.

ChampTypeRequisDescription
showClosebooleanouiAfficher un bouton de fermeture (✕)
coverCoverouiImage et couleur de fond
titleTextnonTitre
messageTextnonCorps du texte
buttonsButton[]ouiBoutons en bas (peut être vide)
{
"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" }
}
]
}
}

Une carte centrée.

ChampTypeRequisDescription
showClosebooleanouiAfficher un bouton de fermeture (✕)
dimBackgroundbooleanouiAssombrir l’écran derrière la carte
backgroundstringouiCouleur de fond de la carte
imagestringnonImage de couverture
titleTextnonTitre
messageTextnonCorps du texte
buttonsButton[]ouiBoutons sous le texte (peut être vide)
{
"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" }
}
]
}
}

Une fenêtre vidéo flottante en picture-in-picture ancrée dans un coin de l’écran.

ChampTypeRequisDescription
showClosebooleanouiAfficher un bouton de fermeture (✕)
positionbottom-right | bottom-left | top-right | top-leftouiCoin de l’écran
loopbooleanouiLecture en boucle
mutedbooleanouiDémarrer en sourdine
urlstringouiURL de la vidéo
posterstringnonAffiche montrée avant le début de la lecture
fallbackstringnonImage montrée si la lecture de la vidéo échoue
widthnumberouiLargeur de la fenêtre en pourcentage de la largeur de l’écran, limitée entre 15 et 70
aspectRationumberouiRapport hauteur/largeur de la fenêtre
borderRadiusnumbernonRayon des coins de la fenêtre, en points
actionActionnonDéclenchée lorsque la fenêtre elle-même est touchée

Il n’y a pas de boutons configurables sur pip. Les contrôles de la fenêtre (agrandir en plein écran, sourdine, fermer) sont fournis par le système.

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

Une carte avec la récompense cachée sous une couche de film à gratter.

ChampTypeRequisDescription
showClosebooleanouiAfficher un bouton de fermeture (✕)
backgroundstring | string[]ouiCouleur de fond de la carte, ou arrêts de dégradé
revealThresholdnumberouiFraction du film qui doit être grattée (0–1) avant que la récompense ne se révèle
coverCoverouiLa couche de film. Sans image, une indication « grattez ici » est affichée sur la couleur de fond
revealButtonButton (no action)nonBouton « Révéler instantanément »
titleTextnonTitre
messageTextnonCorps du texte
rewardRewardouiLe prix caché sous le film
{
"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" }
}
}
}
}

Une carte épinglée au bord inférieur, avec une poignée de glissement.

ChampTypeRequisDescription
showClosebooleanouiAfficher un bouton de fermeture (✕)
dimBackgroundbooleanouiAssombrir l’écran derrière la feuille
backgroundstringouiCouleur de fond de la feuille
imagestringnonImage de couverture
titleTextnonTitre
messageTextnonCorps du texte
buttonsButton[]ouiBoutons sous le texte (peut être vide)
{
"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" }
}
]
}
}

Une roue de la fortune avec des segments pondérés et un bouton central.

ChampTypeRequisDescription
showClosebooleanouiAfficher un bouton de fermeture (✕)
backgroundstring | string[]ouiCouleur de fond de la carte, ou arrêts de dégradé
winIndexnumberouiIndex (base 0) du segment gagnant
spinButtonButton (no action)ouiBouton central
titleTextnonTitre
messageTextnonCorps du texte
rewardRewardouiRécompense pour le tour gagnant (solution de repli pour les segments sans la leur)
loseTitleTextnonTitre affiché en cas de perte
segmentsSegment[]ouiSegments de la roue (le SDK attend 2–12)

Segment :

ChampTypeRequisDescription
messageTextouiÉtiquette du segment
colorstringnonCouleur du segment. Omettre pour une palette de secours appliquée autour de la roue
weightnumberouiTaille relative du segment
rewardRewardnonRécompense spécifique au segment
{
"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 }
]
}
}

Diapositives en plein écran avec des barres de progression en haut, similaires aux stories des réseaux sociaux.

ChampTypeRequisDescription
showClosebooleanouiAfficher un bouton de fermeture (✕)
loopbooleanouiRedémarrer à partir de la première diapositive après la dernière
itemsItem[]ouiDiapositives (au moins 1)

Élément des stories :

ChampTypeRequisDescription
titleTextnonTitre
messageTextnonSous-titre
imagestringnonImage de fond de la diapositive
buttonsButton[]ouiBoutons CTA en bas (peut être vide)
durationnumberouiDurée de la diapositive, en secondes
{
"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
}
]
}
}

Vidéo en plein écran avec du texte et des boutons par-dessus.

ChampTypeRequisDescription
showClosebooleanouiAfficher un bouton de fermeture (✕)
loopbooleanouiLecture en boucle
mutedbooleanouiDémarrer en sourdine
urlstringouiURL de la vidéo (HLS ou MP4)
posterstringnonAffiche montrée avant le début de la lecture
fallbackstringnonImage montrée si la lecture de la vidéo échoue
titleTextnonTitre
messageTextnonCorps du texte
buttonsButton[]ouiBoutons CTA en bas (peut être vide)
{
"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" }
}
]
}
}

Localisation

Anchor link to

Les in-apps natifs réutilisent exactement le même mécanisme de localisation que les Rich Media HTML : les valeurs de chaîne dans native-config.json peuvent contenir des placeholders {{key|type|default}}, et les traductions se trouvent dans un fichier pushwoosh.json à côté, dans le même format décrit dans Ajout de pushwoosh.json. Un placeholder peut apparaître dans n’importe quel champ de chaîne, à n’importe quelle profondeur (un titre, une étiquette de bouton, une URL d’image, une URL d’action).

Contenu dynamique

Anchor link to

Les champs de texte — title, message, text du bouton, reward.title/reward.message, et message de l’élément/segment — acceptent également le Contenu dynamique et la syntaxe Liquid : le même raccourci {Tag|modifier|default} et les balises Liquid {% %}/{{ }} utilisés dans le contenu des notifications push et des e-mails. Pushwoosh les résout pour chaque destinataire avant l’envoi du message, de la même manière que pour les notifications push et les e-mails.

Lors de la création d’un modèle dans l’éditeur d’in-app natif du Control Panel, les jetons insérés s’affichent sous forme de puces dans l’aperçu en direct, et la Sauvegarde est bloquée si le Liquid d’un champ de texte ne peut pas être analysé.

Intégration SDK

Anchor link to

Une fois que vous avez ajouté le module SDK in-app natif à votre application, les messages s’affichent automatiquement. Aucun code supplémentaire n’est requis pour afficher les messages déclenchés par une notification push, un Customer Journey, postEvent ou la boîte de réception.

Le SDK expose également une petite API pour un contrôle manuel :

  • iOS : Pushwoosh.inApp (module PushwooshInApp)
  • Android : PushwooshInAppUi (module pushwoosh-inapp-ui)
CapacitéiOSAndroid
Afficher une configuration directement (test/utilisation manuelle)Pushwoosh.inApp.present(config)PushwooshInAppUi.present(configJson)
Observer le cycle de vie et les clicsdelegate (PWInAppMessageDelegate)delegate (InAppMessageDelegate)
Vérifier si quelque chose est à l’écranisPresentingisPresenting
Fermer ce qui est actuellement affichédismiss()dismiss()
Mettre en pause / reprendre l’affichageisPausedisPaused
Appliquer la limitation maxDisplays / cooldownsetFrequencyCapEnabled(_:)setFrequencyCapEnabled(...)

Callbacks du délégué (tous déclenchés sur le thread principal) : shouldDisplay (retournez false pour supprimer un message avant qu’il ne s’affiche, par exemple sur un écran de paiement), willPresent, didPresent, didClose, et clickedAction (déclenché lorsque l’utilisateur appuie sur une action url, avant l’ouverture de l’URL).

iOS signale en plus rewardRevealed et rewardClaimed pour les modèles ludiques scratchcard et spinwheel.

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