anonymousCartSignInMode for automatic merging and implementing custom merge logic for more complex scenarios.Use anonymousCartSignInMode
CustomerSignIn and MyCustomerSignIn types provide the anonymousCartSignInMode field to control how an anonymous Cart is handled when its owner signs in. In practice, you choose between MergeWithExistingCustomerCart when both sessions should be preserved, and UseAsNewActiveCustomerCart when the anonymous session should replace the previous active Cart. For the complete platform behavior, see Merge a Cart.The available modes are as follows:
MergeWithExistingCustomerCart: merges the Line Items of an anonymous Cart with the Customer's existing active Cart. If the Customer has an active Cart with a shipping address, tax rates are recalculated based on that address before merging. If the Customer has no active Cart, the anonymous Cart becomes their new active Cart.UseAsNewActiveCustomerCart: makes the anonymous Cart the Customer's new active Cart. Tax recalculation depends on the Customer's previous active Cart:- No previous active Cart: taxes are recalculated.
- Previous active Cart without a shipping address: taxes are not recalculated.
- Previous active Cart with a shipping address: taxes are recalculated only if the anonymous Cart does not have a shipping address.
How merge modes work
The shipping address is important because it determines whether tax rates are recalculated during the merge process. This directly affects the prices your Customers see. The presence or absence of a shipping address does not prevent items from merging. It only affects tax recalculation.
MergeWithExistingCustomerCart recalculates prices by using the New York tax rate before it merges the items. This helps make sure that the Customer sees pricing based on their delivery location immediately after sign-in.Line Item matching logic
- If conflicting Line Item keys point to different products or variants, those Line Items are not merged and remain in the anonymous Cart.
- If no key conflicts exist, Line Items are matched based on their properties: product, variant, channels, custom fields, and price mode. Keys are not considered in this matching logic. This means two identical Line Items with different keys will be merged, with the higher quantity retained.
- For the complete matching rules and all merge scenarios, see the Merge rules section in the API reference.
Choosing the right merge mode
Use the following table to determine which merge mode fits your business requirements:
| Aspect | MergeWithExistingCustomerCart | UseAsNewActiveCustomerCart |
|---|---|---|
| Result | Combines Line Items from both Carts into one | Replaces the Customer's Cart with the anonymous Cart |
| Use when | Customers should keep items from both sessions | Anonymous session represents the Customer's current intent |
| Tax recalculation | Yes, if active Cart has a shipping address | Conditional: Yes if no active Cart; No if active Cart lacks shipping address; Yes if active Cart has shipping address but only if anonymous Cart lacks one |
| Previous active Cart | Updated with merged items | Disassociated but not deleted |
Example - Comparison of Cart merging strategies
The following example demonstrates both merge modes in action, showing how each mode affects the final Cart contents when a Customer signs in.
anon-cart-1) contains one Zen Speaker X item and the Customer's existing active cart (cust-cart-A) contains one Zen Tablet Y item.import { apiRoot } from '../../client'; // Assuming apiRoot is initialized and exported here
import {
CustomerSignInResult,
AnonymousCartSignInMode,
} from '@commercetools/platform-sdk'; // Import necessary types
async function simulateLoginAndCartHandlingInStore(
storeKey: string,
email: string,
password: string,
anonymousCartId: string,
mode: AnonymousCartSignInMode
): Promise<CustomerSignInResult> {
try {
const requestBody = {
email: email,
password: password,
anonymousCartId: anonymousCartId, // This is always a string as per function signature
anonymousCartSignInMode: mode,
};
console.log(
`\n--- Attempting in-store login for ${email} with anonymous cart ${anonymousCartId} using mode: ${mode} for store "${storeKey}" ---`
);
const loginResponse = await apiRoot
.inStoreKeyWithStoreKeyValue({ storeKey: storeKey })
.login()
.post({
body: requestBody,
})
.execute();
const signInResult: CustomerSignInResult = loginResponse.body; // Explicitly type the response body
console.log(
`In-Store Login successful. Customer: ${signInResult.customer.email}`
);
console.log(`Active Cart ID: ${signInResult.cart?.id}`);
if (signInResult.cart?.lineItems) {
console.log('Cart Line Items:');
signInResult.cart.lineItems.forEach((item) => {
// Ensure name is accessed safely, as it's a LocalizedString
console.log(` - ${item.name['en-US']} (Quantity: ${item.quantity})`);
});
}
return signInResult;
} catch (error: any) {
// Type 'any' for caught error for now because stricter typing for HTTP errors can be complex
console.error(
`In-Store Login failed with mode ${mode} for store "${storeKey}":`,
error
);
throw error;
}
}
(async () => {
const davidEmail = 'david.shopper@example.com';
const davidPassword = 'DavidSecurePass!';
const anonCartId = 'anon-cart-1'; // Anonymous Cart: 1x Zen Speaker X
const ELECTRONICS_HIGH_TECH_STORE_KEY = 'electronics-high-tech-store';
// David's existing active Cart: 1x Zen Tablet Y
// Scenario 1: MergeWithExistingCustomerCart
// Result: Active Cart contains 1x Zen Speaker X AND 1x Zen Tablet Y
try {
await simulateLoginAndCartHandlingInStore(
ELECTRONICS_HIGH_TECH_STORE_KEY,
davidEmail,
davidPassword,
anonCartId,
'MergeWithExistingCustomerCart'
);
} catch (e) {
console.error(
`Failed to simulate MergeWithExistingCustomerCart scenario for store ${ELECTRONICS_HIGH_TECH_STORE_KEY}.`
);
/* handle error */
}
// Scenario 2: UseAsNewActiveCustomerCart
// Result: Active Cart contains ONLY 1x Zen Speaker X (previous Cart disassociated)
try {
await simulateLoginAndCartHandlingInStore(
ELECTRONICS_HIGH_TECH_STORE_KEY,
davidEmail,
davidPassword,
anonCartId,
'UseAsNewActiveCustomerCart'
);
} catch (e) {
console.error(
`Failed to simulate UseAsNewActiveCustomerCart scenario for store ${ELECTRONICS_HIGH_TECH_STORE_KEY}.`
);
/* handle error */
}
})();
Implement custom Cart merging logic
While the built-in merge modes handle most scenarios and use cases, some business requirements need more control. In these cases, you can implement custom Cart merging logic for specific needs.
When to use custom Cart merging logic
Consider implementing custom Cart merging logic if you need to:
- Apply complex business rules: merge only items from specific categories or add duplicate products as separate Line Items instead of increasing quantity.
- Allow Customer selection: present both Carts to the user and let them choose which items to keep.
- Merge custom data: handle complex merging of custom fields on Carts or Line Items.
- Custom conflict resolution: go beyond the default behavior for handling Cart conflicts.
How to implement custom Cart merging logic
A custom Cart merging process involves these steps:
-
Sign in without
anonymousCartId: call the login endpoint with only credentials to prevent automatic merging and retrieve thecustomerIdandactiveCart. -
Fetch both Carts: retrieve the anonymous Cart ID from the client (for example, a cookie) and fetch both Carts to compare their contents.
-
Apply your merge logic: use Cart update actions (
addLineItem,changeLineItemQuantity,removeLineItem,setCustomField) to build the final merged Cart according to your business rules. -
Clean up: optionally delete the anonymous Cart after successful merging.
Custom Cart merging offers maximum flexibility but introduces complexity in development, testing, and maintenance. Use it only when the built-in modes don't meet your requirements.
Key takeaways
- Use
anonymousCartSignInModeon sign-in to control how anonymous Carts are handled automatically. - Choose
MergeWithExistingCustomerCartwhen Customers should keep items from both their anonymous and logged-in sessions. - Choose
UseAsNewActiveCustomerCartwhen the anonymous session represents the Customer's current intent and should replace their existing Cart. - Tax recalculation during merge depends on whether the Customer's active Cart has a shipping address—this impacts the final prices Customers see.
- Line Items are matched by properties (product, variant, channels) not keys, so identical items with different keys will merge.
- For complex business rules like conditional merging or Customer-driven selection, implement custom Cart merging logic in your backend.
- See the Cart merge API reference for complete technical specifications.