...
Personalized offers are constructed using the following:
Config Offer /wiki/spaces/FEP/pages/3500441682 - These are offers created in Sanity for the sole purpose of being used for personalized offer assignment. Personalized offers get most of the offer specific details from the config offer.
Offer Template - /wiki/spaces/FEP/pages/3500998755 - This is a template that is used as a “shell” to create the personalized offer record. An offer template is also created in Sanity and requires a config offer to be linked. The main purpose of the template is to streamline which rules are required when creating personalized offers in bulk. If rules are defined in the template, then those rules MUST be configured during the assignment process and will override the rules configured as part of the config offer.This is a template that is used as a “shell” to create the personalized offer record. An offer template is also created in Sanity and requires a config offer to be linked. The main purpose of the template is to streamline which rules are required when creating personalized offers in bulk. If rules are defined in the template, then those rules MUST be configured during the assignment process and will override the rules configured as part of the config offer.
...
Deepflame Bulk Assignment
Campaign Webhook Assignment via Braze
Support Offers via Support Tool
Personalized Offers UI
Generally speaking, personalized offers will look and feel the same as regular systemwide (national) offers in the app. See example below (can you tell it’s a personalized offer? )
...
Example URL: {base URL}/rewards/offers/{personalized offer ID}
Offer Dispatcher
offer Dispatcher was created in October 2023. A new lambda has been created to migrate code from Tasks back to Lambdas. offerDispatcher takes streams of data from dynamoDB. Any time a row is added to the pendingPersonalizedOffers table in DynamoDB. Once that stream is triggered, a list of record(s) is sent to the offerDispatcher lambda.
Enhancements/ Updates
With the migration, there have been some changes to the original code.
1. CSV’s are no longer accepted, any new offers should be stored in the new table pendingPersonalizedOffers. Once an offer is stored it then triggers the lambda.
Activated offers are no longer being utilized.
Braze is no longer being utilized.
Cloud watch is no longer being utilized to store metrics. Just logs
Data dog is replacing cloud watch
Once a pending offer has been stored in the personalized offers database, it is removed from the table.
Row Structure
No Challenge Example Data
Code Block |
---|
{
"userId": string,
"sortKey": string (campaignId+offerId),
"offerId": string,
"campaignId": string,
"ttl": number,
"startDate": ISO-TimeStamp
"expiryDate": ISO-TimeStamp,
"rank": number
} |
With Challenge Example Data
Code Block |
---|
{ "userId": "us-east-1:192991f1-ede8-47bf-89e1-3942d4ab8aaa", "sortKey": "e2dd4cb3-9b0f-479c-8e1b-e42234f27314+d2dd9cb3-9b0f-479c-8e1b-e40046f57170", "challengeStatus": "{\"reward\": {\"value\": \"100\"},\"goals\": {\"visit1\": {\"condition\": {\"total_cost\": \"1\"}},\"visit2\": {\"condition\": {\"total_cost\": \"1\"}}}}", "challengeType": "frequency", "expiryDate": "2025-09-20T17:37:37+0000", "frequency": "290fb746-9850-4994-b7d7-5630046792e1", "offerId": "290fb746-9850-4994-b7d7-5630046792e1", "rank": 12, "startDate": "2023-10-20T17:37:37+0000", "taskId": "e2dd4cb3-9b0f-479c-8e1b-e42234f27314" } |
Note: frequency
must match offerId
To view challenge offers: GitHub/Loyalty/engine/src/lib/models/FormationGame.ts
Legacy Code
IssuePersonalizedOffers in engine and in tasks has remained unaffected.