Recettes de personnalisation personalization-recipes

Sur cette page : recherchez des recettes de personnalisation prêtes à l’emploi pour les dates, les tableaux, les chaînes, la logique conditionnelle et les cas de périphérie de PQL que vous pouvez copier directement dans votre contenu Adobe Journey Optimizer.

Cette page fournit des modèles de personnalisation prêts à l’emploi pour les cas d’utilisation les plus courants dans Adobe Journey Optimizer. Tous les exemples utilisent la syntaxe de l’éditeur de personnalisation et peuvent être copiés directement dans un contenu d’e-mail, de SMS ou de notification push.

Pour obtenir une référence complète des fonctions disponibles, voir la section Fonctions d’assistance, Fonctions date/heure, Fonctions de chaîne et Fonctions de tableau.

TIP
Avant de copier des exemples, passez en revue les bonnes pratiques de personnalisation afin d’éviter les erreurs de syntaxe les plus courantes.

Recettes de date et d’heure date-time-recipes

Recette 1 : afficher la date courante dans un format lisible recipe-current-date

Utilisez formatDate avec getCurrentZonedDateTime() pour effectuer le rendu de la date du jour dans n’importe quel format :

{%= formatDate(getCurrentZonedDateTime(), "MMMM dd, yyyy") %}

Sortie (exemple) : April 11, 2026

Modèles de format courants :

Motif
Exemple de sortie
"dd/MM/yyyy"
11/04/2026
"MM/dd/yyyy"
04/11/2026
"EEEE, MMMM dd"
Saturday, April 11
"yyyy-MM-dd"
2026-04-11
NOTE
Utilisez des minuscules y (année civile) plutôt que des Y (année basée sur la semaine) pour éviter des résultats inattendus aux limites de l’année. Voir la section sur les caractères de motif pour obtenir une référence complète.

Recette 2 : compte à rebours jusqu’à une date d’expiration ou d’événement recipe-countdown

Utilisez dateDiff pour calculer le nombre de jours restants jusqu’à l’attribut de date de profil, puis effectuez son rendu dynamique :

