/
[Solution] Complete your menu (WIP)

[Solution] Complete your menu (WIP)

Document Status

IN REVIEW

Document Owner(s)

@Augusto Romao, Vinicius

Reviewers

Internal reviewers

@Caes, Guilherme
@Capovilla, Evandro
@Leite, Marina
@Macedo Ferreira, Samuel
@Raphael Ferreira Gomes
@Franca, Helio 
@Ruani, Andrea

INTL reviewers

 

Context

This feature aims to enhance the up-selling capabilities within the Guest App by suggesting specific products based on the item selected by the guest (Combo, Picker, Item, etc.) after adding to the cart. The motivation is to increase the average ticket value, thus enhancing the overall customer experience and boosting sales. Besides solving Iberia problems, this solution will be available across other markets, leveraging the Guest App’s versatility.

For more details about the opportunity, read here: [Opportunity] Complete your Menu

 

Proposed solution

This solution consists extending the existing upsell feature (described here: https://rbictg.atlassian.net/browse/TRX-1894) to be more versatile and efficient. The UX will be improved providing a more clear and easy to use experience in the process to add more items after selecting the main meal.

image-20250207-213442.png

The user will have the possibility to edit (add/reduce/resume) the selected items in the checkout page and cart preview

image-20250207-213616.png

Figma file

Customer experience on Guest App: https://www.figma.com/design/lGSm8QVc9nUieJtNt2Or2S/branch/Qhb14qiY6BlKrx5DNXsMD2/5.-Menu-%26-Products?m=auto&node-id=44397-33382&t=ktqSMubDlOZAqdXf-1

Operators experience on Sanity: https://www.figma.com/design/oLr5rewpNjJ5VWgoCh27i1/branch/JduXZhFLRk1eCvkH1lTwx6/RBI-Sanity-Studio?m=auto&node-id=8444-71163&t=G8MlIlDzh6ffxuOS-1

 

Configuration - Sanity changes

Adding a new feature in Sanity (intl-whitelabel-cms) where it will be possible to configure these upsell items.

1. Toggle inside products to define them as “Deal”

  • For all types of Item (like Combo and Item) there will be a new toggle to mark the product as a deal item

  • This will be useful to differentiate between regular items and deal items

  • This solution will be connected with the configuration for the new document explained in the next steps below ([Solution] Complete your menu (WIP) | 3. New Upsell Group)

Expected tasks

  1. Add new toggle inside the following item documents

    1. Combo schemas/menu/documents/combo.tsx

    2. Item schemas/menu/documents/item.tsx

PS: Picker will not be supported for now.

Example for the toggle:

{ name: 'itemAsDeal', title: 'This is a promotional item?', type: 'boolean', default: false, }

2. New Feature Upsell Sanity document

In this page, the user will be able to:

  • Add the desired Upsell Group (how many he wants, no limit)

  • Configure the display frequency for the new upsell modal. Possible values:

    • Only After first trigger product is added to cart

    • Every time a trigger product is added to cart

Expected tasks

  1. Create a new document for Feature Upsell and necessary fields and information

Important: for this task, we’ll not add yet the field for “Upsell Groups”. This will be done in the next section below ([Solution] Complete your menu (WIP) | 3. New Upsell Group modal).

3. New Upsell Group modal

  • Here the user can create a specific and unique group of upselling items. It can be given a title

  • First, the operator needs to select the products that will trigger the new upsell modal. Offers and rewards are excluded

  • Then, it’s possible to select the type of service mode. Possible values

    • Only Pick Up

    • Only Delivery

    • Different for Delivery and Pick Up

      • For this specific option, when selected, will show separated list items based on the service mode

      • Will be possible to select the amount limit for each list

     

    • Same for Delivery and Pick Up

Last, the operator will choose the suggested items to be added in the upselling modal. Here there will be the possibility to look at “Deal products” or “Standard products” by changing the “Deal Upsell List” toggle

Listing deal items OFF

Listing deal items ON

Listing deal items OFF

Listing deal items ON

  • In case of “Deal products” there are also the possibility to limit the amount of each single item

  • Changing between the active list will not remove the items even if the user publishes the document with one of them. For future editions, if the user wants to roll back to the “Standard products” list, for example, the items will be there when the user press the “Deal Upsell List” to be OFF again

Form validation

  • The user will not be able to use an item in the Triggers list at the same time in more than one Upsell Group. We need to add validation on this and warn the user that the item is being used in another group, if possible, showing the group name to help.

  1. Create custom component for “Upsell Groups”

    1. We’ll need to create a new custom component as explained here [Solution] Complete your menu (WIP) | 4. Upsell Group reference available in items. If INTL approve this approach than we’re good to go

    2. Create the object for upsell groups in schemas/menu/objects/upsell-groups.ts. This will be used in the Feature Upsell document field for “User Groups” in the property of: [{ type: 'upsellGroups' }],

This component will be in the /components folder and should be tied (perhaps a new sub-folder) to the component above as they work together.

const paramModalItemRef = 'modalItemKeyToOpen'; // New component in /components folder const ModalItemLoader = (props: any) => { const [groupOpenFromOtherDocumentRef, setGroupOpenFromOtherDocumentRef] = useState(''); const clearUrlParamsOnClose = () => { const url = new URL(window.location.href); url.searchParams.delete(paramModalItemRef); window.history.replaceState({}, document.title, url.toString()); setGroupOpenFromOtherDocumentRef(''); }; // Search for the new param to get the item key reference useEffect(() => { const params = new URLSearchParams(window.location.search); const itemGroupKey = params.get(paramModalItemRef); if (itemGroupKey) { setGroupOpenFromOtherDocumentRef(itemGroupKey); } // Ensure that we'll clear the params from URL if the user closes the Modal our decide // to go out of the document where this component is (in this case, Feature Upsell doc) return () => clearUrlParamsOnClose(); }, []); // We'll use the open property to tell the sanity object item it should be opened when // rendered if it matches. return ( <ArrayOfObjectsInput {...props} renderItem={(itemProps: any) => { return props.renderItem({ ...itemProps, open: groupOpenFromOtherDocumentRef === itemProps.key || itemProps.open, onClose: () => { itemProps.onClose(); clearUrlParamsOnClose(); }, }); }} /> ); };

Now that we have the two new logics we can create the new Feature Upsell document the new ModalItemLoader that will be connected to our other logic.

New Feature Upsell document

  • Instead using a regular native field, this document will be using the new custom

export default defineType({ title: 'Feature Upsell', name: 'featureUpsell', type: 'document', __experimental_actions: ['update', 'publish', 'create'], __experimental_omnisearch_visibility: false, fields: [ { title: 'Upsell Groups', name: 'upsellGroups', description: 'Items that should show up as a upsell on the checkout page when service mode is Delivery. this list of suggested items may be overwritten by Upselling configurations in Sections or Menu Combos.', type: 'array', of: [{ type: 'upsellGroups' }], validation: (Rule: Rule) => [validateNoSkeletonObjects(Rule), Rule.required().min(1)], components: { input: ModalItemLoader, // The new component to load modal items }, }, ... // other necessary fields ], preview: { prepare: () => ({ title: 'Feature Upsell PoC', }), }, });
  1. Implement form validation to detect if a trigger item is already in use in another Upsell Group

PoC diff: https://github.com/rbilabs/intl-whitelabel-cms/compare/main...poc/IBFEC-3408

4. Upsell Group reference available in items

The user can check if an item (Combo and Item) was configured in an existing Upsell Group by checking this new reference section "Upsell Group".

  • This new section will be available for all item documents

  • Clicking in the referenced group will send the user to the Feature Upsell document with the group modal already opened for edition

Technical decision details

From what we know, Sanity doesn’t have a native way to show references already selected in existing item fields documents (that open a modal). To solve that we’ll need to create some custom components.

  • Fetch list of document ID references (generic component)

    • Fetch another specific document looking for a reference from the document ID where this component was called and render the list of references found

    • To clarify: this component will be used inside the item documents (like Combo and Item).  For example, if I open a Combo document, I want to know if this Combo that I’ve opened is already configured in the Feature Upsell groups.

  • Custom objects list that can be opened by URL params (generic component)

    • Render a default array of objects list from Sanity but with a wrapper logic that will look if the expected param exists in the URL. If the params were found, then we’ll be able to open the item modal where the reference is

    • To clarify: this component will be used inside the new Feature Upsell document

The details below will show a proposed solution for the image above where we want to have references in documents that are already published. The following codes come from a PoC and are intended to be generic and reusable.

PoC diff: https://github.com/rbilabs/intl-whitelabel-cms/compare/main...poc/IBFEC-3408

 

Note: Some of the steps below were broken into small tasks to be done in the previous sections, but I’ll let the whole big picture here to help with the understanding.

 

  1. New input component to fetch if open document id was referenced in another document (expected task for this section)

This component will be in /components folder.

  1. New input component that has the ability to open the modal item pragmatically (expected task in previous sections)

 This component will be in the /components folder and should be tied (perhaps a new sub-folder) to the component above as they work together.


Now that we have the two new logics we can create the new Feature Upsell document the new ModalItemLoader that will be connected to our other logic.

New Feature Upsell document (expected task in previous sections)

  • Instead using a regular native field, this document will be using the new custom

 

2.a Now that Feature Upsell is prepared and configured, we should add the GroupsReferenceInOtherDoc new component inside the document that we want to search for references in other document (expected task for this section)

For this example we’ll add this component inside Combo document (/intl-whitelabel-cms/schemas/menu/documents/combo.tsx)

  • We’ll add this same field in other necessary items like (Item and Combo, etc.)

Pros and Cons

  • Enhance the user experience and configuration

    • Showing if the document item is already configured inside some Feature Upsell group

    • With this, the user will save time because it will not be necessary to go to the Feature Upsell document and open all the groups trying to look if the desired item is configured there

  •   The solution is generic, and the components will be available to be reused in other documents

  • As this is a custom logic, if Sanity updates the interfaces, adding breaking changes, this solution could be broken. As we are using well-known properties, we think that this is not as fragile as it appears

  • To search for references in other documents, we need to make a new query using the internal Sanity client when the user opens the document. During the tests we didn't see any negative impact on this, but it's worth mentioning

 

Frontend - Whitelabel App changes

1. Extend the current Upsell solution

As mentioned earlier, we already have in the app the Upsell modal (that was developed here: https://rbictg.atlassian.net/browse/TRX-1894).

The current solution works in the following way:

  • The Upsell Modal will always be shown for the first journey (e.g., when the cart is empty and the user adds an item, no matter the type)

  • If the user clears the cart and adds again a new item, this will be considered a new journey, and the Upsell Modal will be triggered again

Now that we have all the necessary context, it’s clear that we’ll need to extend this solution, based on the described User Scenarios.

Changes in legacy upsell modal experience

  • The modal will have new upsell limit information (if configured in Sanity for the deal products list). This will not affect markets that are using the old feature menu upsell configuration

Expected tasks

  1. Adjust upsell modal to show items limit information

    1. Rule: as said above, the collapse will only show this if

      1. If we have some data configured in the new Feature Upsell document. If not, the legacy logic should work as before

      2. User configured deal products list inside the “Upsell Groups”

      3. User configured the items limit quantity on Sanity

2. Render promotional items inside cart item (checkout and cart preview)

The current behavior is to show all the promotional item as a regular cart item. The new solution proposes to show all promotional upsell groups (marked as a deal in Sanity) inside the main item (who was responsible for triggering the Upsell Modal, showing the offers):

Cart item before (upsell item)

Cart item with upsell items marked as a deal

Cart item before (upsell item)

Cart item with upsell items marked as a deal

Besides the new information on the checkout page, we’ll show the upsell item in the cart preview as well:

Cart preview before

Cart preview with upsell items

Cart preview before

Cart preview with upsell items

Management of items

  • As items will be added to the cartEntries will be easy to manage the items as they are independent

  • We can reuse the necessary methods from the order context to manage the items freely

 

Technical decision details

From the analyzed proposals, our suggestion is to go for the 1. Add upsell item as regular items (cartEntries root).

 

1. Add upsell item as regular items (cartEntries root)

Frontend changes

For this solution to work as expected we intend to reuse the isUpsell property combined with the triggerUpsellItemId new property (ICartEntry interface).

Besides the interface change, here the following expected work

  • Create a new component responsible to render the “upsell information card” inside the main item in checkout page and cart preview

  • Create a container component responsible to hold the necessary logic for this (call Sanity query, cart entries manipulation, etc). We can create a new hook as well or some utils to help

 

More technical details below.

 

Backend changes

If we decide to go with this option, we’ll need to at least adjust the backend to receive the existing isUpsell and the new triggerUpsellItemId property to be saved in DynamoDB. Why?

  • Without these properties, it will be impossible to make the relationship between the upsell item and the main item responsible for triggering the promotion on the confirmation page, receipts page and the email template page. This will enable the layout customization

Expected changes
  • Adjust the price order service adding the isUpsell and triggerUpsellItemId prop in the ICartEntryInput interface (used in the priceOrder function in WL App). Without this, the query will be broken if we decide to just send the new properties

  • Check and ensure that Gateway and Graphql will also be transiting/returning the property in the following queries

    • GetOrder and GetUserOrders: used in Recent Orders receipt + Confirmation Page

  • Adjust Whitelabel App frontendToBackendCartEntryMap method to allow isUpsell and triggerUpsellItemId to be sent to the backend

 

Pros and Cons

No impacts for partners as the upsell item will be on the cart entry root as expected

No impacts for the priceOrder calculation as the item will be in the root as expected

Little backend impact as we just need two new properties to be saved in DynamoDB (one of them already exists, just needs to be saved)

As the solution relies on keeping compatibility with cart entries, we need to add some conditions to hide the default cart item from the page during the renderization and some manual logics to ensure the removal of these hidden items

 

Disregarded solutions

1. Add upsell items as children items

When we tested this path of solution, this helped a lot in resolving many aspects in the application (items already tied to the main item), simplifying a lot the solution. Less manipulation in the code

The feature will demand that the upsell item not be affected by the trigger main item quantity. As children by default will always be affected by that, drop this solution idea right away.

Another problem about children is that we don’t know exactly what kind of manipulation all partners will be doing to calculate this price. This is a risk that drops this idea as well

2. Reuse Offers flow

Normally, offer flow needs more than one document to configure the whole experience Order-level Content -> Incentives -> to create offers and Order-Level Content -> Live Offers Configuration -> Live Offers -> configure the desired lists to turn ON the offer . In our new solution proposes a dedicated document to configure everything

We are reusing the Feature Menu upsell modal experience, and this feature was not originally developed to be considered as an offer. The whole flow is dealing with upsells inside the code. Technically speaking, Offers has its own states and management and this means plugging in the solution to be considered now an offer adding more complexity as we need some personalized visuals at the checkout page and Offers will not deliver that (e.g. more condition inside the code)

We don’t need to rely on offers flow to show an item with discount information (strike-through). We can improve our feature to suporte this in the future

Offers have the concept of redeem. For our use case, when the user sees the upsell modal, he’s dealing with menu items, having the flexibility to add or reduce the upsell quantity. We don’t want to redeem the upsells; this means that we’ll need to add more complex logic into the code to have this new behavior without breaking the legacy code

 

3. Update confirmation page and receipt page to show new upsell children information

Receipt with highlight nested upsell

Confirmation screen with highlight nested upsell (delivery)

Receipt with highlight nested upsell

Confirmation screen with highlight nested upsell (delivery)

As explained here with the isUpsell and triggerUpsellItemId saved in the DB and properly returned in the query, we’ll be able to customize these screens in the following way:

  • Show the upsell item nested below the main item (responsible for triggering the promotion)

 

Note: For pickup-related service modes, during the tests, the confirmation page was not showing any item information. Recent orders were not showing the order as well for some service modes like Dine In and Take Out. For Drive-Thru, recent orders appear to work normally. This is not related to this feature.

 

4. Update email template to show new upsell children information

In the same way that we need to highlight the upsell information in receipt and confirmation screen we’ll update the email template showing this new information:

Waiting UX team proposal

 

 

Support - Admin app changes

1. Customer orders information with highlight upsell items

To improve admin app support, we'll add the new upsell nested item information in the order summary.

 

Acceptance Criteria

1. Adding Extra Items During Meal Selection

1.1 Basic “Complete your menu” modal

  • Given the user has joined the menu section

  • When the user select one product from the menu and add it into the cart

  • Then the "Complete Your Menu" interface prompts the user with additional options (e.g., fries, toppings, sides, drinks) and the user can select extra items

1.2 Promotional items modal

  • Given the user is visualizing the “Complete your menu” modal

  • When the user choose between the different options available

  • Then the "Complete Your Menu" interface shows promotional items (discounted items) to push him to buy more products or complementary items (no discounted). No possibility to mix discounted with no discounted.

1.3 Maximum Item Limit

  • Given the user is in the "Complete Your Menu" interface,

  • When the user adds items up to the allowed maximum,

  • Then the system disables the "+" button to prevent exceeding the limit.

 


2. Editing Items in Checkout Page and other pages of the purchase flow

2.1 Editing No Promotional Items

  • Given the user is in the checkout page with unlinked items in the cart,

  • When the user reduces or removes unlinked items (standard behaviour),

  • Then the system updates the cart and allows the user to add new items, respecting the maximum limit if activated.

2.2 Editing Promotional Items

  • Given the user is in the checkout page with promotional items in the cart,

  • When the user attempts to add or edit those items,

  • Then the system redirects the user to the "Complete Your Menu" interface to make changes.

2.3 Handling Exceeded Linked Item Limits

  • Given the user has removed a meal but still has linked items in the cart,

  • When the total linked items exceed the allowed number,

  • Then the system displays an error message and prevents the user from proceeding until the number of items is below the maximum allowed.

2.4 Update purchasing flow with related informations

  • Given the user has selected the upselling items

  • When the user move ahead in the purchase flow,

  • Then the system displays the upselling items accordingly (pre-cart component, confirmation page, confirmation email, etc.)


3. Sanity CMS Integration for Upsell Configuration

3.1 Adding New Upsell Groups

  • Given the operator accesses the "Feature Upsell" section in the CMS,

  • When the operator creates a new upsell group,

  • Then they can:

    • Add multiple groups with no limit.

    • Define triggering products (excluding offers and rewards).

    • Specify suggested items for the upsell modal.

3.2 Configuring Display Frequency

  • Given the operator is configuring the upsell modal,

  • When they specify the display frequency,

  • Then the system uses the defined frequency for showing upsell prompts during the user journey.

3.3 Upselling group configuration

  • Given the operator is in the “Group upsell” interface,

  • When the operator has selected the main product

  • Then the operator can choose the upselling items

3.4 Service mode selection

  • Given the operator is in the “Group upsell” interface,

  • When the operator is the section “Service modes”

  • Then the operator can choose the type of service mode to link the upsell group

3.5 Maximum Item Limit

  • Given the operator is in the “Group upsell” interface,

  • When the operator create the allowed maximum number of items to be seletected,

  • Then the user cannot exceed the limit.

3.6 Linking Items to Meals

  • Given the operator is in the “Group upsell” interface,

  • When the operator activate the possibility to link items to the main meal,

  • Then those items will be treated as dependent on the meal for actions like adding, editing, or removing in the cart.


4. Feature Applicability Across Brands

  • Given the platform supports multiple brands,

  • When the "Complete Your Menu" feature is deployed,

  • Then it should work consistently and seamlessly for all supported RBI brands


5. Feature Applicability Across Markets

  • Given the platform operates in multiple markets,

  • When the "Complete Your Menu" feature is deployed,

  • Then it should function correctly and adhere to the specific configurations for all markets without additional modifications.

 

User Scenarios

SCENARIO

 

USER STEPS

MARKET CONFIGURATION

COMMENTS

SCENARIO

 

USER STEPS

MARKET CONFIGURATION

COMMENTS

Adding Extra Items During Meal Selection

The meal and chosen extra items are added to the cart successfully.

  1. User selects a meal from the menu

 

 

 

 

  1. The interface Complete Your Menu prompts the user to add extra items (e.g., fries, toppings, sides, drinks)

 

Upselling configuration

 

 

This scenario is valid for every category as the Upselling configuration is indipendent (exclude Offers and Rewards).

 

 

  1. User selects items up to the maximum allowed

 

a) Limiting number of upselling items (blocking “+”)

 

b) Possibility to link the upsell item to the main item

 

There is no possibility to exceed the number as the design will block the button “+”.

 

Adding / reducing / removing an item in the checkout page

The system adheres to the logic defined and users are informed of the potential limitation.

  1. User proceeds to checkout and decides to edit one or more items to the existing selection

 

 

User is able to add upsells until he reaches the limit.

If the limit is reached the user will be able to edit the upsells or increase the meal quantity

 

 

 

2a. In case the items are not linked with the meal, it’s possible to reduce / remove them and add until the allowed number in the same checkout page like a standard meal

 a) If the “Deal Upsell List” is OFF the upsell will not be linked to the main item

 

 

 

2b. In case the items are linked, there will be the possibility to reduce/remove and the adding option until the allowed number in the “Complete your menu” page/modal because the user can access to specific products (promotional products mainly) only if linked

 

If the users remove one or more meal and the number of linked items exceed the allowed, an error message should be displayed and the user should not be allowed to move forward.

 

The application will alert the user when he’s doing actions like reduce meal quantity or remove the entire meal item (that has upsell attached)

 

 

 

2c. If the user removes all upsell items or enters the checkout page without any upsell, the app will alert the user that he has the option to add upsells to the order

 

 

This new way to show the Upsell products will impact other parts of the purchase flow such as:

  • CART PREVIEW

  • CONFIRMATION PAGE

  • RECEIPT

  • CONFIRMATION GUEST EMAIL

 

Potential Challenges

  • How to design a simple solution without adding a lot of complexity to the legacy code and at the same time provide a good configuration experience for the operator?

This was the biggest challenge that we faced during the construction of the current proposal.

Metrics

Metrics will remain the ones existing in this dashboard: https://app.eu.amplitude.com/analytics/share/406896002004409787294008dba7f2ef TBV

 

Delivery Plan

  1. Sanity configuration and backend development

  2. Whitelabel App user experience

  3. Admin App new upsell items information

Note: we’ll add more details here when we got the approval for the solution/idea.

QA Plan

Testing scenarios. See example here.

 

Call-outs

  1. As the main idea is to add the upsell items in the cartEntries structure, we won’t have any external dependencies and no partner dependencies. The item in the cartEntries root is what everyone is already using nowadays, meaning full compatibility

  2. For this first deliverable, we don’t want to show the upsell item with a cut price (strike-through) showing the original price and the discount, respecting the original upsell that we are extending. This can be an improvement for the next deliverables

Related content

[Opportunity] Complete your Menu
[Opportunity] Complete your Menu
More like this
--- to be deleted --
--- to be deleted --
Read with this
Analysis - Completa tu menu using new Upsell solution
Analysis - Completa tu menu using new Upsell solution
More like this
[Solution] Ability to audit per store available and unavailable products (DOP)
[Solution] Ability to audit per store available and unavailable products (DOP)
Read with this
Upselling - Complete your menu
Upselling - Complete your menu
More like this
[Solution] Admin tool - Add Customer Tier Information
[Solution] Admin tool - Add Customer Tier Information
Read with this