Passer au contenu

Syntaxe des modèles d'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 de Rich Media.

Prérequis

Anchor link to

Les in-apps natifs nécessitent :

  • iOS : SDK 7.2.0 ou ultérieur (7.2.1+ pour bannière, carrousel et feuille)
  • Android : SDK 6.10.0 ou ultérieur (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 le Support des plateformes avant de vous fier à un format spécifique.

Support 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+
videoPas encore disponible
pipPas encore disponible
scratchcardPas encore disponible
spinwheelPas encore disponible

Structure du modèle

Anchor link to

Un modèle d’in-app natif est une archive ZIP, identique à un modèle de 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 plafonnement 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, à l’étape Paramètres d’affichage de la campagne.

Le plafonnement 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 du 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": "Tournez pour un avantage garage", "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 lien profond (deep link)
{ "type": "url", "url": "pushwoosh://sale" }
ChampTypeRequisDescription
textTextouiÉtiquette du bouton
backgroundstringouiCouleur de remplissage du bouton
borderBorderouiBordure du bouton
actionActionouiAction déclenchée à 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": "Réserver un essai", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://sale" }
}

Récompense

Anchor link to

Le panneau de prix 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, rendu avec un bouton de copie
buttonButtonnonBouton de confirmation avec sa propre action
{
"title": { "text": "20 % de réduction sur le detailing", "color": "#111111FF" },
"message": { "text": "Valable pour toute réservation de detailing complet ce mois-ci.", "color": "#555555FF" },
"code": "APEX20",
"button": {
"text": { "text": "Réserver le 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 au bord supérieur ou inférieur 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é avec 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": "L'Alpine A110 vient de sortir", "color": "#FFFFFFFF" },
"message": { "text": "L'icône poids plume — touchez pour voir la configuration", "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 de 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": "V8 biturbo de 585 ch — vient d'arriver", "color": "#FFFFFFFF" },
"action": { "type": "url", "url": "pushwoosh://product/n6fx" }
},
{
"image": "https://example.com/card-2.jpg",
"title": { "text": "Alpine A110", "color": "#FFFFFFFF" },
"message": { "text": "L'icône poids plume — allocation limitée", "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": "Le cheval cabré, réimaginé.", "color": "#EBEBEBFF" },
"buttons": [
{
"text": { "text": "Réserver maintenant", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 8 },
"action": { "type": "url", "url": "pushwoosh://sale" }
},
{
"text": { "text": "Pas maintenant", "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": "La GT R est arrivée", "color": "#4B5057FF" },
"message": { "text": "585 ch — maintenant dans le showroom.", "color": "#4B5057FF" },
"buttons": [
{
"text": { "text": "Réserver un essai", "color": "#FFFFFFFF" },
"background": "#0E72E5FF",
"border": { "color": "#0E72E5FF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://sale" }
},
{
"text": { "text": "Pas maintenant", "color": "#4B5057FF" },
"background": "#FFFFFFFF",
"border": { "color": "#4B5057FF", "radius": 12 },
"action": { "type": "close" }
}
]
}
}

Une fenêtre vidéo flottante en Picture-in-Picture (incrustation d’image) ancrée à 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 affiché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, mettre en 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": "Révéler sans gratter", "color": "#3A1C71FF" },
"background": "#F2DFF5FF",
"border": { "color": "#F2DFF5FF", "radius": 10 }
},
"title": { "text": "Votre récompense de fidélité", "color": "#FFFFFFFF" },
"message": { "text": "Grattez le film pour révéler l'avantage garage de cette semaine.", "color": "#F2DFF5FF" },
"reward": {
"title": { "text": "20 % de réduction sur le detailing", "color": "#111111FF" },
"message": { "text": "Valable pour toute réservation de detailing complet ce mois-ci.", "color": "#555555FF" },
"code": "APEX20",
"button": {
"text": { "text": "Réserver le 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": "Votre devis est prêt", "color": "#000000FF" },
"message": { "text": "Rachat garanti pour votre A110 : 68 500 $.", "color": "#000000FF" },
"buttons": [
{
"text": { "text": "Obtenir un devis garanti", "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 leur propre récompense)
loseTitleTextnonTitre affiché en cas de perte
segmentsSegment[]ouiSegments de la roue (le SDK attend entre 2 et 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": "TOURNEZ", "color": "#1B1B46FF" },
"background": "#F2C94CFF",
"border": { "color": "#D9A02BFF", "radius": 36 }
},
"title": { "text": "Tournez pour un avantage garage", "color": "#FFFFFFFF" },
"message": { "text": "Un tour — chaque part est gagnante cette semaine.", "color": "#E3D9F2FF" },
"reward": {
"title": { "text": "Vous avez gagné un avantage garage !", "color": "#FFFFFFFF" },
"code": "APEXPERK",
"button": {
"text": { "text": "Réclamer", "color": "#FFFFFFFF" },
"background": "#5B2B8FFF",
"border": { "color": "#5B2B8FFF", "radius": 12 },
"action": { "type": "close" }
}
},
"segments": [
{ "message": { "text": "5 % de réduction", "color": "#FFFFFFFF" }, "color": "#5856D6FF", "weight": 1 },
{
"message": { "text": "20 % de réduction", "color": "#FFFFFFFF" },
"color": "#30B0C7FF",
"weight": 1,
"reward": {
"title": { "text": "20 % de réduction sur votre prochain service", "color": "#FFFFFFFF" },
"code": "SPIN20",
"button": {
"text": { "text": "Réclamer l'offre de service", "color": "#FFFFFFFF" },
"background": "#30B0C7FF",
"border": { "color": "#30B0C7FF", "radius": 12 },
"action": { "type": "url", "url": "pushwoosh://service" }
}
}
},
{ "message": { "text": "Lavage gratuit", "color": "#FFFFFFFF" }, "color": "#FF2D55FF", "weight": 1 }
]
}
}

Diapositives 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 de 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": "L'édition spéciale Green Hell", "color": "#FFFFFFFF" },
"buttons": [
{
"text": { "text": "Configurez la vôtre", "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": "La légende poids plume, réincarnée", "color": "#FFFFFFFF" },
"buttons": [],
"duration": 4
}
]
}
}

Vidéo 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 affiché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": "La révélation", "color": "#FFFFFFFF" },
"message": { "text": "Regardez-la bouger avant tout le monde.", "color": "#EBEBEBFF" },
"buttons": [
{
"text": { "text": "Découvrir la gamme", "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 Ajouter 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).

Intégration du SDK

Anchor link to

Une fois que vous avez ajouté le module SDK pour 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 un 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 le plafonnement 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 ludifiés scratchcard et spinwheel.

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