報酬の定義ガイド reward-definition-guide

目次

ロイヤルティに関する課題を解決

チャレンジタスク、マイルストーン、またはチャレンジが​ を完了し、報酬値が設定されている ​場合、プラットフォームは報酬プロバイダーのHTTP エンドポイントをJSON ペイロードで呼び出すことによって報酬を発行します。 報酬定義​は、発行する報酬を表し、プロバイダーが期待する正確なペイロードを形成するJSONatarewardJsonataを提供します。

このガイドでは、報酬プロバイダーの設定、報酬の定義の作成、rewardJsonata式の記述、評価時に利用可能なコンテキストの把握について説明します。

2 レベルモデル

報酬は、次の2つのレベルで構成されています。

Reward Provider  (endpoint, auth, headers)
└── Reward Definition  (denomination, rewardJsonata)
└── Reward Definition
└── ...

報酬プロバイダー​は、単一の外部報酬システムを表します。配信エンドポイント URL、認証、およびカスタム HTTP ヘッダーを保持します。 1つのプロバイダーには、複数の​ 報酬定義 ​を保持でき、各プロバイダーが提供する報酬タイプまたは名称(例:「50星」、「ダブルスター」、「無料アイテム」)を表します。

チャレンジは、プロバイダーとGUIDによる定義を参照します。 報酬が発行されると、プラットフォームは定義のrewardJsonata式を評価し、結果をプロバイダーのエンドポイントにPOSTします。

ポイントプロバイダーと定義フィールド

報酬プロバイダーのフィールド
table 0-row-4 1-row-4 2-row-4 3-row-4 4-row-4 5-row-4 6-row-4 7-row-4 8-row-4 html-authored
フィールド タイプ 必須 説明
guid String なし(システム割り当て) 一意のID: 読み取り専用:
name String 組織内で一意の表示名。
desc String × プロバイダーの人間が判読可能な説明。
enabled Boolean × falseの場合、このプロバイダーのすべての定義に対する特典配信は
中断されます。
url String 報酬ペイロードを受信するHTTP エンドポイント。
プラットフォームは、このURLに対して評価された
rewardJsonata出力をPOSTします。
additionalHeaders Object × すべての
配信リクエストに含めるカスタム HTTP ヘッダー(例:API キー、
コンテンツタイプの上書き)。
maxRatePerSecond Integer × プロバイダーごとのオプションのレート制限(1 ~ 5000)。
Nullは無制限を意味します。
enableMTLS Boolean × エンドポイントに相互TLSが必要かどうか。
報酬定義フィールド
table 0-row-4 1-row-4 2-row-4 3-row-4 4-row-4 5-row-4 6-row-4 7-row-4 html-authored
フィールド タイプ 必須 説明
guid String なし(システム割り当て) 一意のID: 読み取り専用:
name String プロバイダー内で一意の表示名。
denomination String × 表示
で使用され、式
reward.denomination
で使用可能な報酬の単位(例:"Stars""Points""Miles")。
desc String × 報酬の説明。式で
reward.descとして使用できます。
enabled Boolean × falseの場合、この定義は非アクティブであり
報酬を発行しません。
isDefault Boolean × これをサンドボックス全体のデフォルト
の報酬定義としてマークします。 すべてのプロバイダーで一度に1つの定義
のみをデフォルトにできます。
新しいデフォルトを設定すると、前の定義が消去されます。
公開時にパーソナライズされた課題
に関する報酬の詳細を自動入力するために使用されます。
rewardJsonata String JSONata式が
リワード発行時に評価されました。 完全な
報酬コンテキストを受け取り、JSON
ペイロードをプロバイダーにPOSTに返す必要があります。

報酬のコンテキスト

rewardJsonataが評価されると、報酬イベントに関する既知のすべての情報を含む単一のルートオブジェクトを受け取ります。 エクスプレッション内のすべてのパスは、このルートに関連しています。

