Francisco Quintanilla
Mar 27, 2023
  3236
(0 votes)

How to Merge Anonymous Carts When a Customer Logs In with Optimizely Commerce 14

In e-commerce, it is common for users to browse a site anonymously, adding items to their cart without creating an account. Later, when the user decides to create an account or log in, they may have items already in their anonymous cart that they would like to keep. In this scenario, it is important to merge the anonymous cart with the authenticated cart to ensure a seamless shopping experience.

In this blog post, I will show you how to merge anonymous carts with authenticated carts in Optimizely Commerce 14.

Overview

The code I will be using is a middleware component that runs on every incoming HTTP request. If the user is authenticated, the middleware retrieves the user's anonymous cart using the IAnonymousIdFeature and merges it with their authenticated cart.

using EPiServer.Commerce.Order;
using EPiServer.ServiceLocation;
using Mediachase.Commerce;
using Mediachase.Commerce.Anonymous;
using Mediachase.Commerce.Customers;
using Mediachase.Commerce.Markets;

namespace Infrastructure.Commerce.Extensions
{
    public class AnonymousCartMergingMiddleware
    {
        private readonly RequestDelegate _next;

        public AnonymousCartMergingMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            if (context.User.Identity != null && context.User.Identity.IsAuthenticated)
            {
                var anonymousId = context.Features.Get<IAnonymousIdFeature>().AnonymousId;
                
                if (!string.IsNullOrWhiteSpace(anonymousId))
                {
                    var orderRepository = ServiceLocator.Current.GetInstance<IOrderRepository>();
                    var marketService = ServiceLocator.Current.GetInstance<IMarketService>();
                    
                    var market = marketService.GetMarket(MarketId.Default);
                    var cart = orderRepository.LoadCart<ICart>(new Guid(anonymousId), Constants.CartName.ShoppingCart, market.MarketId);

                    if (cart != null && cart.GetAllLineItems().ToList().Count > 0)
                    {
                        var currentMarket = ServiceLocator.Current.GetInstance<ICurrentMarket>();
                        cart.MarketId = currentMarket.GetCurrentMarket().MarketId;
                        orderRepository.Save(cart);
                        
                        var profileMigrator = ServiceLocator.Current.GetInstance<IProfileMigrator>();
                        profileMigrator.MigrateCarts(new Guid(anonymousId));
                    }
                }
            }

            await _next(context);
        }
    }
}

You can use an extension method to expose the middleware through `IApplicationBuilder`.

namespace Infrastructure.Commerce.Extensions
{
    public static class AnonymousCartMergingMiddlewareExtensions
    {
        public static IApplicationBuilder UseAnonymousCartMerging(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<AnonymousCartMergingMiddleware>();
        }
    }
}

The following code calls the middleware from `Startup.cs`

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseAnonymousCartMerging();        
    }
Mar 27, 2023

Comments

Manoj Kumawat
Manoj Kumawat Apr 20, 2023 02:08 PM

I am curious to know if AnonymousId is consistent throughout the user session until you merge the carts. 

in CMS 11 we had a problem of Anonymous ID being lost in a load-balanced environment. Then I had to do this in order to keep anonymousID persistent. 

https://vimvq1987.com/loading-carts-load-balancing-environment/

Not sure if this is still a problem with that. If not, then it is not a problem anymore to worry about. 

Please login to comment.
Latest blogs
Running 64 Sites on Headless Optimizely CMS with GraphQL

64 websites. Live. Running on headless Optimizely with GraphQL. We just wrapped a major rollout for our Rockwool Digital Experience Platform  and t...

Piotr | Mar 14, 2026

Disabling the scheduler also stops event-based indexing in Optimizely

If you disable the scheduler in Optimizely CMS, should event-based indexing stop working too? It does!

Tomas Hensrud Gulla | Mar 13, 2026 |

Meet the latest OMVPs - H1 2026 Cohort

Meet the Latest Cohort of Optimizely Most Valuable Professionals (OMVPs) Every year, the Optimizely Most Valuable Professional (OMVP) program...

Satata Satez | Mar 13, 2026

64 Websites Live on Headless Optimizely with GraphQL

64 websites running on headless Optimizely with GraphQL. A major rollout for Digital Experience Platform covering Algolia integration, Next.js...

Piotr | Mar 12, 2026 |

64 Websites Live on Headless Optimizely with GraphQL

64 websites running on headless Optimizely with GraphQL. A major rollout for Digital Experience Platform covering Algolia integration, Next.js...

Piotr | Mar 12, 2026 |

Optimizely Commerce vs Composable Commerce: What Should You Do with CMS 13?

As organizations modernize their digital experience platforms, a common architectural question emerges: Should we continue using Optimizely Commerc...

Aniket | Mar 12, 2026