Ricette di personalizzazione personalization-recipes

In questa pagina: Trova ricette di personalizzazione pronte all’uso per date, array, stringhe, logica condizionale e casi edge di PQL che puoi copiare direttamente nel contenuto di Adobe Journey Optimizer.

Questa pagina fornisce modelli di personalizzazione pronti all’uso per i casi d’uso più comuni in Adobe Journey Optimizer. Tutti gli esempi utilizzano la sintassi dell’editor di personalizzazione e possono essere copiati direttamente nei contenuti e-mail, SMS o push.

Per un riferimento completo delle funzioni disponibili, vedere Funzioni helper, Funzioni data/ora, Funzioni stringa e Funzioni array.

TIP
Prima di copiare gli esempi, controlla le best practice per Personalization per evitare gli errori di sintassi più comuni.

Ricette data e ora date-time-recipes

Ricetta 1 - Visualizza la data corrente in un formato leggibile recipe-current-date

Utilizza formatDate con getCurrentZonedDateTime() per eseguire il rendering della data odierna in qualsiasi formato:

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

Output (esempio): April 11, 2026

Modelli di formato comuni:

Pattern
Esempio di output
"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
Utilizzare y minuscolo (anno di calendario) anziché Y (anno basato su settimane) per evitare risultati imprevisti ai limiti dell'anno. Vedi caratteri pattern per il riferimento completo.

Ricetta 2: conto alla rovescia per una data di scadenza o evento recipe-countdown

Utilizzare dateDiff per calcolare il numero di giorni rimanenti fino a un attributo di data profilo, quindi eseguirne il rendering in modo dinamico:

{% 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%}

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

Ricetta 3: X giorni prima di una data di fine dinamica recipe-days-before

Per calcolare una data che è X giorni prima di un attributo di profilo (ad esempio per fare riferimento nel contenuto o nelle righe dell’oggetto), utilizzare addDays con un offset negativo:

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

Output (esempio): April 04, 2026 (7 giorni prima dell’11 aprile)

Per impostare anche un’ora fissa del giorno (ad esempio le 9), combinare con setHours:

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

Ricetta 4 - Visualizza solo ora corrente come HH:MM recipe-time-only

Utilizzare extractHours e extractMinutes per visualizzare solo la parte relativa al tempo, con una protezione iniziale dello zero per i minuti:

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

Output (esempio): Your appointment is at 14:05.

Ricetta 5 — Rilevare fine settimana e giorno feriale recipe-weekend