{
  "rewardContext": {
    "rewardValue": "50",
    "source":      "challenge"
  },
  "reward": {
    "name":         "500 Stars",
    "desc":         "Issue 500 Stars to the member",
    "denomination": "Stars",
    "enabled":      true
  },
  "task": { ... },
  "milestone": { ... },
  "challenge": { ... },
  "timestamp": "2026-02-10T00:29:22.538+00:00"
}
コンテキストフィールド
table 0-row-2 1-row-2 2-row-2 3-row-2 4-row-2 5-row-2 6-row-2 7-row-2 8-row-2 9-row-2 10-row-2 11-row-2 12-row-2 13-row-2 14-row-2 15-row-2 16-row-2
フィールド 説明
rewardContext.rewardValue この発行をトリガーしたチャレンジ、タスク、またはマイルストーンに設定された報酬値文字列。
rewardContext.source 報酬のトリガーは"task""challenge"、または"milestone"です。
reward RewardDefinition自体 – namedescdenomination
task 完了中のタスク (例:accumulatorsschedulereward)。
task.accumulators.spend タスクによって累積された適格な支出の合計。
task.accumulators.qty タスクによって累積された適格な項目数の合計。
task.accumulators.item_list タスクに適用されたすべての適格項目。 各エントリには、itemtransactionIdtimestamputcOffsetlocationIdがあります。
task.accumulators.item_list[-1] 適用された最新の項目(JSONata負のインデックス)。 最後のトランザクション IDまたはタイムスタンプの取得に便利です。
task.schedule.currentStreak 現在の連続訪問ストリーク数(ストリークの課題の場合)。
task.schedule.currentVisits 合計訪問数(訪問チャレンジの場合)。
milestone この報酬をトリガーしたマイルストーン。マイルストーン報酬でない場合はnullcountreward.rewardValueが含まれます。
challenge.profileId メンバーのロイヤルティ ID。
challenge.kvpCustom チャレンジで設定されたカスタムキーと値のペア。 キャンペーン ID、製品名、プロバイダー固有のメタデータを渡すための共通パターン。
challenge.name チャレンジ名。
challenge._id チャレンジ ID。
timestamp ISO 8601の報酬発行のタイムスタンプ。

rewardJsonata式の記述

式は、報酬コンテキストを入力として受け取り、JSON オブジェクト(プロバイダーのエンドポイントにPOSTされたペイロード)を返す必要があります。 そのオブジェクトの形状は、プロバイダーのAPIに完全に依存しています。プロバイダーが期待する構造にコンテキストフィールドをマッピングします。

単純な固定ペイロード

最も単純なケース:プロバイダーには、コンテキストから既知のポイント数とメンバーIDが必要です。

code language-jsonata
{
  "memberId":   challenge.profileId,
  "points":     $number(rewardContext.rewardValue),
  "currency":   reward.denomination
}

出力:

code language-json
{
  "memberId": "ADB-0000030",
  "points":   50,
  "currency": "Stars"
}

rewardContext.rewardValueは常に文字列です。 プロバイダーが数値を想定している場合は、$number()を使用して変換します。

プロバイダー固有のメタデータにkvpCustomを使用しています

多くの場合、プロバイダーは、課題の実行ごとに固有のキャンペーン IDやソースシステムコードなどのフィールドを必要とします。 チャレンジのオーサリング時にこれらをchallenge.kvpCustomに保存し、その後、それらをエクスプレッションで参照することで、キャンペーン全体でエクスプレッションを再利用できます。

code language-jsonata
{
  "memberId":         challenge.profileId,
  "points":           $number(rewardContext.rewardValue),
  "campaignId":       challenge.kvpCustom.campaignId,
  "transactionSource": "AJO"
}

また、チャレンジ単位ではなく、特定の報酬タイプに固定された定数に対してreward.kvpCustomを使用することもできます。

タスクアキュムレーターデータの使用

タスクのアキュムレータには、選定イベントごとにレコードが保持されます。 item_list[-1]を使用して、最近適用された項目にアクセスします。このtransactionIdtimestampは、プロバイダー側での監査証跡と重複排除に役立ちます。

code language-jsonata
{
  "memberId":       challenge.profileId,
  "points":         $number(rewardContext.rewardValue),
  "transactionId":  task.accumulators.item_list[-1].transactionId,
  "transactionDate": task.accumulators.item_list[-1].timestamp
}
テキストメッセージの作成

通知ベースのプロバイダー(Slack、SMS、電子メール)の場合、JSONataの&連結演算子を使用してメッセージ文字列を直接作成できます。

