このページ: Handlebars 反復構文を使用して、イベント、カスタムアクション応答、データセット参照など、コンテキストデータソースの配列をループし、動的なリストをメッセージに表示する方法について説明します。
Handlebars 反復構文を使用して、イベント、カスタムアクション応答、他のコンテキストデータなど、様々なソースからのデータの動的なリストをメッセージに表示する方法について説明します。
概要 overview
Journey Optimizer では、メッセージのパーソナライゼーション中に複数のソースからのコンテキストデータにアクセスできます。 ネイティブチャネル(メール、プッシュ、SMS)で Handlebars 構文を使用して、これらのソースからの配列を反復処理し、製品リスト、レコメンデーション、その他の繰り返し要素などの動的コンテンツを表示できます。
使用可能なコンテキストソース:
- イベント:ジャーニーイベント(ビジネスイベント、単一イベント)からのデータ
- カスタムアクションの応答:カスタムアクションを介した外部 API 呼び出しから返されたデータ
- データセット参照:Adobe Experience Platform データセットから取得した強化されたデータ
- 技術プロパティ:ジャーニー ID や補足識別子などのジャーニーメタデータ
- ジャーニーコンテキスト:実行中にアクセス可能なその他のジャーニー関連データ
- オーケストレーションキャンペーンのエンリッチメントコレクション(オーケストレーションキャンペーンのみ):オーケストレーションキャンペーンでのパーソナライズの追加を参照してください。
このガイドでは、メッセージ内の各ソースからの配列を反復処理する方法と、ジャーニーアクティビティを設定する際に配列を操作する方法について説明します。 メッセージのパーソナライゼーションの基本を理解するには、Handlebars 反復構文から始めるか、ジャーニー式での配列の操作を参照して、配列データをカスタムアクションやデータセット参照に渡す方法を学んでください。
Handlebars 反復構文 syntax
Handlebars には、配列を反復処理する {{#each}} ヘルパーが用意されています。 基本構文は次のとおりです。
主なポイント:
arrayPathを配列データへのパスに置き換えますitemを任意の変数名(例:product、response、element)に置き換えます{{item.propertyName}}を使用して各項目のプロパティにアクセスします- マルチレベルの配列に対して複数の
{{#each}}ブロックをネストできます
イベントデータの反復処理 event-data
イベントデータは、ジャーニーがイベントによりトリガーされた際に使用できます。 これは、買い物かごの内容、注文項目、フォームの送信など、ジャーニーが開始された時点でキャプチャされたデータを表示するのに役立ちます。
イベントのコンテキストパス
<event_ID>:ジャーニーで設定されたイベントの一意の ID<fieldPath>:イベントスキーマ内のフィールドまたは配列へのパス
1697323153)である場合は、式パス内でバックティック(`)で囲みます。 バックティックがないと、PQL パーサーにより、構文エラーが発生します。| code language-handlebars |
|---|
|
例:イベントからの買い物かご項目
イベントスキーマに productListItems 配列(標準 XDM 形式)が含まれている場合は、以下のサンプルに示すように買い物かごの内容を表示できます。
| code language-handlebars |
|---|
|
例:イベントでネストされた配列
ネストされた構造には、ネストされた {{#each}} ブロックを使用します。
| code language-handlebars |
|---|
|
ネストについて詳しくは、ベストプラクティスを参照してください。
カスタムアクション応答の反復処理 custom-action-responses
カスタムアクション応答には、外部 API 呼び出しから返されたデータが含まれます。 これは、ロイヤルティポイント、製品レコメンデーション、在庫ステータス、パーソナライズされたオファーなど、システムからのリアルタイム情報を表示するのに役立ちます。
カスタムアクションのコンテキストパス
<actionName>:ジャーニーで設定されたカスタムアクションの名前<fieldPath>:応答ペイロード内のフィールドまたは配列へのパス
例:API からの製品レコメンデーション
カスタムアクションから返された製品レコメンデーションの配列を反復処理し、メッセージに個別のカードとして表示するには、以下の例を参照してください。
API 応答:
| code language-json |
|---|
|
メッセージのパーソナライゼーション:
| code language-handlebars |
|---|
|
例:カスタムアクションからのネストされた配列
ネストされた配列(各オブジェクトに別の配列が含まれるオブジェクトの配列)を含むカスタムアクション応答を反復処理するには、以下の例を参照してください。 これは、ネストされた {{#each}} ループを使用して複数のレベルのデータにアクセスする方法を示しています。
API 応答:
| code language-json |
|---|
|
メッセージのパーソナライゼーション:
| code language-handlebars |
|---|
|
より複雑なネストパターンについて詳しくは、ベストプラクティスを参照してください。
例:ロイヤルティ層のメリット
ロイヤルティステータスに基づいて動的なメリットを表示するには、以下の例を参照してください。
API 応答:
| code language-json |
|---|
|
メッセージのパーソナライゼーション:
| code language-handlebars |
|---|
|
データセット参照結果の反復処理 dataset-lookup
データセット参照アクティビティを使用すると、ジャーニーの実行中に Adobe Experience Platform データセットからデータを取得できます。 強化されたデータは、配列として保存され、メッセージ内で反復処理できます。
データセット参照アクティビティの設定について詳しくは、この節を参照してください。 データセット参照は、イベントデータと組み合わせると特に強力です。実用的なユースケースについて詳しくは、例:データセット参照を使用して強化されたイベントデータを参照してください。
データセット参照のコンテキストパス
<activityID>:データセット参照アクティビティの一意の IDentities:データセットから取得した強化されたデータの配列
例:データセットからの製品詳細
データセット参照アクティビティを使用して、SKU に基づいて製品情報を取得する場合は、以下のサンプルを参照してください。
データセット参照の設定:
- 参照キー:
list(@event{purchase_event.products.sku}) - 返されるフィールド:
["SKU", "category", "price", "name"]
メッセージのパーソナライゼーション:
| code language-handlebars |
|---|
|
例:データセットデータを使用してフィルタリングされた反復
反復中にデータセット参照結果をフィルタリングし、特定の条件に一致する項目(例:特定のカテゴリからの製品)のみを表示するには、{{#each}} ループ内で条件付き {{#if}} ステートメントを使用します。 以下の例を参照してください。
| code language-handlebars |
|---|
|
条件付きフィルタリングについて詳しくは、ベストプラクティスを参照してください。
例:データセット参照からの合計の計算
データセット参照結果を反復処理しながら合計を計算して表示するには、以下の例を参照してください。
| code language-handlebars |
|---|
|
ジャーニーの技術プロパティの使用 technical-properties
ジャーニーの技術プロパティには、ジャーニー ID や補足識別子など、ジャーニー実行に関するメタデータへのアクセス権が用意されてします。 これらは、反復パターンと組み合わせると、特に特定のジャーニーインスタンスに基づいて配列をフィルタリングする際に役立つ場合があります。
使用可能な技術プロパティ
例:補足識別子を使用した配列項目のフィルタリング
配列を含むイベントトリガージャーニーで補足識別子を使用する際は、フィルタリングして、現在のジャーニーインスタンスに関連する項目のみを表示できます。 補足識別子について詳しくは、このガイドを参照してください。
シナリオ:複数の予約でジャーニーがトリガーされますが、このジャーニーインスタンスをトリガーした特定の予約(補足 ID で識別)の情報のみを表示する必要があります。
| code language-handlebars |
|---|
|
例:トラッキング用のジャーニー ID を含める
トラッキングの目的でメッセージにジャーニー ID を含めるには、以下の例を参照してください。
| code language-handlebars |
|---|
|
複数のコンテキストソースの組み合わせ combine-sources
様々なソースからのデータを同じメッセージに組み合わせて、リッチでパーソナライズされたエクスペリエンスを作成できます。 この節では、複数のコンテキストソースを組み合わせて使用する実用的な例を示します。
組み合わせることができるコンテキストソース:
例:リアルタイムの在庫を含む買い物かご項目
イベントデータ(買い物かごの内容)とカスタムアクションデータ(在庫ステータス)を組み合わせるには、以下のサンプルを参照してください。
| code language-handlebars |
|---|
|
例:データセット参照を使用して強化されたイベントデータ
イベント SKU とデータセット参照からの詳細な製品情報を組み合わせるには、以下のサンプルを参照してください。
| code language-handlebars |
|---|
|
例:複数のソースと技術プロパティの組み合わせ
複数のコンテキストソース(プロファイルデータ、イベントデータ、カスタムアクション、技術プロパティ)を 1 つのメッセージに組み合わせるには、以下のサンプルを参照してください。
| code language-handlebars |
|---|
|
その他のコンテキストタイプ other-contexts
このガイドでは配列の反復処理に焦点を当てていますが、通常は反復を必要としないその他のコンテキストタイプもパーソナライゼーションに使用できます。 これらは、ループ処理ではなく直接アクセスされます。
これらのソースを使用した完全なパーソナライゼーション構文と例について詳しくは、以下を参照してください。
ジャーニー式での配列の操作 arrays-in-journeys
前の節では、Handlebars を使用したメッセージのパーソナライゼーションでの配列の反復処理に焦点を当てていますが、ジャーニーアクティビティを設定する際にも配列を操作します。 この節では、特にカスタムアクションにデータを渡す場合やデータセット参照で配列を使用する際に、ジャーニー式のイベントからの配列データを使用する方法について説明します。
first、all、serializeList などの関数を含むジャーニー式エディターを使用します。 メッセージコンテンツでは、{{#each}} ループを含む Handlebars 構文を使用します。カスタムアクションパラメーターへの配列値の受け渡し arrays-to-custom-actions
カスタムアクションを設定する際、多くの場合、イベント配列から値を抽出し、パラメーターとして渡す必要があります。 この節では、一般的なパターンについて説明します。
コレクションを渡す方法について詳しくは、カスタムアクションパラメーターへのコレクションの受け渡しを参照してください。
配列からの 1 つの値の抽出
ユースケース:イベント配列から特定のフィールドを取得し、GET リクエストでクエリパラメーターとして渡します。
シナリオの例:製品リストから価格が 0 を超える最初の SKU を抽出します。
イベントスキーマの例:
| code language-json |
|---|
|
カスタムアクション設定:
- カスタムアクションで、クエリパラメーター(例:
sku)をstringタイプで設定します - 動的な値を許可するには、
Variableとしてマークします
アクションパラメーターのジャーニー式:
| code language-javascript |
|---|
|
説明:
@event{YourEventName}:ジャーニーイベントを参照します.first(currentEventField.condition):条件に一致する最初の配列項目を返しますcurrentEventField:イベント配列内の各項目をループ処理する際に表します.SKU:一致した項目から SKU フィールドを抽出します- 結果:
"SKU-1"(アクションパラメーターに適した文字列)
first 関数について詳しくは、コレクション管理関数を参照してください。
配列からの値のリストの作成
ユースケース:クエリパラメーターとして渡す ID のコンマ区切りリストを作成します(例:/products?ids=sku1,sku2,sku3)。
カスタムアクション設定:
- クエリパラメーター(例:
ids)をstringタイプで設定します Variableとしてマークします
ジャーニー式:
| code language-javascript |
|---|
|
説明:
-
.all(currentEventField.condition):条件に一致するすべての配列項目を返します(リストを返します) -
currentEventField:イベント配列内の各項目をループ処理する際に表します -
.SKU: SKU 値のみを含めるようにリストをプロジェクト化します -
serializeList(list, delimiter, addQuotes):リストを文字列に結合します",":区切り文字としてコンマを使用しますtrue:各文字列要素を引用符で囲みます
-
結果:
"SKU-1,SKU-3"(クエリパラメーターに適しています)
詳細情報:
カスタムアクションのコレクション処理について詳しくは、カスタムアクションパラメーターへのコレクションの受け渡しを参照してください。
カスタムアクションへのオブジェクトの配列の受け渡し
ユースケース:オブジェクトの完全な配列をリクエスト本文で送信します(本文を含む POST または GET の場合)。
リクエスト本文の例:
| code language-json |
|---|
|
カスタムアクション設定:
- リクエスト本文で、
productsをlistObjectタイプとして定義します Variableとしてマークします- オブジェクトフィールド
id、name、price、colorを定義します(それぞれがマッピング可能になります)
ジャーニーキャンバス設定:
-
詳細設定モードで、コレクション式を設定します。
code language-javascript @event{YourEventName.commerce.productListItems.all(currentEventField.priceTotal > 0)} -
コレクションマッピング UI で、次の操作を実行します。
id→productListItems.SKUにマッピングname→productListItems.nameにマッピングprice→productListItems.priceTotalにマッピングcolor→productListItems.colorにマッピング
Journey Optimizer は、アクションペイロード構造に一致するオブジェクトの配列を構築します。
| note |
|---|
| NOTE |
イベント配列を操作する場合は、currentEventField を使用して各項目を参照します。 データソースコレクション(Adobe Experience Platform)には、currentDataPackField を使用します。 カスタムアクション応答コレクションには、currentActionField を使用します。 |
詳しくは、カスタムアクションパラメーターへのコレクションの受け渡しを参照してください。
データセット参照での配列の使用 arrays-with-dataset-lookup
データセット参照アクティビティを使用する際、値の配列を参照キーとして渡して、強化されたデータを取得できます。
例:イベント配列内のすべての SKU の製品詳細を参照します。
データセット参照の設定:
参照キーフィールドでは、list() を使用して配列パスをリストに変換します。
| code language-javascript |
|---|
|
これにより、データセットで参照するすべての SKU 値のリストが作成されます。 結果は、context.journey.datasetLookup.<activityID>.entities の配列として使用でき、メッセージ内で反復処理できます(データセット参照結果の反復処理を参照)。
制限とパターン array-limitations
ジャーニーで配列を操作する際は、次の制限に注意してください。
ジャーニーフローで配列に動的なループはない
ジャーニーでは、配列内の各項目に対して 1 つのアクションノードが複数回実行される動的なループを作成できません。 これは、制御できないパフォーマンスの問題を防ぐことを目的としています。
実行できない内容:
- カスタムアクションを配列項目ごとに 1 回動的に実行する
- 配列の長さに基づいて複数のジャーニー分岐を作成する
代わりに推奨されるパターン:
-
すべての項目を一度に送信:配列全体またはシリアル化されたリストを、すべての項目を処理する単一のカスタムアクションに渡します。 配列からの値のリストの作成を参照してください。
-
外部集計を使用:外部 API で複数の ID を受け入れ、1 回の呼び出しで組み合わされた結果を返すようにします。
-
AEP で事前計算:計算属性を使用して、プロファイルレベルで配列から値を事前計算します。
-
単一値の抽出:必要な値が 1 つのみの場合は、
firstまたはheadを使用して抽出します。 詳しくは、配列からの 1 つの値の抽出を参照してください。
詳しくは、ガードレールと制限を参照してください。
配列サイズの考慮事項
大規模な配列は、ジャーニーのパフォーマンスに影響を与える場合があります。
- イベント配列:イベントペイロードの合計を 50 KB 未満に抑えます
- カスタムアクション応答:応答ペイロードは 100 KB 未満にする必要があります
- データセット参照結果:参照キーと返されるエンティティの数を制限します
完全な例:カスタムアクションに対するイベント配列 complete-example
カスタムアクションでイベント配列を使用する方法を示す完全なワークフローを以下に示します。
シナリオ:ユーザーが買い物かごを放棄すると、買い物かごのデータを外部のレコメンデーション API に送信してパーソナライズされた提案を取得し、メールで表示します。
手順 1:カスタムアクションを設定
カスタムアクション「GetCartRecommendations」を作成します。
- メソッド:POST
- URL:
https://api.example.com/recommendations - リクエスト本文:
| code language-json |
|---|
|
cartItemsをlistObjectおよびVariableタイプとしてマークしますsku(文字列)、price(数値)、quantity(整数) のフィールドを定義します
詳しくは、カスタムアクションの設定を参照してください。
手順 2:応答ペイロードを設定
カスタムアクションで、応答を設定します。
| code language-json |
|---|
|
詳しくは、API 呼び出し応答の使用を参照してください。
手順 3:ジャーニー内のアクションを関連付け
-
買い物かごの放棄イベントの後に、カスタムアクションを追加します
-
cartItemsコレクションの詳細設定モードの場合:code language-javascript @event{cartAbandonment.commerce.productListItems.all(currentEventField.quantity > 0)} -
コレクションフィールドをマッピングします。
sku→productListItems.SKUprice→productListItems.priceTotalquantity→productListItems.quantity
手順 4:メールで応答を使用
メールコンテンツで、レコメンデーションを反復処理します。
| code language-handlebars |
|---|
|
手順 5:設定をテスト
ライブジャーニーを実行する前に、アクション設定の「テストリクエストを送信」機能を使用してカスタムアクションをテストし、作成されたリクエストと値を確認します。
- ジャーニーテストモードを使用します
productListItems配列を含むサンプルイベントデータでトリガーします- カスタムアクションが正しい配列構造を受け取ることを確認します
- アクションテストログを確認します
- メールをプレビューして、両方の配列が正しく表示されていることを確認します
詳しくは、カスタムアクションのトラブルシューティングを参照してください。
ベストプラクティス best-practices
コンテキストデータを反復処理して、維持可能でパフォーマンスの高いパーソナライゼーションを作成する際は、次のベストプラクティスに従います。
わかりやすい変数名の使用
反復処理している内容を明確に示す変数名を選択します。 これにより、コードの読みやすさが向上し、維持が容易になります。 詳しくは、パーソナライゼーション構文を参照してください。
| code language-handlebars |
|---|
|
ループ内の式フラグメント
{{#each}} ループ内で式フラグメントを使用する際は、ループ範囲の変数をフラグメントパラメーターとして渡すことができないことに注意してください。 ただし、フラグメントは、フラグメント外部のメッセージコンテンツで定義されているグローバル変数にアクセスできます。
サポートされているパターン - グローバル変数の使用:
| code language-handlebars |
|---|
|
globalDiscount はメッセージ内でグローバルに定義されているので、フラグメントはこれを参照できます。
サポートされていないパターン - ループ変数の受け渡し:
| code language-handlebars |
|---|
|
回避策:フラグメントを使用する代わりに、パーソナライゼーションロジックをループ内に直接含めるか、ループの外でフラグメントを呼び出します。
例やその他の回避策などについて詳しくは、ループ内の式フラグメントの使用を参照してください。
空の配列の処理
配列が空の場合にフォールバックコンテンツを指定するには、 {{else}} 句を使用します。 詳しくは、ヘルパー関数を参照してください。
| code language-handlebars |
|---|
|
条件付きヘルパーとの組み合わせ
条件付きコンテンツの場合は、ループ内で {{#if}} を使用します。 詳しくは、条件付きルールを参照し、カスタムアクション応答およびデータセット参照の節の例を参照してください。
| code language-handlebars |
|---|
|
パフォーマンスの反復の制限
大規模な配列の場合は、反復回数を制限することを考慮します。
| code language-handlebars |
|---|
|
配列メタデータへのアクセス
Handlebars には、ループ内で高度な反復パターンを実行するのに役立つ特別な変数が用意されています。
@index:現在の反復インデックス(0 ベース)@first:最初の反復の場合は True@last:最後の反復の場合は True
| code language-handlebars |
|---|
|
@index、@first、@last)は、メッセージのパーソナライゼーションの {{#each}} ループ内でのみ使用できます。 ジャーニー式で配列を操作する場合(カスタムアクションに渡す前に配列から最初の項目を取得するなど)は、head、first、all などの配列関数を使用します。 詳しくは、ジャーニー式での配列の操作を参照してください。トラブルシューティング troubleshooting
反復に問題がありますか? この節では、一般的な問題と解決策について説明します。
配列に表示されない
問題:配列の反復にコンテンツが表示されません。
考えられる原因と解決策:
-
パスが正しくない:コンテキストソースに基づいて、配列への正確なパスを確認します。
-
配列が空である:
{{else}}句を追加して、配列にデータがないかどうかを確認します。 例について詳しくは、ベストプラクティスを参照してください。 -
データがまだ使用できない:ジャーニーフロー内のメッセージアクティビティの前に、カスタムアクション、イベント、データセット参照アクティビティが実行されていることを確認します。
構文エラー
問題:式の検証が失敗するか、メッセージがレンダリングされません。
一般的なミス:
- 終了タグが欠落している:すべての
{{#each}}には{{/each}}が必要です。 適切な構造について詳しくは、Handlebars 反復構文を参照してください。 - 変数名が正しくない:ブロック全体で変数名を一貫して使用します。 命名規則について詳しくは、ベストプラクティスを参照してください。
- パス区切り文字が正しくない:スラッシュやその他の文字ではなく、ドット(
.)を使用します
ループ内で式フラグメントが機能しない
問題:式フラグメントが {{#each}} ループ内で使用された際、期待されるコンテンツが表示されないか、空または期待されない出力が表示されます。
考えられる原因と解決策:
-
ループ変数をパラメーターとして渡そうとしている:式フラグメントは、ループ範囲の変数(現在の反復項目など)をパラメーターとして受け取ることができません。 これは既知の制限です。
解決策:次のいずれかの回避策を使用します。
- フラグメントがアクセスできるグローバル変数をメッセージ内に定義する
- フラグメントを使用する代わりに、パーソナライゼーションロジックをループ内に直接含める
- ループ固有のデータを必要としない場合は、ループの外でフラグメントを呼び出す
-
フラグメントが使用できないパラメーターを想定している:フラグメントが特定の入力パラメーターを受け取るようにデザインされた場合、これらのパラメーターをループ内から渡すことができないと、フラグメントは正しく動作しません。
解決策:フラグメントがアクセスできるグローバル変数を使用するようにアプローチを再構築します。 例について詳しくは、ベストプラクティス - ループ内の式フラグメントを参照してください。
-
変数範囲が正しくない:フラグメントが、ループ範囲内にのみ存在する変数を参照しようとしている可能性があります。
解決策:フラグメントに必要な変数をメッセージレベル(ループの外)で定義し、グローバルにアクセスできるようにします。
説明、例、推奨されるパターンなどについて詳しくは、ループ内の式フラグメントの使用を参照してください。
反復のテスト
ジャーニーテストモードを使用して、反復を確認します。 これは、カスタムアクションやデータセット参照を使用する際に特に重要です。
- ジャーニーをテストモードで開始します
- サンプルデータを使用してイベントまたはカスタムアクションをトリガーします
- メッセージプレビューを確認し、反復が正しく表示されることを確認します
- テストモードのログでエラーがないか確認します(カスタムアクションテストモードログを参照)
関連トピック related-topics
パーソナライゼーションの基本:パーソナライゼーションの基本を学ぶ | パーソナライゼーションの追加 | パーソナライゼーション構文 | ヘルパー関数 | 条件付きルールの作成
ジャーニー設定:イベントについて | カスタムアクションの設定 | カスタムアクションパラメーターへのコレクションの受け渡し | カスタムアクションでの API 呼び出し応答の使用 | カスタムアクションのトラブルシューティング | ジャーニーでの Adobe Experience Platform データの使用 | ジャーニーでの補助識別子の使用 | ガードレールと制限 | ジャーニーのテスト
ジャーニー式関数:高度な式エディター | コレクション管理関数(first、all、last) | リスト関数(serializeList、filter、sort) | 配列関数(head、tail)
パーソナライゼーションのユースケース:買い物かご放棄メール | 注文ステータス通知
メッセージデザイン:メールデザインの基本を学ぶ | プッシュ通知の作成 | SMS メッセージの作成 | コンテンツのプレビューとテスト
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 how to use Handlebars
{{#each}}syntax to loop over arrays from contextual sources — events, custom action responses, dataset lookups, and technical properties — in message personalization, and how to work with arrays in journey expression syntax when configuring journey activities.
Intents:
- Iterate over event array data (e.g., cart items, order items) in message personalization using
{{#each}} - Iterate over custom action response arrays (e.g., product recommendations) in messages
- Iterate over dataset lookup result arrays in messages
- Combine data from multiple contextual sources in a single personalized message
- Pass array values to custom action parameters using journey expression syntax
- Use arrays as lookup keys in Dataset Lookup activities
- Apply best practices for empty array fallbacks, variable naming, performance, and expression fragment scoping
Glossary:
- Handlebars: A templating language used in Journey Optimizer message personalization for iteration (
{{#each}}) and conditional rendering ({{#if}}). (product-specific) {{#each}}helper: Handlebars syntax for iterating over an array; each iteration exposes the current item via a named variable (e.g.,|product|). (product-specific)- Contextual data: Data available at message send time from journey sources — events, custom action responses, dataset lookups, and journey technical properties — as opposed to static profile attributes. (product-specific)
currentEventField: A reference used in journey expressions (not Handlebars) to refer to each item in an event array during filtering or mapping operations.currentActionField: Used in journey expressions to refer to each item in a custom action response collection.currentDataPackField: Used in journey expressions to refer to each item in a data source collection.serializeList: A journey expression function that converts a list of values into a delimited string (e.g., comma-separated), suitable for use as a query parameter.- Supplemental identifier: A journey-level identifier that distinguishes concurrent journey instances triggered by the same profile; used to filter an array to the item relevant to the current instance.
Guardrails:
- Journeys cannot create dynamic loops where one action node executes multiple times per array item — this is by design to prevent performance issues. Pass the entire array or a serialized list to a single custom action instead.
- Keep event payloads under 50KB total.
- Custom action response payloads should be under 100KB.
- Limit the number of dataset lookup keys and returned entities for performance.
- Expression fragments cannot receive loop-scoped variables (e.g., the current
{{#each}}iteration item) as parameters — this is a known limitation. Use global variables or inline logic instead. - Numeric event IDs must be wrapped in backticks in expression paths (e.g.,
context.journey.events.`1697323153`.fieldName); without backticks, the PQL parser raises a syntax error.
Terminology:
- Canonical name: Handlebars iteration — variants:
{{#each}}loop, each loop, array iteration - Do not confuse: Handlebars
{{#each}}syntax (used in message content for iteration and display) ≠ journey expression syntax (used in journey activity configuration — uses functions likefirst,all,serializeList) - Do not confuse:
currentEventField(journey expressions over event arrays) ≠currentActionField(custom action response collections) ≠currentDataPackField(data source collections) - Do not confuse:
@index/@first/@last(Handlebars special variables, only available within{{#each}}loops in message content) ≠first/headfunctions (journey expression functions for extracting single items, used in journey activity configuration)
FAQ:
- Q: What is the difference between Handlebars syntax and journey expression syntax when working with arrays? — Handlebars
{{#each}}is used in message content for iteration and display. Journey expression syntax — using functions likefirst,all, andserializeList— is used in journey activity configuration (e.g., custom action parameters, conditions). They are distinct syntaxes used in different contexts. - Q: Can I loop a journey action node so it executes once per array item? — No. Journeys cannot create dynamic loops that execute an action node multiple times per item. Instead, pass the entire array or a serialized list to a single custom action that processes all items, or use external aggregation.
- Q: Can I pass the current loop item to an expression fragment inside a
{{#each}}loop? — No. Expression fragments cannot receive loop-scoped variables as parameters. Use global variables defined outside the loop, or include the personalization logic directly within the loop instead of using a fragment. - Q: How do I display fallback content when an array is empty? — Use the
{{else}}clause within the{{#each}}block. Content inside{{else}}is rendered when the array has no items. - Q: What do
@index,@first, and@lastmean inside a{{#each}}loop? — These are special Handlebars variables available only within{{#each}}loops in message content:@indexis the 0-based current iteration index,@firstis true for the first iteration, and@lastis true for the last iteration.