{% let daysLeft = dateDiff(getCurrentZonedDateTime(), stringToDate(profile.loyalty.expiryDate)) %}
{%#if daysLeft > 0%}
Your reward points expire in {{daysLeft}} day{%#if daysLeft > 1%}s{%/if%}. Use them before they're gone!
{%else%}
Your reward points have expired.
{%/if%}

Sortie (exemple) : Your reward points expire in 7 days. Use them before they're gone!

Recette 3 : X jours avant une date de fin dynamique recipe-days-before

Pour calculer une date qui précède de X jours un attribut de profil (par exemple pour y faire référence dans le contenu ou les lignes d’objet), utilisez addDays avec un décalage négatif :

{%= formatDate(addDays(stringToDate(profile.subscription.endDate), -7), "MMMM dd, yyyy") %}

Sortie (exemple) : April 04, 2026 (7 jours avant le 11 avril)

Pour également définir une heure fixe dans la journée (par exemple, 9 h), combinez avec setHours :

{%= formatDate(setHours(addDays(stringToDate(profile.subscription.endDate), -7), 9), "dd/MM/yyyy HH:mm") %}

Recette 4 : afficher l’heure actuelle sous la forme HH:MM uniquement recipe-time-only

Utilisez extractHours et extractMinutes pour n’afficher que la partie temporelle, avec une protection contre les zéros initiaux pour les minutes :

{% let h = extractHours(getCurrentZonedDateTime()) %}
{% let m = extractMinutes(getCurrentZonedDateTime()) %}
Your appointment is at {{h}}:{%#if m < 10%}0{%/if%}{{m}}.

Sortie (exemple) : Your appointment is at 14:05.

Recette 5 : détecter un jour de week-end ou de semaine recipe-weekend

Utilisez dayOfWeek pour adapter le contenu en fonction de la journée. La fonction renvoie de 1 (lundi) à 7 (dimanche). Utilisez l’opérateur = unique (syntaxe PQL, non ==) :

{%#if dayOfWeek(getCurrentZonedDateTime()) = 6 or dayOfWeek(getCurrentZonedDateTime()) = 7%}
We're closed on weekends — our team will follow up on the next business day.
{%else%}
Our team will get back to you within 24 hours.
{%/if%}
NOTE
dayOfWeek() sert à adapter le contenu en fonction du jour. Pour acheminer différemment les profils dans un parcours en fonction du jour de la semaine, utilisez l’option intégrée Condition de temps → Jour de la semaine dans l’activité Condition du parcours. En savoir plus

Recettes de tableau et de boucle array-recipes

Recette 6 : répertorier tous les éléments d’un tableau de profils recipe-list-items

Utilisez {{#each}} pour effectuer une itération sur un tableau de profils et effectuer le rendu de chaque élément. Cette option n’est disponible que dans l’éditeur de personnalisation (e-mail, SMS, notification push) :

{{#each profile.purchases.recentItems}}
  - {{this.name}}: {{this.price}}&euro;
{{/each}}

Sortie (exemple) :

- Running shoes: 89&euro;
- Water bottle: 15&euro;
- Gym bag: 45&euro;
NOTE
{{#each}} n’est pas pris en charge dans l’activité de condition de parcours. Pour le filtrage de tableau par conditions, utilisez les fonctions de gestion des collections.

Recette 7 : afficher les N premiers éléments d’un tableau par prix recipe-first-n

Utilisez topN pour trier et récupérer les N premiers éléments selon un champ numérique. Puisque topN est une fonction PQL, affectez-la d’abord à une variable avec {% let %}, puis effectuez une boucle avec {{#each}} :

{% let topOrders = topN(profile.orders, price, 3) %}
{{#each topOrders}}
  {{this.name}} — {{this.price}}&euro;
{{/each}}
NOTE
topN(profile.orders, price, 3) trie les commandes par price dans l’ordre décroissant et renvoie les 3 premiers éléments. Il ne renvoie pas simplement les 3 premiers éléments dans l’ordre du tableau d’origine.

Ou utilisez head pour obtenir uniquement le premier élément :

{%= head(profile.purchases.recentItems).name %}

Recette 8 : effectuer un rendu conditionnel du contenu par élément de tableau recipe-conditional-loop

Utilisez {%#if%} à l’intérieur de {{#each}} pour effectuer le rendu de la sortie uniquement pour les éléments correspondants. Définissez un alias de boucle avec as |order| afin que l’évaluateur PQL puisse résoudre la référence d’attribut dans la condition :

{{#each profile.orders as |order|}}
  {%#if order.status = "pending"%}
  Order {{order.id}} is pending — we'll notify you when it ships.
  {%/if%}
{{/each}}
NOTE
this.status fonctionne dans les expressions Handlebars mais n’est pas résolu par l’évaluateur PQL dans {%#if%}. L’utilisation d’un alias de boucle nommé (par exemple, order) rend l’attribut disponible pour les contextes Handlebars et PQL.

Recettes de chaînes et de mise en forme string-recipes

Recette 9 : nettoyer une chaîne avec replaceAll et la réutiliser recipe-replaceall-reuse

replaceAll renvoie une nouvelle valeur, elle ne modifie pas l’original. Utilisez {% let %} pour stocker le résultat et le référencer plusieurs fois sans répéter l’appel de la fonction :

{% let cleanName = replaceAll(profile.person.name.firstName, "[^a-zA-Z]", "") %}
Hi {{cleanName}},
Your exclusive code is: WELCOME-{%= upperCase(cleanName) %}

Sortie (exemple) :

Hi John,
Your exclusive code is: WELCOME-JOHN

Recette 10 : ajouter un guillemet double à une valeur dans la sortie JSON recipe-json-quotes

Pour inclure un guillemet double littéral dans une chaîne (par exemple lors de la génération d’une sortie JSON pour une payload personnalisée), insérez une barre oblique inverse (\") dans l’échappement :

{ "greeting": "Hello \"{{profile.person.name.firstName}}\"" }

Sortie : { "greeting": "Hello \"John\"" }

Recette 11 : mettre en forme un composant de date en majuscules recipe-uppercase-date

Combinez formatDate à upperCase pour effectuer le rendu des noms des mois ou des jours en majuscules :

{%= upperCase(formatDate(getCurrentZonedDateTime(), "MMMM")) %}

Sortie (exemple) : APRIL

Pour une chaîne de date en majuscules complète :

{%= upperCase(formatDate(profile.person.birthDateTime, "EEEE MMMM dd yyyy")) %}

Sortie (exemple) : WEDNESDAY JANUARY 01 2020

Recettes de logique conditionnelle conditional-recipes

Recette 12 : IF/ELSEIF/ELSE dans le contenu personnalisé recipe-if-elseif

Utilisez {%#if%}, {%else if%} et {%else%} pour la logique conditionnelle à plusieurs branches. Ce modèle fonctionne dans le contenu et les fragments des e-mails :

{%#if profile.loyalty.tier = "gold"%}
As a Gold member, enjoy free shipping on all orders.
{%else if profile.loyalty.tier = "silver"%}
As a Silver member, enjoy free shipping on orders over &euro;50.
{%else%}
Join our loyalty program to unlock exclusive benefits.
{%/if%}

Recette 13 : affichage sécurisé des attributs NULL recipe-null-safe

Utilisez une version de secours conditionnelle pour éviter de rendre des valeurs vides lorsqu’un attribut de profil peut être nul ou manquant :

{%#if profile.person.name.firstName%}
Hi {{profile.person.name.firstName}},
{%else%}
Hi there,
{%/if%}

Ou inséré avec un modèle de style ternaire à l’aide de isEmpty :

Hi {%#if isEmpty(profile.person.name.firstName)%}valued customer{%else%}{{profile.person.name.firstName}}{%/if%},

Recettes de cas de périphérie de PQL pql-edge-cases

Recette 14 : référencer une clé d’attribut avec trait d’union recipe-hyphenated-key

Si le nom de votre champ de schéma XDM contient des traits d’union (par exemple, order-total, event-type), placez-le entre accents graves dans une expression PQL pour empêcher que le trait d’union ne soit interprété comme un opérateur de soustraction :

{%= profile.events.`order-total` > 100 %}
NOTE
Les accents graves ne sont pris en charge que dans les expressions PQL ({%= ... %}). Ils ne sont pas acceptés dans l’interpolation simple Handlebars ({{...}}). Si vous devez effectuer directement le rendu d’une valeur de champ avec trait d’union, évaluez-la via une expression PQL ou stockez-la dans une variable à l’aide de {% let %}.

Recette 15 : référencer un identifiant d’événement numérique dans un attribut de contexte recipe-numeric-event-id

Lors de l’utilisation d’un événement de contexte de parcours dont l’ID est une chaîne numérique (par exemple, 1697323153), placez l’ID entre accents graves et utilisez {% let %} avec toDateTime() et formatDate() :

{% let appointmentDate = formatDate(toDateTime(context.journey.events.`1697323153`.timestamp), "dd/MM/yyyy HH:mm") %}
Your appointment: {{appointmentDate}}

Sortie (exemple) : Your appointment: 18/03/2026 14:30

Recette 16 : coercition de type : comparer un champ de chaîne à un nombre recipe-type-coercion

PQL a un type fort. Lorsqu’un champ de profil est stocké sous la forme d’une chaîne, mais que vous devez le comparer numériquement, convertissez-le d’abord avec stringToNumber() :

{%= stringToNumber(profile.loyalty.pointsBalance) > 500 %}

Pour les champs booléens stockés sous forme de chaînes :

{%= toBool(profile.consents.email.val) = true %}
AI Knowledge Reference

This section contains structured knowledge intended to support interpretation, retrieval, and question answering related to this topic.

For complete understanding, this information should be combined with the documentation on this page. Neither source is intended to stand alone; the page describes the feature, while this section provides additional context that helps disambiguate terminology, intent, applicability, and constraints.

  • TL;DR: This page provides 16 ready-to-use copy-paste personalization recipes covering dates, arrays, strings, conditional logic, and PQL edge cases for use in Journey Optimizer email, SMS, and push content.

Intents:

  • Copy ready-to-use date/time patterns (current date, countdown, offset dates, time display, weekend detection)
  • Copy array and loop patterns (list items, top N items, conditional per-item rendering)
  • Copy string formatting patterns (clean and reuse strings, JSON quoting, uppercase date components)
  • Copy conditional logic patterns (multi-branch if/elseif/else, null-safe attribute display)
  • Handle PQL edge cases (hyphenated keys, numeric event IDs, type coercion)

Glossary:

  • Personalization recipe: A ready-to-use copy-paste pattern for a common personalization use case, using personalization editor syntax. (product-specific)
  • formatDate: A function that converts a date to a string using a specified format pattern (e.g. "MMMM dd, yyyy").
  • dateDiff: A function that computes the numeric difference between two dates.
  • getCurrentZonedDateTime(): A function returning the current date and time in a time-zone-aware format.
  • topN: A PQL function that sorts an array by a specified numeric field in descending order and returns the top N items. Must be assigned via {% let %} before use in a Handlebars loop.
  • {% let %}: Handlebars variable assignment syntax for storing computed values; required when a PQL function result needs to be referenced in a subsequent Handlebars context.
  • replaceAll: A string function that replaces all occurrences of a pattern in a string; returns a new string without modifying the original.

Guardrails:

  • {{#each}} is not supported in the journey condition activity; use collection management functions for array filtering in journey conditions.
  • Backtick escaping for hyphenated attribute keys is only supported inside PQL expressions ({%= ... %}); backticks are not accepted in plain Handlebars interpolation ({{...}}).
  • topN is a PQL function and must be assigned to a {% let %} variable before being used as a {{#each}} loop target.
  • When using a loop variable inside a {%#if%} block, declare a named loop alias (e.g. as |order|); this.status is not resolved by the PQL evaluator inside {%#if%}.
  • Use lowercase y in formatDate patterns for calendar year; Y (week-based year) may produce unexpected values at year-end boundaries.

Terminology:

  • Canonical name: personalization recipe — variants: pattern, template, example, copy-paste pattern
  • Do not confuse: {%= ... %} (PQL expression syntax — evaluated, returns a computed value) ≠ {{...}} (Handlebars interpolation — renders a variable or template expression)
  • Do not confuse: {%#if%} / {%/if%} (Journey Optimizer conditional syntax, percent-curly braces) ≠ {{#if}} / {{/if}} (standard Handlebars conditional syntax)
  • Do not confuse: topN(array, field, n) (sorts by field descending, returns top N) ≠ head(array) (returns only the first item from the array)
  • Do not confuse: dayOfWeek() (used in message content to adapt display based on day) ≠ the journey Time condition “Day of the week” option (used in the journey Condition activity to route profiles differently)
  • Do not confuse: date format pattern y (calendar year — correct) ≠ Y (week-based year — may produce unexpected results at year boundaries)

FAQ:

  • Q: What is the difference between {%= ... %} and {{...}} in personalization?{%= ... %} is PQL expression syntax — it is evaluated and returns a computed value (number, string, boolean). {{...}} is Handlebars interpolation — it renders a variable or template expression. Both appear in personalization content but serve different purposes.
  • Q: How do I use a PQL function result inside a Handlebars {{#each}} loop? — Assign the PQL function result to a variable using {% let variableName = pqlFunction(...) %}, then use {{#each variableName}} to iterate over it.
  • Q: Can {{#each}} be used in a journey condition activity? — No. {{#each}} is available only in message personalization content (email, SMS, push). For array filtering in journey conditions, use collection management functions.
  • Q: How do I reference a field whose name contains a hyphen? — Wrap the hyphenated key in backticks inside a PQL expression: {%= profile.events.`order-total` > 100 %}. Backticks are not supported in plain Handlebars interpolation — use a {% let %} variable as an intermediate step if needed.
  • Q: Why does topN need {% let %} before a {{#each}} loop?topN is a PQL function that returns a PQL list. Assigning it to a {% let %} variable makes the result available in the Handlebars context so it can be iterated with {{#each}}.
recommendation-more-help
journey-optimizer-help