code language-jsonata
{
  "text": "You just earned " & rewardContext.rewardValue & " " & reward.denomination & "!"
}

出力:

code language-json
{
  "text": "You just earned 50 Stars!"
}

例1 — シンプルなポイントプロバイダー

シナリオ:​基本的なロイヤルティポイント APIでは、メンバーIDとポイント額が必要です。

報酬の定義:

code language-json
{
  "name":         "Standard Points",
  "denomination": "Points",
  "desc":         "Award loyalty points",
  "enabled":      true,
  "rewardJsonata": "{\"memberId\": challenge.profileId, \"pointQuantity\": $number(rewardContext.rewardValue), \"denomination\": reward.denomination}"
}

形式の式:

code language-jsonata
{
  "memberId":      challenge.profileId,
  "pointQuantity": $number(rewardContext.rewardValue),
  "denomination":  reward.denomination
}

ペイロードがプロバイダー​にPOSTされました

code language-json
{
  "memberId":      "ADB-0000030",
  "pointQuantity": 50,
  "denomination":  "Points"
}
例2 — キャンペーンメタデータを含むプロバイダーペイロード

シナリオ:​このプロバイダーには、監査フィールド、キャンペーン参照、メンバーの説明を含む構造化アワードレコードが必要です。 キャンペーン固有の値はchallenge.kvpCustomに保存されるため、式を編集することなく、同じ報酬の定義がキャンペーン間で機能します。

チャレンジkvpCustom (チャレンジのオーサリング時に設定):

code language-json
{
  "parentCampaignId": "CAMP-2026-Q1",
  "productName":      "Loyalty Program"
}

報酬の定義:

code language-json
{
  "name":         "Stars — Campaign Award",
  "denomination": "Stars",
  "desc":         "Issue Stars for completing a qualifying purchase",
  "enabled":      true,
  "rewardJsonata": "{\"awardPoints\":[{\"idType\":\"externalId\",\"id\":challenge.profileId,\"transactionId\":task.accumulators.item_list[-1].transactionId,\"transactionDate\":task.accumulators.item_list[-1].timestamp,\"originalTransactionId\":task.accumulators.item_list[-1].transactionId,\"transactionSource\":\"AJO\",\"channelSource\":\"Web\",\"parentCampaignId\":challenge.kvpCustom.parentCampaignId,\"productName\":challenge.kvpCustom.productName,\"memberAwardDescription\":reward.desc,\"pointQuantity\":$number(rewardContext.rewardValue)}]}"
}

形式の式:

code language-jsonata
{
  "awardPoints": [
    {
      "idType":                "externalId",
      "id":                    challenge.profileId,
      "transactionId":         task.accumulators.item_list[-1].transactionId,
      "transactionDate":       task.accumulators.item_list[-1].timestamp,
      "originalTransactionId": task.accumulators.item_list[-1].transactionId,
      "transactionSource":     "AJO",
      "channelSource":         "Web",
      "parentCampaignId":      challenge.kvpCustom.parentCampaignId,
      "productName":           challenge.kvpCustom.productName,
      "memberAwardDescription": reward.desc,
      "pointQuantity":         $number(rewardContext.rewardValue)
    }
  ]
}

ペイロードがプロバイダー​にPOSTされました

code language-json
{
  "awardPoints": [
    {
      "idType":                "externalId",
      "id":                    "ADB-0000030",
      "transactionId":         "b4fa0e89-f4bb-41ce-b370-fb97f9c52f1a",
      "transactionDate":       "2026-02-08T00:12:00.000+00:00",
      "originalTransactionId": "b4fa0e89-f4bb-41ce-b370-fb97f9c52f1a",
      "transactionSource":     "AJO",
      "channelSource":         "Web",
      "parentCampaignId":      "CAMP-2026-Q1",
      "productName":           "Loyalty Program",
      "memberAwardDescription": "Issue Stars for completing a qualifying purchase",
      "pointQuantity":         50
    }
  ]
}
例3 - マイルストーン報酬

シナリオ: ストリーク チャレンジでは、N回の訪問ごとにマイルストーン報酬が発行されます。 この式には、マイルストーン数と、プロバイダーサイドのコンテキストの現在のストリークが含まれます。

形式の式:

