個人化方式 personalization-recipes

在此頁面上:​尋找可直接複製到Adobe Journey Optimizer內容中的現成個人化配方,適用於日期、陣列、字串、條件邏輯和PQL邊緣案例。

本頁針對Adobe Journey Optimizer中最常見的使用案例提供現成的個人化模式。 所有範例都使用個人化編輯器語法,並可直接複製到電子郵件、簡訊或推播內容中。

如需可用函式的完整參考,請參閱協助程式函式日期/時間函式字串函式陣列函式

TIP
在複製範例之前,請檢閱Personalization最佳實務以避免最常見的語法錯誤。

日期與時間配方 date-time-recipes

方式1 — 以可讀格式顯示目前日期 recipe-current-date

使用formatDate搭配getCurrentZonedDateTime()以任何格式呈現今天的日期:

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

輸出(範例): April 11, 2026

通用格式模式:

模式
輸出範例
"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
請使用小寫y (行事曆年份)而非Y (以周為單位的年份),以避免在年份邊界出現非預期的結果。 如需完整參考,請參閱圖樣字元

方式2 — 到期或事件日期的倒數 recipe-countdown

使用dateDiff計算設定檔日期屬性之前的剩餘天數,然後以動態方式呈現:

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

輸出(範例): Your reward points expire in 7 days. Use them before they're gone!

配方3 — 動態結束日期前的X天 recipe-days-before

若要計算設定檔屬性之前X天的日期(例如在內容或主旨行中參照),請使用負位移的addDays

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

輸出(範例): April 04, 2026 (4月11日前7天)

若要同時設定一天中的固定時間(例如,上午9點),請結合setHours

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

配方4 — 將目前時間顯示為HH:MM recipe-time-only

使用extractHoursextractMinutes只顯示時間部分,並在前導為零時保留分鐘:

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

輸出(範例): Your appointment is at 14:05.

食譜5 — 偵測週末與平日 recipe-weekend

使用dayOfWeek根據日期調整內容。 此函式傳回1 (星期一)到7 (星期日)。 使用單一=運運算元(PQL語法,而非==):

{%#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()是根據日期調整​內容。 若要根據一週中的某天在歷程中以不同方式路由設定檔,請在歷程條件活動中使用內建的​ 時間條件→一週中的某天 ​選項。 了解更多

陣列與回圈配方 array-recipes

指導方針6 — 列出設定檔陣列中的所有專案 recipe-list-items

使用{{#each}}來反複處理設定檔陣列並演算每個專案。 這僅在個人化編輯器(電子郵件、簡訊、推播)中可用:

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

輸出(範例):

- Running shoes: 89&euro;
- Water bottle: 15&euro;
- Gym bag: 45&euro;
NOTE
歷程條件活動不支援{{#each}}。 若要在條件中篩選陣列,請使用集合管理函式

配方7 — 依價格顯示陣列中的前N個專案 recipe-first-n

使用topN依數值欄位排序及擷取前N個專案。 由於topN是PQL函式,請先將其指派給具有{% let %}的變數,然後以{{#each}}進行回圈:

{% let topOrders = topN(profile.orders, price, 3) %}
{{#each topOrders}}
  {{this.name}} — {{this.price}}&euro;
{{/each}}
NOTE
topN(profile.orders, price, 3)會依遞減順序排序price並傳回前3個專案 — 它不會簡單地傳回原始陣列順序中的前3個專案。

或使用head只取得單一最上層專案:

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

方式8 — 根據陣列專案有條件地呈現內容 recipe-conditional-loop

{{#each}}內使用{%#if%}僅針對相符的專案轉譯輸出。 定義具有as |order|的回圈別名,讓PQL評估器能夠解析條件中的屬性參考:

{{#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在Handlebars運算式中運作,但未由{%#if%}內的PQL評估程式解析。 使用具名回圈別名(例如order)可讓屬性同時用於Handlebars和PQL內容。

字串與格式設定配方 string-recipes

方式9 — 使用replaceAll清除字串並重複使用 recipe-replaceall-reuse

replaceAll傳回新值 — 它不會修改原始值。 使用{% let %}儲存結果並多次參考它,而不重複函式呼叫:

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

輸出(範例):

Hi John,
Your exclusive code is: WELCOME-JOHN

指導方針10 — JSON輸出中的雙引號值 recipe-json-quotes

若要在字串中包含常值雙引號(例如為自訂裝載產生JSON),請使用反斜線(\")將其逸出:

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

輸出: { "greeting": "Hello \"John\"" }

方式11 — 將日期元件格式化為大寫 recipe-uppercase-date

formatDateupperCase結合,以大寫方式呈現月份或日期名稱:

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

輸出(範例): APRIL

若為完整的大寫日期字串:

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

輸出(範例): WEDNESDAY JANUARY 01 2020

條件邏輯配方 conditional-recipes

指導方針12 — 個人化內容中的IF/ELSEIF/ELSE recipe-if-elseif

針對多分支條件式邏輯使用{%#if%}{%else if%}{%else%}。 此模式適用於電子郵件內容和片段:

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

配方13 — 空值安全屬性顯示 recipe-null-safe

使用條件式遞補,以避免在設定檔屬性可能為Null或遺失時呈現空白值:

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

或使用isEmpty以三元樣式模式內嵌:

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

PQL邊緣案例訣竅 pql-edge-cases

指導方針14 — 參照連字屬性索引鍵 recipe-hyphenated-key

如果您的XDM結構描述欄位名稱包含連字型大小(例如order-totalevent-type),請在PQL運算式中以反引號將其包裝,以防止將連字型大小解譯為減法運運算元:

{%= profile.events.`order-total` > 100 %}
NOTE
只有PQL運算式({%= ... %})內支援反引號。 在純的Handlebars內插({{...}})中不接受它們。 如果您需要直接轉譯斷字欄位值,請先透過PQL運算式評估該值,或使用{% let %}將其儲存在變數中。

方式15 — 參考內容屬性中的數值事件ID recipe-numeric-event-id

使用歷程內容事件時,若其ID為數值字串(例如1697323153),請以反引號括住該ID,並使用{% let %}搭配toDateTime()formatDate()

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

輸出(範例): Your appointment: 18/03/2026 14:30

方式16 — 輸入強制:比較字串欄位與數字 recipe-type-coercion

PQL是強型別。 當設定檔欄位儲存為字串,但您需要以數值加以比較時,請先將其轉換為stringToNumber()

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

對於儲存為字串的布林值欄位:

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