Syntaxe de personnalisation personalization-syntax

Sur cette page : découvrez la syntaxe de personnalisation Handlebars et PQL dans Adobe Journey Optimizer, y compris les règles générales, les mots-clés réservés, la coercition de type, les espaces de noms disponibles et les bonnes pratiques.

Dans Journey Optimizer, la personnalisation utilise deux syntaxes complémentaires qui fonctionnent ensemble dans la même expression :

  • Handlebars ({{...}}) : utilisé pour effectuer le rendu des attributs de profil, passer en boucle sur des tableaux et appeler des assistants de blocs. Reportez-vous à la documentation HandlebarsJS pour obtenir une référence complète.
  • Profile Query Language (PQL) ({%= ... %}) : utilisé pour appeler des fonctions intégrées (par exemple upperCase(), formatDate(), dateDiff()) et évaluer des expressions conditionnelles.

Il est essentiel de comprendre le contexte dans lequel vous vous trouvez pour éviter les erreurs d’exécution. Par exemple, un appel de fonction PQL placé dans {{...}} échouera, car Handlebars tente de le résoudre en tant qu’assistant plutôt que de l’évaluer en tant qu’expression PQL.

Exemples :

Cas d’utilisation
Syntaxe
Effectuer le rendu d’un attribut de profil
{{profile.person.name.firstName}}
Appeler une fonction PQL
{%= upperCase(profile.person.name.firstName) %}
Bloc conditionnel
{%#if profile.loyalty.tier = "gold"%}...{%/if%}
Boucle sur un tableau
{{#each profile.orders}}...{{/each}}

La structure des attributs est définie dans un schéma XDM Adobe Experience Platform. En savoir plus.

TIP
Pour les expressions prêtes à l’emploi qui appliquent ces syntaxes à des scénarios réels (mise en forme des dates, comptes à rebours, secours conditionnels, etc.), consultez la page Recettes de personnalisation.

Règles générales de syntaxe general-rules

  • Les identifiants peuvent être n’importe quel caractère Unicode, à l’exception des caractères spéciaux suivants, qui sont réservés à la syntaxe Handlebars :

    code language-none
    Whitespace ! " # % & ' ( ) * + , . / ; < = > @ [ \ ] ^ ` { | } ~
    
  • La syntaxe est sensible à la casse.

  • Les mots true, false, null et undefined ne sont autorisés que dans la première partie d’une expression de chemin.

  • Dans Handlebars, les valeurs renvoyées par {{expression}} se caractérisent par un échappement HTML. Si l’expression contient &, la sortie avec échappement HTML renvoyée est générée sous la forme &amp;. Si vous ne souhaitez pas que Handlebars effectue l’échappement d’une valeur, utilisez trois accolades au lieu de deux.

    Supposons que la valeur du champ profile.person.name soit « Mark & Mary ». Le {{profile.person.name}} de syntaxe affiche Mark &amp; Mary, tandis que {{{profile.person.name}}} affiche Mark & Mary.

  • En ce qui concerne les arguments de fonctions littérales, l’analyseur de langage de création de modèles ne prend pas en charge la barre oblique inverse sans échappement (\). Ce caractère doit avoir fait l’objet d’un échappement avec une barre oblique inverse supplémentaire (\). Exemple:

    {%= regexGroup("abc@xyz.com","@(\\w+)", 1)%}

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

    code language-handlebars
    { "message": "Hello \"{{profile.person.name.firstName}}\"" }
    

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

    Vous pouvez également utiliser la triple accolade {{{ }}} pour générer une valeur HTML sans échappement lorsque la valeur elle-même contient des caractères spéciaux que vous ne souhaitez pas encoder en HTML.

Mots-clés réservés reserved-keywords

Certains mots-clés sont réservés dans PQL (Profile Query Language) et ne peuvent pas être utilisés directement comme noms de champ ou de variable dans les expressions de personnalisation. Si votre schéma XDM contient des champs dont les noms correspondent à des mots-clés réservés, vous devez leur appliquer une séquence d’échappement à l’aide d’accents graves (`) pour les référencer dans vos expressions.

Les mots-clés réservés sont les suivants :

  • Général : let, export, to, as, this, last, next, now, NOW, today, yesterday, tomorrow, from, FROM, From, before, BEFORE, Before, after, AFTER, After,
  • Unités de temps : millisecond, milliseconds, second, seconds, minute, minutes, hour, hours, day, days, week, weeks, month, months, year, years, decade, decades, century, centuries, millennium, millennia,
  • Opérateurs booléens et logiques : true, TRUE, True, false, FALSE, False, not, NOT, Not, and, AND, And, or, OR, Or, null, NULL, Null,

Exemple:

Si votre schéma de profil comporte un champ nommé next, vous devez l’encadrer de guillemets inversés :

{{profile.person.`next`.name}}

Sans les guillemets inversés, l’éditeur de personnalisation échouera lors de la validation et vous obtiendrez une erreur.

NOTE
L’échappement avec apostrophe inverse pour les mots-clés réservés s’applique à la fois aux chemins Handlebars {{...}} et aux expressions PQL {%= ... %}, car ces mots-clés sont réservés au niveau de la résolution du chemin. Cette approche est différente des noms de champ avec trait d’union, où l’échappement avec apostrophe inverse n’est pris en charge que dans les expressions PQL. Voir la section Clés d’attribut avec trait d’union.

Règles de syntaxe PQL pour les clés d’attribut spéciales pql-special-keys

En plus des mots-clés réservés, deux cas supplémentaires nécessitent une séquence d’échappement avec apostrophe inverse dans les expressions PQL.

Clés d’attribut avec trait d’union hyphenated-keys

Si votre schéma XDM contient des noms de champ avec des tirets (par exemple my-field, event-type) ou des noms commençant par des chiffres ou en contenant, placez la clé entre apostrophes inverses dans les expressions PQL :

{%= profile.events.`order-total` > 100 %}
NOTE
L’échappement avec apostrophes inverses n’est pris en charge que dans les expressions PQL ({%= ... %}). Il n’est pas pris en charge dans l’interpolation Handlebars ({{...}}). Toutefois, les noms de champ avec tiret peuvent être référencés directement dans les blocs {{...}} (par exemple {{profile.my-custom-field}}). Seule la syntaxe des apostrophes inverses ne fonctionne pas dans ce cas.

Sans apostrophes inverses dans une expression PQL, le trait d’union est interprété comme un opérateur de soustraction et provoque une erreur de syntaxe PQL.

Identifiants d’événements numériques dans les attributs de contexte numeric-event-ids

Lors du référencement d’attributs d’événements de contexte où l’identifiant d’événement est un nombre (par exemple, 1697323153), placez-le entre apostrophes inverses. Cela s’applique également aux fonctions internes telles que formatDate() :

{% let ts = formatDate(toDateTime(context.journey.events.`1697323153`.timestamp), "dd/MM/yyyy") %}
{{ts}}

Coercition de type type-coercion

PQL a un type fort. Lors de la comparaison ou de la transmission de valeurs, les deux côtés doivent être du même type. Cas courants :

Scénario
Solution
Valeur numérique stockée sous forme de chaîne
Utiliser stringToNumber() avant l’arithmétique ou la comparaison : {%= stringToNumber(profile.loyalty.pointsBalance) > 500 %}
Entier stocké sous forme de chaîne
Utiliser string_to_integer() ou stringToNumber() avant l’arithmétique
Booléen stocké sous forme de chaîne
Utilisez toBool() pour la conversion : {%= toBool(profile.consents.email.val) = true %}

Espaces de noms disponibles namespaces

  • Profile

    Cet espace de noms vous permet de référencer tous les attributs définis dans le schéma de profil décrit dans la documentation Modèle de données Adobe Experience Platform (XDM).

    Les attributs doivent être définis dans le schéma avant d’être référencés dans un bloc de personnalisation Journey Optimizer.

    Pour plus d’informations sur l’utilisation des attributs de profil dans des conditions, consultez cette section.

    accordion
    Exemples de références
    • {{profile.person.name.fullName}}
    • {{profile.person.name.firstName}}
    • {{profile.person.gender}}
    • {{profile.personalEmail.address}}
    • {{profile.mobilePhone.number}}
    • {{profile.homeAddress.city}}
    • {{profile.faxPhone.number}}
  • Audience

    Pour en savoir plus sur le service de segmentation, consultez cette documentation.

  • Offres

    Cet espace de noms vous permet de référencer les décisions d’offre existantes.

    Pour référencer une offre, vous devez déclarer un chemin avec les différentes informations qui définissent une offre. Ce chemin possède la structure suivante :

    offers.Type.[Placement Id].[Activity Id].Attribute

    où :

    • offers identifie l’expression de chemin appartenant à l’espace de noms de l’offre.
    • Type détermine le type de représentation de l’offre. Les valeurs possibles sont les suivantes : image, html et text.
    • Placement Id et Activity Id sont des identifiants d’emplacement et d’activité.
    • Attributes sont des attributs spécifiques à l’offre qui dépendent du type d’offre. Exemple : deliveryUrl pour les images

    Pour plus d’informations sur l’API Decisions et sur la représentation des offres, consultez cette page.

    Toutes les références sont validées par rapport au schéma d’offres avec un mécanisme de validation décrit sur cette page.

    accordion
    Exemples de références
    • Emplacement où l’image est hébergée :

      offers.image.[offers:xcore:offer-placement:126f767d74b0da80].[xcore:offer-activity:125e2c6889798fd9].deliveryUrl

    • URL de la cible lorsque vous cliquez sur l’image :

      offers.image.[offers:xcore:offer-placement:126f767d74b0da80].[xcore:offer-activity:125e2c6889798fd9].linkUrl

    • Contenu textuel de l’offre provenant du moteur de décision :

      offers.text.[offers:xcore:offer-placement:126f767d74b0da80].[xcore:offer-activity:125e2c6889798fd9].content

    • Contenu HTML de l’offre provenant du moteur de décision :

      offers.html.[offers:xcore:offer-placement:126f767d74b0da80].[xcore:offer-activity:125e2c6889798fd9].content

Assistants helpers-all

Un assistant Handlebars est un identifiant simple qui peut être suivi de paramètres. Chaque paramètre est une expression Handlebars. Ces assistants sont accessibles depuis n’importe quel contexte dans un modèle.

Ces assistants de bloc sont identifiés par un # placé devant le nom de l’assistant et une / correspondante doit être placée à la fin avec le même nom.

Les blocs sont des expressions qui ont une ouverture ({{# }}) et une fermeture ({{/}}) de bloc.

Pour plus d’informations sur les fonctions d’assistant, consultez cette section.

Types littéraux literal-types

Adobe Journey Optimizer prend en charge les types littéraux suivants :

Littéral
Définition
Chaîne
Un type de données composé de caractères entourés par des guillemets doubles.
Exemples : "prospect", "jobs", "articles"
Booléen
Un type de données qui est soit vrai soit faux.
Entier
Un type de données représentant un nombre entier. Ce nombre peut être positif, négatif ou nul.
Exemples : -201, 0, 412
Tableau
Un type de données composé d’un groupe d’autres valeurs littérales. Elle utilise des crochets pour regrouper et des virgules pour délimiter les différentes valeurs.
Remarque : vous ne pouvez pas accéder directement aux propriétés des éléments dans un tableau.
Exemples : [1, 4, 7], ["US", "FR"]
CAUTION
L'utilisation de la variable xEvent n'est pas disponible dans les expressions de personnalisation. Toute référence à xEvent entraîne des échecs de validation.

Bonnes pratiques best-practices

Consultez ces règles de syntaxe avant de créer des expressions de personnalisation. La plupart des erreurs d’exécution proviennent du mélange des contextes Handlebars et PQL.

Utilisez la syntaxe correcte du bloc conditionnel

Utilisez toujours {%#if%} / {%else if%} / {%else%} / {%/if%}. La syntaxe {% if %} / {% elseif %} / {% endif %} n’est pas prise en charge.

{%#if profile.loyalty.tier = "gold"%}
Gold member content
{%else if profile.loyalty.tier = "silver"%}
Silver member content
{%else%}
Default content
{%/if%}

N’appelez pas les fonctions PQL dans les blocs Handlebars {{...}}.

{{...}} résout uniquement les variables Handlebars et les assistants. Il n’évalue pas les éléments PQL. Encapsuler une fonction PQL comme upperCase() dans {{...}} provoque une erreur du type « Assistant introuvable ». Utilisez plutôt {%= ... %} :

Incorrect
Correct
{{upperCase(cleanName)}}
{%= upperCase(cleanName) %}

Utiliser un alias de boucle nommé lors de la combinaison de {{#each}} avec{%#if%}

this.field est résolu par le moteur de rendu Handlebars, mais pas par l’évaluateur PQL dans une condition {%#if%}. Définissez un alias nommé avec as |item| afin que les deux contextes puissent résoudre le champ :

{{#each profile.orders as |order|}}
  {%#if order.status = "pending"%}
  Order {{order.id}} is pending.
  {%/if%}
{{/each}}

Attribuer des résultats de fonction PQL à une variable avant la boucle

Les champs PQL définis par l’utilisateur ou l’utilisatrice, tels que topN ne peuvent pas être appelés directement dans {{#each}}. Évaluez-les d’abord avec {% let %}, puis effectuez une itération sur le résultat :

{% let topOrders = topN(profile.orders, price, 3) %}
{{#each topOrders}}
  {{this.name}} — {{this.price}}&euro;
{{/each}}

Utilisez {% let %} pour éviter de répéter les appels de fonction

Lorsqu’une valeur calculée doit être utilisée plusieurs fois, stockez-la dans une variable. Cela améliore la lisibilité et évite les évaluations redondantes :

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

Utiliser l’ordre correct des arguments pourdateDiff

dateDiff(start, end) prend la date antérieure en premier. Pour calculer le nombre de jours restants jusqu’à une date ultérieure, transmettez la date actuelle en premier argument :

{% let daysLeft = dateDiff(getCurrentZonedDateTime(), stringToDate(profile.loyalty.expiryDate)) %}

Utilisez = et non== pour les comparaisons d’égalité dans PQL.

PQL utilise un seul opérateur = pour l’égalité. L’utilisation de == résultats entraîne une erreur de syntaxe.

Utiliser des apostrophes inverses pour les noms de champ avec trait d’union, dans les expressions PQL uniquement

Si un nom de champ de schéma XDM contient un trait d’union (par exemple, order-total), placez-le entre des apostrophes inverses pour éviter qu’il soit analysé en tant qu’opérateur de soustraction. Il n’est pris en charge que dans les expressions PQL {%= ... %}, et non dans les blocs Handlebars {{...}} :

{%= profile.events.`order-total` > 100 %}

Pour les expressions prêtes à l’emploi que vous pouvez copier directement dans votre contenu, consultez la section Recettes de personnalisation.

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 explains the Handlebars and PQL personalization syntaxes in Journey Optimizer — their general rules, reserved keywords, namespace structure, type system, and best practices for avoiding common runtime errors.

Intents:

  • Understand when to use Handlebars ({{...}}) vs. PQL ({%= ... %}) syntax
  • Apply general syntax rules: reserved characters, case sensitivity, HTML escaping, backslash handling
  • Escape reserved keywords and special attribute keys (hyphenated names, numeric event IDs) correctly
  • Apply type coercion when comparing or passing values of mismatched types
  • Reference personalization from the available namespaces: Profile, Audience, Offers
  • Follow best practices to avoid the most common runtime and validation errors

Glossary:

  • Handlebars: The {{...}} templating syntax used for rendering attributes, looping over arrays, and calling block helpers; HTML-escapes output by default. (product-specific)
  • Profile Query Language (PQL): The {%= ... %} expression syntax used for calling built-in functions (e.g. upperCase(), formatDate()) and evaluating conditional expressions. (product-specific)
  • Triple-stash ({{{ }}}): A Handlebars syntax variant that outputs values without HTML escaping, useful when the value itself contains HTML characters that should not be encoded.
  • Reserved keywords: PQL identifiers that cannot be used directly as field or variable names, grouped as general keywords (let, export, to, as, this, last, next, now, NOW, today, yesterday, tomorrow, from, FROM, From, before, BEFORE, Before, after, AFTER, After), time units (millisecond, milliseconds, second, seconds, minute, minutes, hour, hours, day, days, week, weeks, month, months, year, years, decade, decades, century, centuries, millennium, millennia), and boolean/logical operators (true, TRUE, True, false, FALSE, False, not, NOT, Not, and, AND, And, or, OR, Or, null, NULL, Null); must be wrapped in backticks when a schema field uses one of these names.
  • Type coercion: The explicit conversion of a value from one data type to another (e.g. string → number) using functions like stringToNumber() or toBool(), required before comparison or arithmetic in PQL.
  • Namespace: The top-level grouping of personalization data — Profile, Audience, Offers — each with its own path structure and access rules.
  • Block helper: A Handlebars helper identified by # before the helper name and a matching closing /, used for block constructs like {{#each}}.

Guardrails:

  • The xEvent variable is not available in personalization expressions; any reference to xEvent results in validation failures.
  • PQL function calls inside {{...}} Handlebars blocks will fail; use {%= ... %} instead.
  • The {% if %} / {% elseif %} / {% endif %} conditional syntax is not supported; use {%#if%} / {%else if%} / {%/if%}.
  • Backtick escaping for hyphenated field names is only supported inside PQL expressions ({%= ... %}). In {{...}} Handlebars interpolation, backtick syntax fails — but hyphenated field names can still be referenced directly (e.g. {{profile.my-custom-field}}).
  • Reserved keywords (general, time-unit, and boolean/logical, e.g. next, last, this, day, year, true, and, or) must be wrapped in backticks when used as schema field names; applies to both {{...}} and {%= ... %}.
  • Single backslash \ is not supported as a literal function argument; use double backslash \\.
  • PQL is strongly typed; mismatched types in comparisons or arithmetic require explicit conversion using stringToNumber(), toBool(), or similar coercion functions.

Terminology:

  • Canonical name: Handlebars — for the {{...}} syntax; PQL — for the {%= ... %} syntax
  • Do not confuse: {{...}} (Handlebars — renders variables and helpers, HTML-escaped) ≠ {%= ... %} (PQL — evaluates functions and expressions) ≠ {%#if%} / {%/if%} (conditional block syntax, percent-curly braces)
  • Do not confuse: {{profile.person.name}} (single-stash — HTML-escaped output) ≠ {{{profile.person.name}}} (triple-stash — unescaped output)
  • Do not confuse: reserved keyword backtick escaping (applies to both {{...}} and {%= ... %}) ≠ hyphenated key backtick escaping (only supported inside {%= ... %} PQL expressions, not in {{...}})
  • Do not confuse: = (PQL equality operator — correct) ≠ == (not valid PQL — causes a syntax error)

FAQ:

  • Q: When should I use {{...}} vs. {%= ... %}? — Use {{...}} (Handlebars) to render attribute values, loop over arrays, and call block helpers. Use {%= ... %} (PQL) to call built-in functions like upperCase() and formatDate(), and to evaluate conditional expressions.
  • Q: How do I output a value without HTML encoding? — Use the triple-stash {{{ }}} instead of {{...}}. Single-brace Handlebars HTML-escapes output (e.g., & becomes &amp;); triple-stash bypasses escaping.
  • Q: What is the correct equality operator in PQL? — Use a single = for equality comparisons in PQL. Using == is a syntax error.
  • Q: How do I reference a schema field whose name is a reserved keyword (e.g. next, last, this)? — Wrap it in backticks: {{profile.person.\next`.name}}`. This applies to both Handlebars paths and PQL expressions.
  • Q: Can I call PQL functions inside {{...}} Handlebars blocks? — No. {{...}} resolves Handlebars variables and helpers only. A PQL function inside {{...}} causes a “could not find helper” error. Use {%= functionName(...) %} instead.
recommendation-more-help
journey-optimizer-help