code language-jsonata
{
  "memberId":       challenge.profileId,
  "points":         $number(rewardContext.rewardValue),
  "milestoneCount": milestone.count,
  "currentStreak":  task.schedule.currentStreak,
  "denomination":   reward.denomination,
  "source":         rewardContext.source
}

ペイロードがプロバイダー​にPOSTされました(2回目の訪問マイルストーン時):

code language-json
{
  "memberId":       "ADB-0000030",
  "points":         20,
  "milestoneCount": 2,
  "currentStreak":  2,
  "denomination":   "Stars",
  "source":         "milestone"
}

rewardContext.source"milestone"の場合、milestone オブジェクトにはcountreward.rewardValueが入力されます。 ソースが"task"または"challenge"の場合、milestonenullです。

API リファレンス

報酬プロバイダー
code language-http
POST   /loyalty/metadata/config/rewards/providers
GET    /loyalty/metadata/config/rewards/providers
GET    /loyalty/metadata/config/rewards/providers/{providerId}
PUT    /loyalty/metadata/config/rewards/providers/{providerId}
DELETE /loyalty/metadata/config/rewards/providers/{providerId}

すべてのリクエストにはx-gw-ims-org-idおよびx-sandbox-name個のヘッダーが必要です。

プロバイダーの作成:

code language-http
POST /loyalty/metadata/config/rewards/providers
x-gw-ims-org-id: {ORG_ID}
x-sandbox-name: {SANDBOX}
Content-Type: application/json

{
  "name":    "My Points Provider",
  "desc":    "Issues loyalty points via REST",
  "enabled": true,
  "url":     "https://rewards.example.com/award",
  "additionalHeaders": {
    "x-api-key": "YOUR_API_KEY"
  }
}
報酬定義
code language-http
POST   /loyalty/metadata/config/rewards/definitions/{providerId}
GET    /loyalty/metadata/config/rewards/definitions/{providerId}
GET    /loyalty/metadata/config/rewards/definitions/{providerId}/{rewardId}
PUT    /loyalty/metadata/config/rewards/definitions/{providerId}/{rewardId}
DELETE /loyalty/metadata/config/rewards/definitions/{providerId}/{rewardId}

報酬の定義を作成:

code language-http
POST /loyalty/metadata/config/rewards/definitions/{providerId}
x-gw-ims-org-id: {ORG_ID}
x-sandbox-name: {SANDBOX}
Content-Type: application/json

{
  "name":         "50 Stars",
  "denomination": "Stars",
  "desc":         "Award 50 Stars on task completion",
  "enabled":      true,
  "rewardJsonata": "{ \"memberId\": challenge.profileId, \"points\": $number(rewardContext.rewardValue) }"
}

式の検証

rewardJsonata式は、公開時に構文が検証されます。 式が無効な場合、APIは解析エラーの説明を含む422 エラーを返します。

公開前に式を開発してテストするには、JSONata Exerciserを使用します。 報酬コンテキスト JSONを入力ドキュメントとして貼り付け、出力がプロバイダーが期待するものと一致することを確認します。 各トリガータイプ (taskmilestonechallenge)の代表的な報酬コンテキストを上記の例に示します。

よくある間違い

失敗
エフェクト
修正
コンバージョンなしでrewardContext.rewardValueが数値として使用されました
プロバイダーがフィールドを数値として検証する場合、タイプが一致しません
$number(rewardContext.rewardValue)で終了
challenge.kvpCustom.someKeyがnullを返します
オーサリング時にチャレンジにキーが設定されていません
この定義を使用するすべてのチャレンジでkvpCustomにキーが存在することを確認します
task.accumulators.item_list[-1]はnullです
特典が発行される前にアイテムが適用されませんでした(非購入イベント)
条件付きで監視するか、代わりにコンテキストからtimestampを使用します
ソースが"task"または"challenge"の場合、milestoneにアクセスしました
milestoneはnullです。式はnull フィールドをスローまたは生成します
milestoneにアクセスする前にrewardContext.sourceを確認するか、マイルストーン報酬に添付された定義でmilestoneのみを使用してください
式は、オブジェクトではなく配列を返します
プロバイダーが予期しないペイロード構造を受信しました
配列を返す式を外部オブジェクトで折り返します:{ "items": [...] }
recommendation-more-help
journey-optimizer-help