パーソナライゼーションのレシピ personalization-recipes

このページ:​日付、配列、文字列、条件付きロジック、PQL エッジケースに対して、すぐに使用できるパーソナライゼーションレシピについて説明します。これにより、Adobe Journey Optimizer コンテンツに直接コピーできます。

このページでは、Adobe Journey Optimizer で最も一般的なユースケースに対して、すぐに使用できるパーソナライゼーションパターンについて説明します。 すべての例でパーソナライゼーションエディターの構文を使用し、メール、SMS、プッシュコンテンツに直接コピーできます。

使用可能な関数の完全な参照について詳しくは、ヘルパー関数、日時関数、文字列関数、配列関数を参照してください。

TIP
例をコピーする前に、最も一般的な構文エラーの回避について詳しくは、パーソナライゼーションのベストプラクティスを参照してください。

日時のレシピ 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日(PT)の 7 日前)

また、固定時間(例:午前 9 時)を設定するには、setHours と組み合わせます。

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

レシピ 4 - HH:MM としてのみの現在の時間の表示 recipe-time-only

extractHours と extractMinutes を使用して時間部分のみを表示します。その際、分については先頭のゼロを補完する処理を行います。

{% 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}} を使用してプロファイル配列を反復処理し、各項目をレンダリングします。 これは、パーソナライゼーションエディター(メール、SMS、プッシュ)でのみ使用できます。

{{#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 を使用して、上位の項目を 1 つのみ取得します。

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

レシピ 8 - 配列項目ごとに条件付きでのコンテンツのレンダリング recipe-conditional-loop

{{#each}} 内の {%#if%} を使用して、一致する項目に対してのみ出力をレンダリングします。 PQL 評価基準が条件内の属性参照を解決できるように、as |order| を使用してループエイリアスを定義します。

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

formatDate と upperCase を組み合わせて、月や曜日の名前をすべて大文字でレンダリングします。

{%= 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 - Null セーフ属性表示 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-total、event-type)が含まれている場合は、ハイフンが減算演算子として解釈されないように、PQL 式内でバックティックで囲みます。

{%= profile.events.`order-total` > 100 %}
NOTE
バックティックは、PQL式({%= ... %})内でのみサポートされています。 これらは、通常の Handlebars の補間({{...}})では使用できません。 ハイフンを含むフィールド値を直接レンダリングする必要がある場合は、最初に PQL 式で評価するか、{% let %} を使用して変数に格納します。

レシピ 15 - コンテキスト属性での数値イベント ID の参照 recipe-numeric-event-id

ID が数値文字列(例:1697323153)であるジャーニーコンテキストイベントを使用する場合は、ID をバックティックで囲み、toDateTime() および formatDate() と共に {% let %} を使用します。

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