Utilizza dayOfWeek per adattare il contenuto in base al giorno. La funzione restituisce da 1 (lunedì) a 7 (domenica). Utilizza il singolo operatore = (sintassi 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() è per adattare contenuto in base al giorno. Per instradare i profili in modo diverso in un percorso in base al giorno della settimana, utilizzare l'opzione predefinita Condizione temporale → Giorno della settimana nell'attività Condizione percorso. Ulteriori informazioni

Array e cicli predefiniti array-recipes

Ricetta 6 — Elenca tutti gli elementi da un array di profili recipe-list-items

Utilizza {{#each}} per eseguire l’iterazione su un array di profili ed eseguire il rendering di ogni elemento. È disponibile solo nell’editor di personalizzazione (e-mail, SMS, push):

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

Output (esempio):

- Running shoes: 89&euro;
- Water bottle: 15&euro;
- Gym bag: 45&euro;
NOTE
{{#each}} non è supportato nell'attività condizione percorso. Per filtrare gli array nelle condizioni, utilizzare funzioni di gestione della raccolta.

Ricetta 7: mostra i primi N articoli da un array in base al prezzo recipe-first-n

Utilizzare topN per ordinare e recuperare i primi N elementi in base a un campo numerico. Poiché topN è una funzione di PQL, assegnarla prima a una variabile con {% let %}, quindi eseguire il ciclo con {{#each}}:

{% let topOrders = topN(profile.orders, price, 3) %}
{{#each topOrders}}
  {{this.name}} — {{this.price}}&euro;
{{/each}}
NOTE
topN(profile.orders, price, 3) ordina gli ordini per price in ordine decrescente e restituisce i primi 3, non semplicemente restituisce i primi 3 elementi nell'ordine di matrice originale.

In alternativa, utilizzare head per ottenere solo il singolo elemento principale:

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

Ricetta 8 — Eseguire il rendering del contenuto in modo condizionale per elemento array recipe-conditional-loop

Utilizza {%#if%} in {{#each}} per eseguire il rendering dell’output solo per gli elementi corrispondenti. Definisci un alias di loop con as |order| in modo che l’esaminatore PQL possa risolvere il riferimento all’attributo nella condizione:

{{#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 funziona nelle espressioni Handlebars ma non è risolto dal valutatore PQL all'interno di {%#if%}. L'utilizzo di un alias di loop denominato, ad esempio order, rende l'attributo disponibile sia per gli Handlebars che per i contesti di PQL.

Stringhe e formule di formattazione string-recipes

Ricetta 9 — Pulire una stringa con replaceAll e riutilizzarla recipe-replaceall-reuse

replaceAll restituisce un nuovo valore, non modifica l’originale. Utilizzare {% let %} per memorizzare il risultato e fare riferimento a esso più volte senza ripetere la chiamata alla funzione:

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

Output (esempio):

Hi John,
Your exclusive code is: WELCOME-JOHN

Ricetta 10: virgolette doppie per un valore nell’output JSON recipe-json-quotes

Per includere una virgoletta doppia letterale all’interno di una stringa (ad esempio, generando JSON per un payload personalizzato), esegui l’escape con una barra rovesciata (\"):

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

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

Ricetta 11 — Formattare un componente data in maiuscolo recipe-uppercase-date

Combina formatDate con upperCase per riprodurre i nomi dei mesi o dei giorni in lettere maiuscole:

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

Output (esempio): APRIL

Per una stringa di data completa in maiuscolo:

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

Output (esempio): WEDNESDAY JANUARY 01 2020

Ricette logiche condizionali conditional-recipes

Ricetta 12 — IF/ELSEIF/ELSE nel contenuto personalizzato recipe-if-elseif

Utilizzare {%#if%}, {%else if%} e {%else%} per la logica condizionale multi-branch. Questo modello funziona nei contenuti e nei frammenti dell’e-mail:

{%#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%}

Ricetta 13: visualizzazione degli attributi Null-safe recipe-null-safe

Utilizza un fallback condizionale per evitare di eseguire il rendering di valori vuoti quando un attributo di profilo può essere nullo o mancante:

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

Oppure in linea con uno schema di tipo ternario utilizzando isEmpty:

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

ricette per casi edge di PQL pql-edge-cases

Ricetta 14 - Riferimento a una chiave attributo sillabata recipe-hyphenated-key

Se il nome del campo dello schema XDM contiene trattini (ad esempio order-total, event-type), inseriscilo in apici all’interno di un’espressione PQL per impedire che il trattino venga interpretato come un operatore di sottrazione:

{%= profile.events.`order-total` > 100 %}
NOTE
I backtick sono supportati solo all'interno di espressioni di PQL ({%= ... %}). Non sono accettati nell'interpolazione Handlebars normale ({{...}}). Se devi eseguire direttamente il rendering di un valore di campo sillabato, valutalo tramite un'espressione PQL o memorizzalo in una variabile utilizzando prima {% let %}.

Ricetta 15: fare riferimento a un ID evento numerico in un attributo di contesto recipe-numeric-event-id

Quando si utilizza un evento di contesto di percorso il cui ID è una stringa numerica (ad esempio 1697323153), racchiudere l’ID in apici e utilizzare {% let %} con toDateTime() e formatDate():

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

Output (esempio): Your appointment: 18/03/2026 14:30

Ricetta 16 — Tipo coercizione: confrontare un campo stringa con un numero recipe-type-coercion

PQL è fortemente tipizzato. Quando un campo del profilo è memorizzato come stringa ma è necessario confrontarlo numericamente, convertire prima il campo con stringToNumber():

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

Per i campi booleani memorizzati come stringhe:

{%= 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