[Beta privata]{class="badge informative"}

Guida alla definizione del premio reward-definition-guide

Sommario

Introduzione alle sfide di fedeltà

AVAILABILITY
Questa funzionalità è attualmente in versione beta privata. Per informazioni dettagliate sul ciclo di rilascio e sulle fasi di disponibilità in Journey Optimizer, vedere ciclo di rilascio.

Quando un’attività di verifica, un’attività cardine o una sfida completa e ha un valore di ricompensa configurato, la piattaforma emette una ricompensa chiamando l’endpoint HTTP del provider di ricompensa con un payload JSON. Una definizione premio descrive il premio da emettere e fornisce un’espressione JSONata, rewardJsonata, che definisce il payload esatto previsto dal provider.

Questa guida illustra come configurare un provider di premi, creare definizioni di premi, scrivere l’espressione rewardJsonata e capire il contesto disponibile al momento della valutazione.

Modello a due livelli

I premi sono organizzati in due livelli:

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

Un Provider di premi rappresenta un singolo sistema di premi esterno. Contiene l’URL dell’endpoint di consegna, l’autenticazione ed eventuali intestazioni HTTP personalizzate. Un provider può contenere più Definizioni di ricompensa, ognuna delle quali descrive un tipo di ricompensa o una denominazione distinta offerta dal provider (ad esempio “50 Stelle”, “Stelle doppie”, “Elemento libero”).

Una richiesta di verifica fa riferimento al provider e alla definizione per GUID. Quando viene assegnato un premio, la piattaforma valuta l’espressione rewardJsonata della definizione e PUBBLICA il risultato sull’endpoint del provider.

Campi di definizione e provider di premi

Campi del provider di premi
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
Campo Tipo Obbligatorio Descrizione
guid String No (assegnato dal sistema) Identificatore univoco. Sola lettura.
name String Nome visualizzato, univoco all’interno dell’organizzazione.
desc String No Descrizione leggibile del provider.
enabled Boolean No Quando false, la consegna dei premi è
sospesa per tutte le definizioni in questo provider.
url String Endpoint HTTP che riceve il payload di ricompensa.
La piattaforma invia l'output
rewardJsonata valutato a questo URL.
additionalHeaders Object No Intestazioni HTTP personalizzate da includere in ogni
richiesta di consegna (ad esempio chiavi API,
sostituzioni di tipo contenuto).
maxRatePerSecond Integer No Limite di tariffa per provider facoltativo (1-5000).
Null significa illimitato.
enableMTLS Boolean No Se l’endpoint richiede TLS reciproco.
Campi di definizione del premio
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
Campo Tipo Obbligatorio Descrizione
guid String No (assegnato dal sistema) Identificatore univoco. Sola lettura.
name String Nome visualizzato, univoco all’interno del provider.
denomination String No Unità del premio, utilizzata in visualizzazione
e disponibile nelle espressioni come
reward.denomination
(ad esempio "Stars", "Points", "Miles").
desc String No Descrizione del premio, disponibile
nelle espressioni come reward.desc.
enabled Boolean No Quando false, questa definizione è inattiva
e non emetterà premi.
isDefault Boolean No Contrassegna questo come definizione di ricompensa predefinita
a livello di sandbox. È possibile impostare una sola definizione
per tutti i provider alla volta;
l'impostazione di un nuovo valore predefinito cancella quello precedente.
Utilizzato per popolare automaticamente i dettagli dei premi sulle
sfide personalizzate al momento della pubblicazione.
rewardJsonata String Espressione JSONata valutata
al momento del problema del premio. Riceve il contesto completo
di ricompensa e deve restituire il payload JSON
a POST al provider.

Contesto del premio

Quando rewardJsonata viene valutato, riceve un singolo oggetto principale contenente tutto ciò che è noto sull’evento di ricompensa. Tutti i percorsi nell’espressione sono relativi a questa radice.

{
  "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"
}
Campi contestuali
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
Campo Descrizione
rewardContext.rewardValue Stringa di valore del premio configurata per la sfida, l’attività o l’attività cardine che ha attivato l’emissione.
rewardContext.source Che cosa ha attivato il premio: "task", "challenge" o "milestone".
reward La stessa RewardDefinition: name, desc, denomination.
task L’attività di completamento, inclusi accumulators, schedule e reward.
task.accumulators.spend Spesa totale qualificata accumulata dall’attività.
task.accumulators.qty Numero totale di articoli qualificati accumulato dall’attività.
task.accumulators.item_list Tutti gli elementi idonei applicati all’attività. Ogni voce ha item, transactionId, timestamp, utcOffset, locationId.
task.accumulators.item_list[-1] L’elemento più recente applicato (indice JSONata negativo). Utile per determinare l’origine dell’ID o della marca temporale dell’ultima transazione.
task.schedule.currentStreak Conteggio attuale delle sequenze di visite consecutive (per le sfide di serie).
task.schedule.currentVisits Conteggio totale delle visite (per le sfide relative alle visite).
milestone La milestone che ha attivato questo premio, o null se non è un premio milestone. Include count e reward.rewardValue.
challenge.profileId ID fedeltà del membro.
challenge.kvpCustom Coppie chiave-valore personalizzate configurate per la sfida. Un modello comune per il passaggio di ID campagna, nomi di prodotto o metadati specifici del provider.
challenge.name Nome della sfida.
challenge._id ID sfida.
timestamp Timestamp ISO 8601 dell’emissione del premio.

