個人化語法 personalization-syntax

在此頁面上:​瞭解Adobe Journey Optimizer中的Handlebars和PQL個人化語法,包括一般規則、保留關鍵字、型別強制執行、可用名稱空間和最佳實務。

Journey Optimizer中的Personalization使用兩種互補語法,在相同的運算式中一起運作:

  • Handlebars ({{...}}) — 用於轉譯設定檔屬性、陣列上的回圈,以及呼叫區塊協助程式。 如需完整參考,請參閱HandlebarsJS檔案
  • Profile Query Language (PQL) ({%= ... %}) — 用於呼叫內建函式(例如upperCase()formatDate()dateDiff())並評估條件運算式。

瞭解您所在的環境是避免執行階段錯誤的關鍵。 例如,置於{{...}}內的PQL函式呼叫將失敗,因為Handlebars會嘗試將其解析為協助程式,而不是將其評估為PQL運算式。

範例:

使用案例
語法
呈現設定檔屬性
{{profile.person.name.firstName}}
呼叫PQL函式
{%= upperCase(profile.person.name.firstName) %}
條件區塊
{%#if profile.loyalty.tier = "gold"%}...{%/if%}
在陣列上回圈
{{#each profile.orders}}...{{/each}}

屬性結構是在Adobe Experience Platform XDM結構描述中定義。 了解更多

TIP
如需將這些語法套用至實際情況的現成運算式(日期格式、倒數、條件遞補等),請參閱​**Personalization配方**​頁面。

語法一般規則 general-rules

  • 識別碼可以是任何Unicode字元,但下列為Handlebars語法保留的特殊字元除外:

    code language-none
    Whitespace ! " # % & ' ( ) * + , . / ; < = > @ [ \ ] ^ ` { | } ~
    
  • 語法區分大小寫。

  • 字詞​truefalsenull​和​ 未定義 ​只允許在路徑運算式的第一個部分中。

  • 在Handlebars中,{{expression}}傳回的值是​HTML逸出。 如果運算式包含&,則會產生傳回的HTML逸出輸出為&amp;。 如果您不希望Handlebars逸出值,請使用「三重儲存」。

    假設欄位profile.person.name的值為「Mark & Mary」。 語法{{profile.person.name}}將顯示Mark &amp; Mary,而{{{profile.person.name}}}將顯示Mark & Mary

  • 關於常值函式引數,範本化語言剖析器不支援單一未逸出的反斜線(\)符號。 此字元必須使用額外的反斜線(\)符號逸出。 範例:

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

  • 若要在字串值中包含​常值雙引號 (例如在產生JSON輸出時),請使用反斜線(\")將其逸出:

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

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

    或者,當值本身包含您不想要以HTML編碼的特殊字元時,使用三重儲存{{{ }}}來輸出未逸出的HTML。

保留關鍵字 reserved-keywords

某些關鍵字在Profile Query Language (PQL)中會保留,並且無法直接用作個人化運算式中的欄位或變數名稱。 如果您的XDM結構描述包含名稱符合保留關鍵字的欄位,您必須使用反引號(`)將其逸出,以便在運算式中參照。

保留的關鍵字包括:

  • next
  • last
  • this

範例:

如果您的設定檔結構描述有名為next的欄位,您必須以反引號將其換行:

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

如果沒有反引號,個人化編輯器將會因錯誤而無法通過驗證。

NOTE
保留關鍵字的反勾逸出同時適用於{{...}} Handlebars路徑和{%= ... %} PQL運算式,因為這些關鍵字是在路徑解析度層級保留。 這與連字欄位名稱不同,後者僅支援PQL運算式中的反勾字元逸出。 請參閱連字屬性索引鍵

特殊屬性索引鍵的PQL語法規則 pql-special-keys

除了保留的關鍵字之外,另有兩個案例需要在PQL運算式中執行反勾字元逸出。

連字屬性索引鍵 hyphenated-keys

如果您的XDM結構描述包含具有連字型大小的欄位名稱(例如my-fieldevent-type),或是開頭為或包含數字的名稱,請在PQL運算式中以反引號將索引鍵換行:

{%= profile.events.`order-total` > 100 %}
NOTE
只有PQL運算式({%= ... %})內支援反勾字元逸出。 Handlebars內插({{...}})不支援此功能。 不過,可以在{{...}}區塊中直接參考連字欄位名稱(例如{{profile.my-custom-field}});只有反勾語法會失敗。

若沒有PQL運算式中的反引號,連字型大小會解譯為減法運運算元,並導致PQL語法錯誤。

內容屬性中的數值事件ID numeric-event-ids

當參考事件ID為數字(例如1697323153)的內容事件屬性時,請以反引號將其包裝。 這也適用於類似formatDate()的函式內部:

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

輸入強制 type-coercion

PQL是強型別。 比較或傳遞值時,兩邊的型別必須相同。 常見案例:

藍本
解決方案
儲存為字串的數值
在算術或比較前使用stringToNumber(){%= stringToNumber(profile.loyalty.pointsBalance) > 500 %}
儲存為字串的整數
在算術前使用string_to_integer()stringToNumber()
布林值儲存為字串
使用toBool()進行轉換: {%= toBool(profile.consents.email.val) = true %}

可用的名稱空間 namespaces

  • 輪廓

    此名稱空間可讓您參考Adobe Experience Platform資料模型(XDM)檔案中所述的設定檔結構描述中定義的所有屬性。

    屬性必須先在結構描述中定義,才能在Journey Optimizer個人化區塊中參考。

    如需如何在條件中運用設定檔屬性的詳細資訊,請參閱本節

    accordion
    範例參考
    • {{profile.person.name.fullName}}
    • {{profile.person.name.firstName}}
    • {{profile.person.gender}}
    • {{profile.personalEmail.address}}
    • {{profile.mobilePhone.number}}
    • {{profile.homeAddress.city}}
    • {{profile.faxPhone.number}}
  • 客群

    若要深入瞭解細分服務,請參閱此檔案

  • 產品建議

    此名稱空間可讓您參考現有的優惠決定。

    若要參照選件,您必須使用定義選件的不同資訊來宣告路徑。 此路徑的結構如下:

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

    其中:

    • offers會識別屬於優惠方案名稱空間的路徑運算式
    • Type決定優惠方案宣告的型別。 可能的值為: imagehtmltext
    • Placement IdActivity Id是位置與活動識別碼
    • Attributes是優惠方案特定屬性,其取決於優惠方案型別。 範例: deliveryUrl影像

    如需有關Decisions API和優惠宣告的詳細資訊,請參閱此頁面

    所有參考資料都是透過在此頁面中說明的驗證機制針對優惠方案結構描述進行驗證

    accordion
    範例參考
    • 影像的託管位置:

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

    • 按一下影像時的目標URL:

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

    • 來自決策引擎的優惠方案文字內容:

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

    • 來自決策引擎之優惠方案的HTML內容:

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

輔助程式 helpers-all

Handlebars協助程式是簡單識別碼,後面可能會接著引數。 每個引數都是Handlebars運算式。 這些協助程式可從範本中的任何內容存取。

這些區塊協助程式由協助程式名稱前的#識別,並需要相同名稱的相符結尾/

區塊是具有區塊開啟({{# }})和結束({{/}})的運算式。

如需協助程式函式的詳細資訊,請參閱本節

常值型別 literal-types

Adobe Journey Optimizer支援下列常值型別:

常值
定義
字串
由雙引號包住的字元所組成的資料型別。
範例: "prospect""jobs""articles"
布林值
為true或false的資料型別。
整數
代表整數的資料型別。 可以是正數、負數或零。
範例: -2010412
陣列
一種資料型別,由一組其他常值組成。 它使用方括弧將不同值分組,並使用逗號分隔不同值。
注意:​您無法直接存取陣列中專案的屬性。
範例: [1, 4, 7]["US", "FR"]
CAUTION
個人化運算式無法使用​ xEvent ​變數。 對xEvent的任何參考都會導致驗證失敗。

最佳做法 best-practices

在建立個人化運算式之前,請先檢閱這些語法規則。 大多數執行階段錯誤來自混合Handlebars和PQL內容。

使用正確的條件區塊語法

一律使用{%#if%} / {%else if%} / {%else%} / {%/if%}。 不支援{% if %} / {% elseif %} / {% endif %}語法。

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

請勿在{{...}} Handlebars區塊中呼叫PQL函式

{{...}}僅解析Handlebars變數和協助程式 — 它不會評估PQL。 將upperCase()之類的PQL函式包裝在{{...}}內會導致「找不到協助程式」錯誤。 改用{%= ... %}

不正確
正確
{{upperCase(cleanName)}}
{%= upperCase(cleanName) %}

結合{{#each}}{%#if%}​時使用具名回圈別名

this.field是由Handlebars轉譯器解析,但不是由{%#if%}條件內的PQL評估器解析。 定義具有as |item|的具名別名,讓兩個內容都能解析欄位:

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

在循環之前,將PQL函式結果指派給變數

無法直接在{{#each}}中呼叫PQL UDF (例如topN)。 先使用{% let %}評估它們,然後反複檢視結果:

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

使用{% let %}以避免重複函式呼叫

當計算值需要超過一次,請將其儲存在變數中。 這樣可改善可讀性,並防止重複評估:

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

dateDiff​使用正確的引數順序

dateDiff(start, end)會先採用較早的日期。 若要計算未來日期前的剩餘天數,請將目前日期傳入第一個引數:

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

在PQL中使用=進行相等比較,而不是==

PQL使用單一=運運算元來相等。 使用==會導致語法錯誤。

在連字欄位名稱使用反引號 — 僅在PQL運算式中

如果XDM結構描述欄位名稱包含連字型大小(例如order-total),請以反引號將其包裝,以防止將連字型大小剖析為減法運運算元。 這僅在{%= ... %}個PQL運算式中才受支援,在{{...}}個Handlebars區塊中則不受支援:

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

如需可直接複製到內容中的現成運算式,請參閱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