Skip to content

Cross Device Baskets (aka. CDB & XDB)

Summary

Cross Device Baskets is a feature that allows customers to share their basket-items across multiple browsers & devices when they are logged into their Miva customer account.

Note

Logic only deals with active basket sessions, and does not work after baskets expire.

In short, it accomplishes this by sharing & merging the customer's g.Session_ID field through some custom template code that manages the customer's cookies & basket details.

Setup / Installation

Note

The following modifications have been made on Genesis. However, for other existing stores, you can use the following steps to install it

  • Upload the Toolbelt module on the domain, install the module on the Store, and ensure the ry_toolbelt item is assigned to all of the customer-facing pages.
  • Create a ReadyTheme Content Section cross_device_baskets to contain all of the application logic & modal views necessary to run the feature.
  • Add the <mvt:item name="readytheme" param="contentsection( 'cross_device_baskets' )" /> to the top of the Global Header template code.
  • Assign the customfields item to all pages.
  • Changes the logout actions (ex. <input type="hidden" name="Action" value="LOGO" />) to CDB_LOGO.
  • Code has been added pages/Global.js to handle displaying the modal to the customer.

Warn

If custom basket charges are used on the store, you may need to verify & make changes to that code to ensure charges are recalculated & not duplicated.

Test Cases

Sessions & Devices

  • While you are logged into the same Miva customer account account, basket items should be shared across different browsers (ex. Chrome & Firefox)
    • i.e. Test one session with basket contents that is logged in, then log in from another browser/device with an empty basket. This should simply resume the previous basket.
  • While you are logged into the same Miva customer account account, Basket items should be shared within a browser that has two windows open: one in the regular mode & one in incognito mode
  • Basket items should persist after logging out of an account and then logging back in on the same account on the same browser.

Functionality

  • With baskets contents in one logged in session, add items to another session, and then log into the same account to trigger the basket handling choices.
  • Test all 3 choices options + the additional wish list choice options if they are choosing to use those.
  • Ensure baskets are being deleted when the choice is made not to use them (use current deletes the previous, and vise versa). When testing merge option, test with a variety of basket content scenarios and items. Items with attributes, variants, coupons, basket custom fields (if you've customized their integration for - custom fields).
  • Test failing to make a decision on one browser and taking action again on another.
  • Test all logout options on the store to ensure they've been updated to CDB_LOGO and behavior properly by existing that session entirely.

Features & Modifications

Basket Merging

When a customers login, it can be setup to show options to the customer about how they would like to handle their baskets. These are the customer's options:

  • Merge the previous & current session's basket items together
  • Use the previous session's basket items
  • Use the current session's basket items
  • Save previous session's basket items to a wishlist and continue shopping with the current session's items
  • Save current session's basket items to a wishlist and continue shopping with the previous session's items

For Genesis, we have chosen to default to merging the basket items together automatically without giving the customer a choice. We believe this is the most-seamless & industry standard experience for the customers.

However, if you would like to give the customers a choice, update the cross_device_basket ReadyTheme Content Section so that the l.allow_choice_on_login variable is set to 1 at the top. Setting this variable to 1 (truthy) will show the modal to the customer and setting it to 0 (falsy) will not show the modal and trigger the CDB_Merge action automatically instead.

How to Disable

If you do not want the store to have this feature enabled by default, then you can do the following:

  • De-activate the cross_device_baskets ReadyTheme Content Section.
  • Revert the CDB_LOGO actions back to Miva's default LOGO action.
  • Remove the modal JavaScript from pages/Global.js
  • Optionally, uninstall Toolbelt
    • Unassign the ry_toolbelt item from all pages
    • Delete the ry_toolbelt item
    • Uninstall the Toolbelt module.

Custom Functionality for Basket Custom Fields

Sometimes the Cross Device Baskets feature will need to be extended to ensure that client-specific custom-functionality continues to work. This can occur if the functionality relies on Basket Custom Fields that need to be maintained in certain ways as sessions are merged/restore.

If you have to manage basket custom-fields in specific ways, then you'll probably need to add it into the cross_device_baskets ReadyTheme Content Section where it says:

@@ ADD CUSTOM BAKET CUSTOM-FIELD LOGIC HERE @@

Example Code

The following example shows what kind of logic needed to be added to Plant Therapy to maintain their Add-on Product & Add-on Price Group feature.

<mvt:comment>
|
|   EXAMPLE from PT: Custom Addon CustomField Handling
|
|   Load current basket's addon custom fields.
|   Loop through last basket's custom fields.
|   If current basket has the addon custom fields, then combine the values.
|   If current basket does NOT have the addon custom fields, then just update with the last basket's values.
|
</mvt:comment>
<mvt:item name="customfields" param="Read_Basket( 'addonProducts', l.settings:addonProducts )" />
<mvt:item name="customfields" param="Read_Basket( 'addonPriceGroups', l.settings:addonPriceGroups )" />
<mvt:foreach iterator="customfield" array="last_basket_customfields">
    <mvt:if expr="l.settings:customfield:code EQ 'addonProducts'">
        <mvt:if expr="l.settings:addonProducts NE ''">
            <mvt:foreach iterator="last_addon_product" array="customfield:value">
                <mvt:assign name="l.index" value="miva_array_insert_var( l.settings:addonProducts, l.settings:last_addon_product, -1 )" />
            </mvt:foreach>
        <mvt:else>
            <mvt:assign name="l.settings:addonProducts" value="l.settings:customfield:value" />
        </mvt:if>
    </mvt:if>
    <mvt:if expr="l.settings:customfield:code EQ 'addonPriceGroups'">
        <mvt:if expr="l.settings:addonPriceGroups NE ''">
            <mvt:foreach iterator="last_addon_pricegroup" array="customfield:value">
                <mvt:if expr="NOT (l.settings:last_addon_pricegroup CIN l.settings:addonPriceGroups)">
                    <mvt:assign name="l.index" value="miva_array_insert_var( l.settings:addonPriceGroups, l.settings:last_addon_pricegroup, -1 )" />
                </mvt:if>
            </mvt:foreach>
        <mvt:else>
            <mvt:assign name="l.settings:addonPriceGroups" value="l.settings:customfield:value" />
        </mvt:if>
    </mvt:if>
</mvt:foreach>
<mvt:do file="g.Module_Root $ l.cfmod:module" name="l.success" value="Module_Basket_Set_Field( l.cfmod, l.settings:last_basket:basket_id, 'addonProducts', l.settings:addonProducts )" />
<mvt:do file="g.Module_Root $ l.cfmod:module" name="l.success" value="Module_Basket_Set_Field( l.cfmod, l.settings:last_basket:basket_id, 'addonPriceGroups', l.settings:addonPriceGroups )" />

Source: bdepauw's cross-device-baskets-template-code.mvt