Manage Cart sessions and merges

Learn how to seamlessly merge anonymous and customer Carts during the sign-up or sign-in process.

After completing this page, you should be able to:

  • Differentiate between the platform's automatic Cart merging modes (MergeWithExistingCustomerCart and UseAsNewActiveCustomerCart) that occur during customer sign-in.
  • Implement a user sign-in process that correctly merges an anonymous Cart with a customer's existing Cart.

When a customer transitions from a guest to an authenticated session (by logging in or signing up), any Cart (or private resources) they created as a guest must be associated with their account. This prevents the Cart from being orphaned and eventually deleted.

The logic depends on whether the customer already has a Cart associated with their account.

The customer does not have a pre-existing Cart

This is the simplest case. The guest Cart just needs to be assigned to the customer.

Update the Cart by setting its customerId field to the ID of the logged-in customer. The Cart is now linked to their account and will be available across their devices and future sessions.

The customer has a pre-existing Cart

In this case, the customer has two active Carts: the new guest Cart and an older one from a previous session. You must define a merging strategy to resolve this conflict.

Use your own business logic

First, assign the customerId to the new guest Cart as described above. Then, implement business logic to merge the two Carts. Common strategies include:
  • Merge Line Items: move all Line Items from the guest Cart into the customer's existing Cart and then delete the now-empty guest Cart.
    • Use the most recent Cart: keep the Cart with the most recently added item and delete the other.
    • Prompt the user: allow the customer to review both Carts and decide which one to keep or how to merge them.

Composable Commerce also provides the ability to automatically merge existing Carts for you, for both sign-up and sign-in. It will also automatically assign the private resource to the Customer ID.

You can choose to apply your own custom Cart merge logic or use Composable Commerce’s provided merge logic.

Use Composable Commerce merge logic

The following default APIs for sign-up and sign-in can merge the Carts for you:

  • Authenticate (sign in) Customer and Authenticate (sign in) Customer Store: allow you to pass the anonymousCart ID or anonymousId in the CustomerSignin body. Using the anonymousId will mean that the system looks for all Carts with that ID and assigns those Carts to the Customer. In the same body, we have the option to set the anonymousCartSignInMode:
    • MergeWithExistingCustomerCart (default): set to MergeWithExistingCustomerCart if Line Items of the anonymous Cart should be merged with the active Customer Cart that has been modified most recently.
    • UseAsNewActiveCustomerCart: set to UseAsNewActiveCustomerCart if the anonymous Cart should be used as the new active Customer Cart and no Line Items are to be merged.
  • Create (sign up) Customer and Create (sign up) Customer Store: the CustomerDraft allows you to pass the anonymousCart or anonymousId (identifies Carts and Orders belonging to an anonymous session that will be assigned to the new Customer) for merging. Passing these values for sign in or sign up are optional, if you don’t pass them, then they won't be automatically merged. This can mean that you can apply your own merge logic and session management.

Merge customer Carts on sign-in

Let’s consider the scenario where an anonymous shopper browsing the Electronics High Tech store adds items to their Cart. Later, they decide to log in to their existing Electronics High Tech customer account. This customer might already have a Cart from a previous session. Here we will use Composable Commerce’s built-in functionality to help you handle this Cart merging process during the customer sign-in.

Let’s examine the code Zen Electron might implement to handle Customers signing-in:

import { apiRoot } from "../ctp-root";
import {
  CustomerSignInResult,
  CustomerSignin,
} from "@Composable Commerce/platform-sdk";
import { ClientResponse } from "@Composable Commerce/ts-client";

/**
 * Sign in the Customer using their email and password and merge Carts assigned to their anonymousId with their Active Customer Cart
 * @param storeKey Key of the Store the Customer is shopping on
 * @param email Customer email
 * @param password Customer password
 * @param anonymousId Customer assigned anonymousId prior to signing-in
 * @param mergeCarts Cart merge behavior. If true (default), Cart created prior to signing-in will be merged with the Customer's Active Cart. If false, the Cart created prior to signing-in will be added to their Customer Active Carts.
 * @returns CustomerSignInResult on successful sign-in. Contain the Customer data and Active Cart.
 */
async function signin(
  storeKey: string,
  email: string,
  password: string,
  anonymousId?: string,
  mergeCarts: boolean = true
): Promise<CustomerSignInResult> {
  const customerSignin: CustomerSignin = {
    email: email,
    password: password,
    anonymousId: anonymousId ? anonymousId : undefined,
    anonymousCartSignInMode: mergeCarts
      ? "MergeWithExistingCustomerCart"
      : "UseAsNewActiveCustomerCart", // Merge with existing Customer Cart if mergeCarts is not passed or true
  };

  const response = await createApiClient()
    .inStoreKeyWithStoreKeyValue({ storeKey: storeKey }) // Use the Store-scoped endpoint
    .login()
    .post({
      body: customerSignin,
    })
    .execute();
  return response.body;
}
Since Zen Electron uses a single Customer Cart, their team decided to use the default MergeWithExistingCustomerCart behavior to merge the anonymous Cart with the Customer’s Active Cart.

Test your knowledge