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

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

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

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

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

日時のレシピ date-time-recipes

レシピ 1 - 読み取り可能な形式での現在の日付の表示 recipe-current-date

formatDategetCurrentZonedDateTime() を使用して、今日の日付を任意の形式でレンダリングします。

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

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

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

クイックリファレンス quick-reference

この節には、このトピックに関連する解釈、検索、質問への回答をサポートすることを目的とした構造化された知識が含まれています。

完全に理解するには、この情報をこのページのドキュメント組み合わせる必要があります。 どちらのソースも単独で使用することを意図していません。このページでは、機能について説明していますが、この節では、用語、意図、適用可能性、制約の曖昧さを解消するのに役立つ追加コンテキストを提供しています。

概要

TL;DR

このページでは、Journey Optimizerの電子メール、SMS、プッシュコンテンツで使用する日付、配列、文字列、条件付きロジック、PQL edge ケースなど、すぐに使用できる16種類のパーソナライゼーションレシピをコピー&ペーストして使用できます。

インテント

  • すぐに使用できる日付/時間パターンをコピー(現在の日付、カウントダウン、オフセット日、時間表示、週末の検出)
  • 配列とループのパターンをコピー(リスト項目、上位N項目、条件付き項目別レンダリング)
  • 文字列の書式設定パターンのコピー(文字列のクリーニングと再利用、JSON引用符、大文字の日付コンポーネント)
  • コンディショナルロジックパターンをコピー(マルチブランチ if/elseif/else、null-safe属性表示)
  • PQL エッジケース(ハイフネートキー、数値イベント ID、型強制)の処理
用語集
  • Personalization recipe:パーソナライゼーションエディターの構文を使用した、一般的なパーソナライゼーションのユースケースに対応した、すぐに使用できるコピー&ペーストのパターン。 (製品固有)
  • formatDate:指定された形式パターンを使用して日付を文字列に変換する関数(例:"MMMM dd, yyyy")。
  • dateDiff: 2つの日付の数値の差を計算する関数。
  • getCurrentZonedDateTime():現在の日時をタイムゾーンに応じた形式で返す関数。
  • topN:配列を指定された数値フィールドで降順に並べ替え、上位N個の項目を返すPQL関数。 Handlebars ループで使用する前に、{% let %}を介して割り当てる必要があります。
  • {% let %}:計算値を保存するためのHandlebars変数割り当て構文。後続のHandlebars コンテキストでPQL関数の結果を参照する必要がある場合に必要です。
  • replaceAll:文字列内のパターンのすべての出現を置き換える文字列関数。元の文字列を変更せずに新しい文字列を返します。
用語
  • 正規名: パーソナライゼーションレシピ – バリアント:パターン、テンプレート、例、パターンのコピー&ペースト
  • 混同しないでください: {%= ... %} (PQL式の構文 – 評価され、計算値を返します) ≠ {{...}} (Handlebars補間 – 変数またはテンプレート式をレンダリングします)
  • 混同しないでください: {%#if%} / {%/if%} (Journey Optimizerの条件付き構文、パーセント中括弧) ≠ {{#if}} / {{/if}} (標準のHandlebarsの条件付き構文)
  • 混同しないでください: topN(array, field, n) (フィールドを降順で並べ替え、上位Nを返します) ≠ head(array) (配列の最初の項目のみを返します)
  • 混乱しないでください: dayOfWeek() (メッセージのコンテンツで使用され、日に基づいて表示を調整する) ≠ ジャーニー時間条件「曜日」オプション (ジャーニー条件アクティビティで使用され、プロファイルのルートが異なる)
  • 混同しないでください:​日付形式パターン y (暦年 – 正解)≠ Y (週ベースの年 – 年の境界で予期しない結果が発生する可能性があります)
ガードレールと制限
  • {{#each}}はジャーニー条件アクティビティではサポートされていません。ジャーニー条件の配列フィルタリングにコレクション管理関数を使用してください。
  • ハイフネーション付きの属性キーのバックティックエスケープは、PQL式({%= ... %})内でのみサポートされています。バックティックは、プレーンハンドルバー補間({{...}})では受け付けられません。
  • topNはPQL関数であり、{{#each}} ループ ターゲットとして使用する前に{% let %}変数に割り当てる必要があります。
  • {%#if%} ブロック内でループ変数を使用する場合、名前付きループエイリアスを宣言します(例:as |order|)。this.statusは、{%#if%}内のPQL エバリュエーターによって解決されません。
  • 暦年のformatDate パターンで小文字のyを使用します。Y (週ベースの年)は、年末の境界で予期しない値が生成される場合があります。
FAQ

Q: パーソナライゼーションにおける{%= ... %}{{...}}の違いは何ですか?

{%= ... %}はPQL式の構文です。この構文は評価され、計算された値(数値、文字列、ブール値)を返します。 {{...}}はHandlebars補間です。変数またはテンプレート式をレンダリングします。 どちらもパーソナライゼーションコンテンツに表示されますが、目的が異なります。

Q: Handlebars {{#each}} ループ内でPQL関数の結果を使用するにはどうすればよいですか?

PQL関数の結果を{% let variableName = pqlFunction(...) %}を使用して変数に割り当て、{{#each variableName}}を使用して反復処理します。

Q: {{#each}}をジャーニー条件アクティビティで使用できますか?

いいえ。 {{#each}}は、メッセージのパーソナライゼーションコンテンツ(電子メール、SMS、プッシュ通知)でのみ使用できます。 ジャーニー条件での配列フィルタリングの場合は、コレクション管理関数を使用します。

Q:名前にハイフンが含まれるフィールドを参照する方法を教えてください。

ハイフネーション付きのキーをPQL式{%= profile.events.`order-total` > 100 %}内でバックティックに折り返します。 プレーンハンドルバー補間では、バックティックはサポートされていません。必要に応じて、中間ステップとして{% let %}変数を使用してください。

Q: topNさんが{{#each}} ループの前に{% let %}を必要とするのはなぜですか?

topNは、PQL リストを返すPQL関数です。 {% let %}変数に割り当てると、結果はHandlebars コンテキストで利用できるようになり、{{#each}}で反復できるようになります。

recommendation-more-help
journey-optimizer-help