Scrittura dell’espressione rewardJsonata

L’espressione riceve il contesto di ricompensa come input e deve restituire un oggetto JSON, il payload POSTed all’endpoint del provider. La forma di tale oggetto dipende interamente dall’API del provider. I campi contestuali vengono mappati in base alla struttura prevista dal provider.

Payload fisso semplice

Il caso più semplice: il provider richiede un conteggio dei punti e un ID membro, entrambi noti dal contesto.

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

Output:

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

rewardContext.rewardValue è sempre una stringa. Utilizza $number() per convertirlo se il provider prevede un valore numerico.

Utilizzo di kvpCustom per metadati specifici del provider

I provider spesso richiedono campi come ID campagna o codici del sistema sorgente specifici per ogni sfida eseguita. Memorizza questi elementi in challenge.kvpCustom durante l’authoring della sfida, quindi fai riferimento ad essi nell’espressione, mantenendo l’espressione riutilizzabile nelle campagne.

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

È inoltre possibile utilizzare reward.kvpCustom per le costanti fisse per un determinato tipo di premio anziché per sfida.

Utilizzo dei dati accumulatori delle attività

Gli accumulatori di task tengono traccia di ogni evento qualificato. Utilizza item_list[-1] per accedere all’elemento applicato più di recente. I relativi transactionId e timestamp sono utili per gli audit trail e la deduplicazione sul lato provider.

code language-jsonata
{
  "memberId":       challenge.profileId,
  "points":         $number(rewardContext.rewardValue),
  "transactionId":  task.accumulators.item_list[-1].transactionId,
  "transactionDate": task.accumulators.item_list[-1].timestamp
}
Creazione di un messaggio di testo

Per i provider basati su notifiche (Slack, SMS, e-mail), puoi creare una stringa di messaggio direttamente utilizzando l’operatore di concatenazione & di JSONata:

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

Output:

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

Esempi

Esempio 1 — Fornitore di punti semplice

Scenario: un’API di base per i punti fedeltà prevede un ID membro e una quantità di punti.

Definizione premio:

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}"
}

Espressione formattata:

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

Payload inviato al provider:

code language-json
{
  "memberId":      "ADB-0000030",
  "pointQuantity": 50,
  "denomination":  "Points"
}
Esempio 2 — Payload del provider con metadati della campagna

Scenario: Il provider richiede un record di riconoscimento strutturato che includa campi di controllo, riferimenti alla campagna e descrizione del membro. I valori specifici della campagna sono archiviati in challenge.kvpCustom, pertanto la stessa definizione del premio funziona nelle campagne senza modificare l’espressione.

SfidakvpCustom (impostata durante l’authoring della sfida):

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

Definizione premio:

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)}]}"
}

Espressione formattata:

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)
    }
  ]
}

Payload inviato al provider:

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
    }
  ]
}
Esempio 3 — Premio Milestone

Scenario: una sfida di tipo streak genera un premio milestone ogni N visite. L’espressione include il conteggio delle milestone e la sequenza corrente per il contesto lato provider.

Espressione formattata:

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

Payload POST inviato al provider (alla seconda visita):

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

Quando rewardContext.source è "milestone", l’oggetto milestone viene popolato con count e reward.rewardValue. Quando l’origine è "task" o "challenge", milestone è null.

Documentazione delle API

Provider di premi
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}

Tutte le richieste richiedono x-gw-ims-org-id e x-sandbox-name intestazioni.

Crea un provider:

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"
  }
}
Definizioni dei premi
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}

Creare una definizione di premio:

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) }"
}

Convalida espressione

rewardJsonata espressioni sono convalidate per la sintassi al momento della pubblicazione. Se l’espressione non è valida, l’API restituisce un errore 422 con una descrizione dell’errore di analisi.

Per sviluppare e testare un’espressione prima della pubblicazione, utilizzare l’JSONata Exerciser. Incolla il JSON del contesto di ricompensa come documento di input e l’espressione per verificare che l’output corrisponda a quello previsto dal provider. Negli esempi precedenti viene mostrato un contesto di ricompensa rappresentativo per ogni tipo di trigger (task, milestone, challenge).

Errori comuni

Errore
Effetto
Correggi
rewardContext.rewardValue utilizzato come numero senza conversione
Tipo non corrispondente se il provider convalida il campo come numerico
A capo con $number(rewardContext.rewardValue)
challenge.kvpCustom.someKey restituisce null
Chiave non impostata sulla sfida al momento dell’authoring
Assicurarsi che la chiave sia presente in kvpCustom per ogni sfida che utilizza questa definizione
task.accumulators.item_list[-1] è nullo
Nessun elemento applicato prima del premio emesso (evento non di acquisto)
Controlla con un condizionale o utilizza timestamp dal contesto
Accesso a milestone eseguito quando l’origine è "task" o "challenge"
milestone è null; l’espressione genera o produce campi null
Controlla rewardContext.source prima di accedere a milestone oppure utilizza solo milestone nelle definizioni allegate ai premi milestone
L’espressione restituisce un array invece di un oggetto
Il provider riceve una struttura di payload imprevista
Racchiudi espressioni che restituiscono array in un oggetto esterno: { "items": [...] }
recommendation-more-help
journey-optimizer-help