Sintaxis de personalización personalization-syntax

En esta página: Conozca la sintaxis de personalización de Handlebars y PQL en Adobe Journey Optimizer, incluidas las reglas generales, las palabras clave reservadas, la coerción de tipos, los espacios de nombres disponibles y las prácticas recomendadas.

Personalization en Journey Optimizer usa dos sintaxis complementarias que funcionan juntas en la misma expresión:

  • Handlebars ({{...}}): se usa para procesar atributos de perfil, recorrer en bucle matrices y llamar a ayudantes de bloque. Consulte la documentación de HandlebarsJS para obtener una referencia completa.
  • Profile Query Language (PQL) ({%= ... %}): se usa para llamar a funciones integradas (por ejemplo, upperCase(), formatDate(), dateDiff()) y evaluar expresiones condicionales.

Es fundamental comprender en qué contexto se encuentra para evitar errores de tiempo de ejecución. Por ejemplo, una llamada a una función de PQL colocada dentro de {{...}} fallará porque Handlebars intenta resolverla como un ayudante en lugar de evaluarla como una expresión de PQL.

Ejemplos:

Ejemplo de uso
Sintaxis
Procesamiento de un atributo de perfil
{{profile.person.name.firstName}}
Llamar a una función de PQL
{%= upperCase(profile.person.name.firstName) %}
Bloque condicional
{%#if profile.loyalty.tier = "gold"%}...{%/if%}
Repetir sobre una matriz
{{#each profile.orders}}...{{/each}}

La estructura de atributos se define en un esquema XDM de Adobe Experience Platform. Más información.

TIP
Para obtener expresiones listas para usar que apliquen estas sintaxis a escenarios reales (formato de fecha, cuenta atrás, reserva condicional, etc.), consulte la página Fórmulas de Personalization.

Sintaxis: reglas generales general-rules

  • Los identificadores pueden ser cualquier carácter Unicode excepto los siguientes caracteres especiales, que están reservados para la sintaxis Handlebars:

    code language-none
    Whitespace ! " # % & ' ( ) * + , . / ; < = > @ [ \ ] ^ ` { | } ~
    
  • La sintaxis distingue entre mayúsculas y minúsculas.

  • Las palabras true, false, null y undefined solo se permiten en la primera parte de una expresión de ruta.

  • En Handlebars, los valores devueltos por {{expression}} son HTML-escaped. Si la expresión contiene &, el resultado devuelto con escape de HTML se generará como &amp;. Si no desea que Handlebars escape un valor, utilice la “pila triple”.

    Supongamos que el valor del campo profile.person.name es “Mark & Mary”. La sintaxis {{profile.person.name}} mostrará Mark &amp; Mary, mientras que {{{profile.person.name}}} mostrará Mark & Mary.

  • En cuanto a los argumentos de funciones literales, el analizador de idioma de creación de plantillas no admite un único símbolo de barra invertida sin escape (\). Este carácter debe especificarse con una barra invertida (\) adicional. Ejemplo:

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

  • Para incluir comillas dobles literales dentro de un valor de cadena (por ejemplo, al generar la salida JSON), escríbalo con una barra invertida (\"):

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

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

    Como alternativa, utilice la triple pila {{{ }}} para generar HTML sin escape cuando el valor en sí contenga caracteres especiales que no desee codificar en HTML.

Palabras clave reservadas reserved-keywords

Algunas palabras clave están reservadas en Profile Query Language (PQL) y no se pueden usar directamente como nombres de campo o variable en expresiones de personalización. Si el esquema XDM contiene campos con nombres que coinciden con palabras clave reservadas, debe escaparlos utilizando comillas invertidas (`) para hacer referencia a ellos en las expresiones.

Las palabras clave reservadas incluyen:

  • General: let, export, to, as, this, last, next, now, NOW, today, yesterday, tomorrow, from, FROM, From, before, BEFORE, Before, after, AFTER, After
  • Unidades de tiempo: millisecond, milliseconds, second, seconds, minute, minutes, hour, hours, day, days, week, weeks, month, months, year, years, decade, decades, century, centuries, millennium, millennia
  • Operadores booleanos y lógicos: true, TRUE, True, false, FALSE, False, not, NOT, Not, and, AND, And, or, OR, Or, null, NULL, Null

Ejemplo:

Si el esquema de perfil tiene un campo denominado next, debe envolverlo en acentos graves:

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

Sin las comillas invertidas, el editor de personalización falla en la validación con un error.

NOTE
El escape de acento grave para palabras clave reservadas se aplica tanto a las rutas de acceso de Handlebars {{...}} como a las expresiones PQL {%= ... %}, ya que estas palabras clave están reservadas en el nivel de resolución de ruta de acceso. Esto es diferente a los nombres de campo con guiones, donde el escape de acento grave solo se admite dentro de expresiones PQL. Consulte Claves de atributo con división de palabras.

Reglas de sintaxis de PQL para claves de atributo especiales pql-special-keys

Más allá de las palabras clave reservadas, dos casos adicionales requieren el escape de acento grave en las expresiones PQL.

Claves de atributo con guiones hyphenated-keys

Si el esquema XDM contiene nombres de campo con guiones (p. ej. my-field, event-type) o nombres que comiencen o contengan números, ajuste la clave en comillas invertidas dentro de expresiones PQL:

{%= profile.events.`order-total` > 100 %}
NOTE
El escape de acento grave solo se admite dentro de expresiones PQL ({%= ... %}). No se admite en la interpolación Handlebars ({{...}}). Sin embargo, se puede hacer referencia directamente a los nombres de campo con guiones en {{...}} bloques (p. ej. {{profile.my-custom-field}}); solo falla la sintaxis de acento grave en ellos.

Sin comilla invertida en una expresión PQL, el guión se interpreta como un operador de resta y provoca un error de sintaxis de PQL.

ID de eventos numéricos en atributos de contexto numeric-event-ids

Cuando se haga referencia a atributos de evento de contexto en los que el ID de evento sea un número (por ejemplo, 1697323153), encapsúlelo con acentos graves. Esto también se aplica dentro de funciones como formatDate():

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

Coerción de tipo type-coercion

PQL tiene establecimiento inflexible de tipos. Al comparar o pasar valores, ambos lados deben ser del mismo tipo. Casos frecuentes:

Situación
Solución
Valor numérico almacenado como cadena
Usar stringToNumber() antes de la comparación o aritmética: {%= stringToNumber(profile.loyalty.pointsBalance) > 500 %}
Entero almacenado como cadena
Usar string_to_integer() o stringToNumber() antes de la aritmética
Booleano almacenado como cadena
Usar toBool() para convertir: {%= toBool(profile.consents.email.val) = true %}

Áreas de nombres disponibles namespaces

  • Perfil

    Este espacio de nombres le permite hacer referencia a todos los atributos definidos en el esquema de perfil descrito en Documentación del Modelo de datos de Adobe Experience Platform (XDM).

    Es necesario definir los atributos en el esquema antes de hacer referencia a ellos en un bloque personalizado Journey Optimizer.

    Para obtener más información sobre cómo aprovechar los atributos de perfil en condiciones, consulte esta sección.

    accordion
    Referencias de muestra
    • {{profile.person.name.fullName}}
    • {{profile.person.name.firstName}}
    • {{profile.person.gender}}
    • {{profile.personalEmail.address}}
    • {{profile.mobilePhone.number}}
    • {{profile.homeAddress.city}}
    • {{profile.faxPhone.number}}
  • Audiencia

    Para obtener más información sobre el servicio de segmentación, consulte esta documentación.

  • Ofertas

    Este área de nombres le permite hacer referencia a decisiones de ofertas existentes.

    Para hacer referencia a una oferta, debe declarar una ruta con la diferente información que define una oferta. Esta ruta tiene la siguiente estructura:

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

    donde:

    • offers identifica la expresión de ruta que pertenece al área de nombres de la oferta
    • Type determina el tipo de representación de la oferta. Los valores posibles son: image, html y text
    • Placement Id y Activity Id son identificadores de ubicación y actividad
    • Attributes son atributos específicos de la oferta que dependen del tipo de oferta. Ejemplo: deliveryUrl para imágenes

    Para obtener más información sobre la API Decisions y las representaciones Offer, consulte esta página

    Todas las referencias se validan con el esquema de ofertas con un mecanismo de validación descrito en esta página

    accordion
    Referencias de muestra
    • Ubicación donde se aloja la imagen:

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

    • URL de destino al hacer clic en la imagen:

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

    • Contenido de texto de la oferta procedente del motor de decisión:

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

    • Contenido de HTML de la oferta proveniente del motor de decisión:

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

Ayudantes helpers-all

Un asistente de Handlebars es un identificador simple que puede ir seguido de parámetros. Cada parámetro es una expresión Handlebars. Se puede acceder a estos ayudantes desde cualquier contexto de una plantilla.

Estos ayudantes de bloque se identifican con un # antes del nombre del ayudante y requieren un / de cierre coincidente, del mismo nombre.

Los bloques son expresiones que tienen un bloque de apertura ({{# }}) y cierre ({{/}}).

Para obtener más información sobre las funciones de ayuda, consulte esta sección.

Tipos literales literal-types

Adobe Journey Optimizer admite los siguientes tipos literales:

Literal
Definición
Cadena
Un tipo de datos compuesto por caracteres entre comillas dobles.
Ejemplos: "prospect", "jobs", "articles"
Booleano
Un tipo de datos que puede ser verdadero o falso.
Número entero
Un tipo de datos que representa un número entero. Puede ser positivo, negativo o cero.
Ejemplos: -201, 0, 412
Matriz
Un tipo de datos que se comprende como un grupo de otros valores literales. Utiliza corchetes para agrupar y comas para delimitar entre distintos valores.
Nota: No puede tener acceso directo a las propiedades de los elementos de una matriz.
Ejemplos: [1, 4, 7], ["US", "FR"]
CAUTION
El uso de la variable xEvent no está disponible en expresiones de personalización. Cualquier referencia a xEvent producirá errores de validación.

Prácticas recomendadas best-practices

Revise estas reglas de sintaxis antes de crear expresiones de personalización. La mayoría de los errores de tiempo de ejecución provienen de la mezcla de Handlebars y contextos PQL.

Use la sintaxis de bloque condicional correcta

Use siempre {%#if%} / {%else if%} / {%else%} / {%/if%}. No se admite la sintaxis {% if %} / {% elseif %} / {% endif %}.

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

No llame a funciones de PQL dentro de {{...}} bloques de Handlebars

{{...}} solo resuelve las variables Handlebars y los ayudantes, no evalúa PQL. Al ajustar una función de PQL como upperCase() dentro de {{...}}, se produce el error “no se pudo encontrar el asistente”. Usar {%= ... %} en su lugar:

Incorrecto
Correcto
{{upperCase(cleanName)}}
{%= upperCase(cleanName) %}

Use un alias de bucle con nombre al combinar {{#each}} con{%#if%}

this.field lo ha resuelto el procesador Handlebars, pero no el evaluador PQL dentro de una condición {%#if%}. Defina un alias con nombre con as |item| para que ambos contextos puedan resolver el campo:

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

Asignar resultados de funciones de PQL a una variable antes del bucle

No se puede llamar a las UDF de PQL como topN directamente dentro de {{#each}}. Evalúelos primero con {% let %} y después itere en el resultado:

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

Use {% let %} para evitar repetir llamadas a funciones

Cuando un valor calculado se necesite más de una vez, almacénelo en una variable. Esto mejora la legibilidad y evita evaluaciones redundantes:

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

Use el orden de argumentos correcto paradateDiff

dateDiff(start, end) toma primero la fecha anterior. Para calcular los días restantes hasta una fecha futura, pase la fecha actual como primer argumento:

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

Use = para comparaciones de igualdad en PQL, no==

PQL usa un solo operador = para la igualdad. Usar == resulta en un error de sintaxis.

Use comillas invertidas para nombres de campos con guiones, solo en expresiones PQL

Si el nombre de un campo de esquema XDM contiene un guion (por ejemplo, order-total), encapsúlelo en comillas invertidas para evitar que el guion se analice como operador de resta. Esto solo se admite dentro de {%= ... %} expresiones PQL, no en {{...}} bloques Handlebars:

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

Para ver las expresiones listas para usar que puede copiar directamente en el contenido, consulte Fórmulas de Personalization.

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