...
Table of Contents | ||
---|---|---|
|
Overview
To display valid offers and rewards on the UI, the client needs to retrieve data from two sources: the Loyalty Engine (Through the Loyalty Middleware) and Sanity (RBI’s CMS). The Loyalty Engine will provide incentives for which the user is "eligible," meaning they satisfy all necessary criteria (rules). Meanwhile, Sanity will offer information about active incentives, and reward categories, as well as all visual display content, such as names, images, descriptions, and more.
The client must hit both of the previously mentioned data sources and intersect the data to decide what to present. The sequence in which these queries are executed will depend on the client and its implementation. It is advised to first query Sanity for all "sorted offers" (active system-wide offers), “config offers” (possible personalized offers for any given user), and "reward categories" (active rewards), and then utilize those identifiers to request pertinent information from the Loyalty Engine.
Querying Sanity using GraphQL
Info |
---|
GraphQL URL (Playground Available): https://czqk28jt.apicdn.sanity.io/v1/graphql/dev_bk_us/default |
Replace
dev_bk_us
with the{{stage}}_{{brand}}_{{country}}
that you desire to query.Sanity GraphQL can be hit via a POST request. Please reference the POST URL structure for each of the sample queries below.
Please use this playground to play with the queries below and examine the schema for fields you may wish to request.
Example Offers Query
The
_id
is subject to the dataset you are using. For the most part, it will befeature-loyalty-offers-ui-singleton
, however, some markets have drifted from this conventionSample Query:
Code Block |
---|
query getSanityOffers {
LoyaltyOffersUI(id: "feature-loyalty-offers-ui-singleton") {
# Available for all users.
sortedSystemwideOffers {
_id
loyaltyEngineId
name {
enRaw
}
}
# These are "templates", personalized offers get created based on this template.
# You should use these only to display content (images, names, etc), and display only the actual offer from the engine.
liveConfigOffers {
_id
loyaltyEngineId
name {
enRaw
}
}
}
} |
Example Rewards Query
The
_id
is subject to the dataset you are using. For the most part it will bereward-list-singleton
, however, some markets have drifted from this conventionSample Query:
...
Glossary of terms
The following terms are used throughout this document:
Offer: Offers are discounted products - this may come in the form of individual item discounts, bundle discounts, dollars-off discounts, or percent-off discounts.
System-Wide Offer: System-wide offers are the ‘base’ offers in the loyalty offers system. These are available to all users who meet the required criteria for redemption and do not require any steps or processes to be assigned to a specific user. You’ll see these referenced as GLOBAL offers.
Configuration Offer: Config. offers are one-half of the required components to create a personalized offer. These are templates that only exist to provide the configuration for personalized offers. As such, they will not appear on their own on the offers page if they are not referenced by a personalized offer and the entity by itself does not represent a redeemable incentive.
Personalized Offer: Personalized offers are offers assigned specifically to a particular user. Every time a personalized offer is assigned to a user, it creates a unique offer record that can only be used for that particular user.
Rewards: Rewards are a special type of product that usually has a price of zero, and can be exchanged for points accumulated from previous purchases.
Loyalty Middleware: Public facing API for Loyalty. Consists of both a REST API and a GraphQL endpoint.
Loyalty Engine: The core Loyalty component that handles everything behind the scenes.
Loyalty Platform: Refers to both Middleware and Engine as a whole.
Sanity: RBI’s Content Management System (CMS).
Overview
To display valid offers and rewards on the kiosk UI, the client needs to retrieve data from two sources: the Loyalty Engine (Through the Loyalty Middleware) and Sanity (RBI’s CMS). The Loyalty Engine will provide incentives for which the user is "eligible," meaning they satisfy all necessary criteria (rules). Meanwhile, Sanity will offer information about active incentives, and reward categories, as well as all visual display content, such as names, images, descriptions, and more.
The client must hit both of the previously mentioned data sources and intersect the data to decide what to present. The sequence in which these queries are executed will depend on the client and its implementation. It is advised to first query Sanity for all "sorted offers" (active system-wide offers), “config offers” (possible personalized offers for any given user), and "reward categories" (active rewards), and then utilize those identifiers to request pertinent information from the Loyalty Engine.
Querying Sanity
There are two ways of querying Sanity:
Using GraphQL
Using GROQ
We strongly suggest using GraphQL, as this is a more widely known querying language. Additionally, using the provided GraphQL playground, vendors will be able to see the whole schema during development and make necessary adjustments to their queries with ease.
Info |
---|
Recommended reading:
|
Option 1) Using Sanity GraphQL
Info |
---|
GraphQL URL (Playground Available): https://czqk28jt.api.sanity.io/v1/graphql/staging_bk_de/default |
Replace
staging_bk_de
with the{{stage}}_{{brand}}_{{country}}
that you desire to query.Sanity GraphQL can be hit via a POST request. Please reference the POST URL structure for each of the sample queries below.
Please use this playground to play with the queries below and examine the schema for fields you may wish to request.
Example offers query
The Sanity ID for the live offers document, for the most part, will be
feature-loyalty-offers-ui-singleton
, however, some markets have drifted from this convention.Sample query:
Code Block | ||
---|---|---|
| ||
query getSanityOffers {
LoyaltyOffersUI(id: "feature-loyalty-offers-ui-singleton") {
# Available for all users.
# You can use these to lookup assets from global.
sortedSystemwideOffers {
_id
loyaltyEngineId
name {
enRaw
}
}
# These are config. offers (templates).
# You should use these only to display content (images, names, etc).
# You can use these to lookup assets from the actual Personalized offers.
liveConfigOffers {
_id
loyaltyEngineId
name {
enRaw
}
}
}
} |
Example reward query
The
_id
is subject to the dataset you are using. For the most part it will bereward-list-singleton
, however, some markets have drifted from this conventionSample query:
Code Block |
---|
query getSanityRewards { RewardList(id: "reward-list-singleton") { rewardCategories { _id label { en } rewards { ... on Reward { # Sanity ID of the reward _id # Loyalty Engine ID to be used in the Loyalty Engine query if needed loyaltyEngineId # Reward content to display to the user (name, image, description...) name { en } image { en { asset { url # Loyalty Engine ID to be used in the Loyalty Engine query if needed } loyaltyEngineId } # Reward content to} display to the user (name, image, description...) description { name { enRaw en } } # Here we add the rules we imagewant {to check for the rewards en { # e.g., LoyaltyPoints (reward points cost), RewardPrice (reward money price), asset { # SubtotalSpend (minimum subototal to spend for redeeming the reward) url ruleSet { } ... on LoyaltyPoints { } } points description { } enRaw ... on RewardPrice { } price # Here we add the rules we want to check for the} rewards # e..g., LoyaltyPoints (reward points cost), RewardPrice (reward money price),on SubtotalSpend { # SubtotalSpendminimumSpend (minimum subototal to spend for redeeming the reward) } ruleSet { # Add more ruleSets as needed here (e... on LoyaltyPoints {g. FirstOrderOnly, LoyaltyBetweenDates, etc) # See the screenshot below for how pointsget the list of available ruleSet from GraphQL Playground } } ... on RewardPrice { # Benefit of the reward, it can be either a Combo, Item, OfferDiscount price # or Picker } # e.g., OfferDiscount (It ...can onbe SubtotalSpenda {discount for the whole cart or minimumSpend # a discount for a specific product) } incentives { # Add more ruleSets as needed here (e..g. on FirstOrderOnly,OfferDiscount LoyaltyBetweenDates,{ etc) # SeediscountType the screenshot below for how get the list of available ruleSet from GraphQL Playground discountValue } discountProduct { # Benefit of the reward, it can be either a Combo, Item, OfferDiscount... on Item { # or Picker name { # e.g., OfferDiscount (It can be a discount for the whole cart or en # a discount for a specific product) } incentives { ... on} OfferDiscount { discountType... on Combo { discountValue name { discountProduct { en ... on Item { } name { } en } } } } } # Reward redemption method available ...redemptionMethod on Combo { # Here we can get the needed PLUs by looking for namea {specific vendor # e.g., Partner constant PLU en vendorConfigs { } partner { }_type }constantPlu } pluType } } # Reward redemption method available} } redemptionMethod } } # Here we} can get the needed PLUs by looking for a specific vendor # e.g., Partner constant PLU vendorConfigs { partner { _type constantPlu pluType } } } } } } } |
Expand | ||
---|---|---|
| ||
To get list of ruleSet available, navigate to https://czqk28jt.apicdn.sanity.io/v1/graphql/dev_bk_aq/default, and search for “ruleSet” in the Schema explorer as seen here: |
...
}
|
Expand | ||
---|---|---|
| ||
To get list of ruleSet available, navigate to https://czqk28jt.apicdn.sanity.io/v1/graphql/dev_bk_aq/default, and search for “ruleSet” in the Schema explorer as seen here: |
Option 2) Using a GROQ Query
Replace
staging_bk_de
with the{{stage}}_{{brand}}_{{country}}
that you desire to query.Replace
{{GROQ_QUERY}}
with the desired GROQ query.
Code Block |
---|
https://czqk28jt.api.sanity.io/v2021-10-21/data/query/staging_bk_de?query={{GROQ_QUERY}} |
Example offers query
Code Block |
---|
https://czqk28jt.api.sanity.io/v2021-10-21/data/query/staging_bk_de?query=*%5B_type+in+%5B%27systemwideOffer%27%2C%27configOffer%27%5D%26%26_id+in*%5B_id%3D%3D%27feature-loyalty-offers-ui-singleton%27%5D%7B%22refs%22%3A%40.liveConfigOffers%5B%5D._ref%2B%40.sortedSystemwideOffers%5B%5D._ref%7D.refs%5B%5D+%5D%7B_id%2C_type%2Cname%2Cincentives%2Cdescription%2ClocalizedImage%2CofferPrice%2CrestaurantAvailabilityValidation%7BvalidationStatus%2ClastValidated%7D%2Crules%2Cdaypart%2CshortCode%2CredemptionMethod%2CloyaltyEngineId%7D |
Example reward query
Code Block |
---|
// Pending... |
Querying the Loyalty Platform
Info |
---|
GraphQL URL (Playground Available): https://euc1-dev-bk-loyalty-middleware.rbictg.com/graphql-loyalty-middleware.rbictg.com/graphql |
Replace
euc1
with the AWS Short Region that your market belongs to. Please communicate with RBI reps to know which region your market is hosted.Replace
dev-bk
with the{{stage}}-{{brand}}
that you desire to query. You will need to prefix the URL with the AWS region that your market lives in. Please communicate with RBI reps to know which region your market is hosted.An example URL for ES (Spain) would be https://euw3-dev-bk-loyalty-middleware.rbictg.com/graphql
Make When querying the loyalty platform, please make sure to set the
x-ui-region
header to the country code you want to query, in uppercase, for example:
...
Please use this playground to play with the queries below and examine the schema for fields you may wish to request.
Some
where
filters that may be relevant to Kioskkiosks:ids
- a collection of Engine IDs for offers/rewards. This is theloyaltyEngineId
field on every sanity offer/reward document.omitInvalids
- This controls whether invalid incentives will be returned. Only incentives that failed “fixable” rules will be returned if this is set tofalse
. A fixable rule is one that the user can change behavior to make the rule pass, like theminSpend
, the user can add more items to their cart to meet the requirement. An absolute failure likedate-band
will not be returned regardless of what the value of this filter isThis is useful for displaying error / in-line messages in the UI
serviceMode
- some incentives can only be redeemed if the service mode meets the required rulesetstoreId
- some incentives can only be redeemed at certain storessubtotalAmount
= some incentives require a minimum spendcartEntries
- some incentives require certain items to be in the cart, this rule uses the sanity id of each rbi productpaymentMethod
- some incentives require certain payment methods to be used
Example
...
offers query
Info |
---|
You should use the
|
Code Block |
---|
query getLoyaltyOffers { loyaltyOffersV2(loyaltyId: "<USER_LOYALTY_ID>", where: { omitInvalids: false }) { id name type sanityId errors { code ruleId } } } |
Example
...
offers query response
Code Block |
---|
{ "data": { "loyaltyOffersV2": [ { "id": "a4c24211-2d36-47be-bad8-8deea437dbfa", "name": "$6 Let's Get This Bacon Meal", "type": "GLOBAL", "sanityId": "AAA-AAA-AAA", "errors": null }, { "id": "fbba4e93-eecd-42b6-a4ed-333856d47bda", "name": "Delivery Offer - $8 The Spicy One Meal", "type": "GLOBAL", "sanityId": "BBB-BBB-BBB", "errors": null }, { "id": "2a7b2f20-1662-4854-9f4b-e9974200f294", "name": "Support 50% Discount Offer", "type": "PERSONALIZED", "sanityId": "CCC-CCC-CCC", "errors": null }, { "id": "6646b80b-dea9-4bf4-81f5-390554926987", "name": "Loyalty Upsize Swap", "errors": [ { "code": "unsatisfied-cart-requirements", "ruleId": "cart-requirement" } ] } ] } } |
Example
...
rewards query
Code Block |
---|
query getLoyaltyRewards { loyaltyRewards(loyaltyId: "<USER_LOYALTY_ID>", where: { omitInvalids: false }) { id name errors { code ruleId } } } |
Example
...
rewards query response
Code Block |
---|
{ "data": { "loyaltyRewardsV2": [ { "id": "3b5bdddc-c7c9-42d8-9332-b0c3f36c8e1c", "name": "Value Powerade Zero", "errors": null }, { "id": "728aaedd-3234-4eae-89af-35cd5672adcb", "name": "Large Dr. Pepper", "errors": null }, { "id": "480122d7-86ff-4db0-965c-7dbb72bb5179", "name": "Value Soft Drinks", "errors": null } ] } } |
...