在此页面上:了解Adobe Journey Optimizer中的Handlebars和PQL个性化语法,包括常规规则、保留关键词、类型强制、可用命名空间和最佳实践。
Journey Optimizer中的Personalization使用两种互补语法,它们在同一表达式中协同工作:
- Handlebars (
{{...}}) — 用于呈现配置文件属性、通过数组循环和调用块帮助程序。 有关完整参考,请参阅HandlebarsJS文档。 - Profile Query Language (PQL) (
{%= ... %}) — 用于调用内置函数(如upperCase()、formatDate()、dateDiff())并计算条件表达式。
了解您所处的上下文是避免运行时错误的关键。 例如,置于{{...}}内的PQL函数调用将失败,因为Handlebars尝试将其解析为帮助程序,而不是将其计算为PQL表达式。
示例:
{{profile.person.name.firstName}}{%= upperCase(profile.person.name.firstName) %}{%#if profile.loyalty.tier = "gold"%}...{%/if%}{{#each profile.orders}}...{{/each}}属性结构在Adobe Experience Platform XDM架构中定义。 了解详情。
语法一般规则 general-rules
-
标识符可以是任何Unicode字符,但为Handlebars语法保留的以下特殊字符除外:
code language-none Whitespace ! " # % & ' ( ) * + , . / ; < = > @ [ \ ] ^ ` { | } ~ -
语法区分大小写。
-
仅在路径表达式的第一部分中允许使用单词true、false、null和undefined。
-
在Handlebars中,{{expression}}返回的值是HTML转义。 如果表达式包含
&,则返回的HTML转义输出将生成为&。 如果不希望Handlebars转义值,请使用“三重存储”。假设字段
profile.person.name的值为“Mark & Mary”。 语法{{profile.person.name}}将显示Mark & 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架构包含名称与保留关键词匹配的字段,则必须使用反撇号(`)对其进行转义,以在表达式中引用它们。
保留的关键字包括:
nextlastthis
示例:
如果您的配置文件架构具有一个名为next的字段,则必须用反勾号将其换行:
{{profile.person.`next`.name}}
如果没有回退,个性化编辑器将验证失败并出现错误。
{{...}} Handlebars路径和{%= ... %} PQL表达式,因为这些关键字在路径解析级别保留。 这与连字符字段名称不同,在连字符字段中,仅在PQL表达式中支持反勾转义。 请参阅连字符属性键。特殊属性键的PQL语法规则 pql-special-keys
除了保留的关键字之外,还有两种情况需要在PQL表达式中进行反勾转义。
连字符属性键 hyphenated-keys
如果XDM架构包含字段名称带有连字符(如my-field、event-type),或者名称以数字开头或包含数字,请在PQL表达式中以反撇号将键换行:
{%= profile.events.`order-total` > 100 %}
{%= ... %})中支持反勾转义。 在Handlebars插值({{...}})中不支持它。 但是,可以在{{...}}块中直接引用连字符字段名称(例如{{profile.my-custom-field}});只有反勾语法在该块中失败。在PQL表达式中没有反撇号的情况下,连字符会被解释为减法运算符,并导致PQL语法错误。
上下文属性中的数字事件ID numeric-event-ids
在引用事件ID为数字(例如1697323153)的上下文事件属性时,请用反勾号将其换行。 这也适用于诸如formatDate()之类的函数:
强制键入 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确定优惠呈现的类型。 可能的值为:image、html和textPlacement Id和Activity Id是投放位置和活动标识符Attributes是特定于优惠的属性,具体取决于优惠类型。 示例:deliveryUrl图像
有关Decisions API和Offer呈现的详细信息,请参阅此页面
所有引用均通过此页面中描述的验证机制针对优惠架构进行验证
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"示例:
-201,0,412注意:您不能直接访问数组中项的属性。
示例:
[1, 4, 7],["US", "FR"]最佳实践 best-practices
在构建个性化表达式之前,请查看这些语法规则。 大多数运行时错误来自混合Handlebars和PQL上下文。
使用正确的条件块语法
始终使用{%#if%} / {%else if%} / {%else%} / {%/if%}。 不支持{% if %} / {% elseif %} / {% endif %}语法。
请勿在{{...}} Handlebars块中调用PQL函数
{{...}}仅解析Handlebars变量和帮助程序 — 它不计算PQL。 将PQL函数(如upperCase())包装在{{...}}中会导致“无法找到帮助程序”错误。 请改用{%= ... %}:
{{upperCase(cleanName)}}{%= upperCase(cleanName) %}将{{#each}}与{%#if%}组合时使用命名循环别名
this.field由Handlebars渲染器解析,但不由{%#if%}条件内的PQL计算器解析。 使用as |item|定义命名别名,以便两个上下文都可以解析该字段:
在循环前将PQL函数结果分配给变量
不能直接在{{#each}}中调用PQL UDF(如topN)。 首先使用{% let %}对其进行评估,然后对结果进行迭代:
使用{% let %}避免重复函数调用
当计算值需要多次时,将其存储在变量中。 这样可提高可读性并防止冗余评估:
对dateDiff使用正确的参数顺序
dateDiff(start, end)首先采用较早的日期。 要计算未来日期前的剩余天数,请将当前日期作为第一个参数传递:
在PQL中使用=进行等式比较,而不是==
PQL使用单个=运算符实现相等。 使用==会导致语法错误。
对连字符字段名称使用反撇号 — 仅在PQL表达式中
如果XDM架构字段名称包含连字符(例如order-total),请用反撇号将其换行,以防止将连字符解析为减法运算符。 这仅在{%= ... %}个PQL表达式中受支持,在{{...}}个Handlebars块中不受支持:
{%= profile.events.`order-total` > 100 %}
对于可以直接复制到内容中的现成表达式,请参阅Personalization脚本。
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()ortoBool(), 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
xEventvariable is not available in personalization expressions; any reference toxEventresults 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 likeupperCase()andformatDate(), 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&); 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.