Magento 2 Guest Checkout and Customer Accounts Explained
Guest checkout is one of those settings that looks like a yes or no question and turns into a long discussion. Marketing wants accounts for retention, the conversion people want fewer fields, and support wants customers to find their orders without calling. Magento supports both paths, plus a few ways to connect them, and most of the trouble comes from not knowing what happens to guest orders afterward.
This article explains how guest checkout and customer accounts work together in Magento Open Source and Adobe Commerce 2.4.8: the configuration, what happens when a guest creates an account after the order, how to link older guest orders safely, and what changes for headless frontends.
Turning guest checkout on or off
The main switch is in Stores, Configuration, Sales, Checkout, Checkout Options, Allow Guest Checkout. With it off, customers must log in or register before they reach checkout. With it on, they can enter an email and continue.
There is one product level exception. Under Stores, Configuration, Catalog, Catalog, Downloadable Product Options, the setting "Disable Guest Checkout if Cart Contains Downloadable Items" forces an account when the cart has downloadable products. That makes sense, because the download links live in the customer account.
My usual advice is to keep guest checkout on for B2C stores and to make account creation attractive after the order instead of mandatory before it. Forcing an account at the start of checkout is friction at the worst moment. The decision is the merchant's, though, and B2B stores with negotiated prices usually require login anyway.
What a guest order looks like
A guest order is a normal order with a few differences in sales_order:
customer_idis NULL.customer_is_guestis 1.customer_group_idis the NOT LOGGED IN group, id 0.- The name and email fields hold what the customer typed at checkout.
That last point matters for pricing too. Catalog price rules, cart price rules and tier prices can target customer groups. A guest always gets the NOT LOGGED IN group, so rules meant for "General" customers do not apply to guests. If the merchant expects guests and registered customers to see the same promotions, the rules need both groups.
The email address used by a guest can belong to an existing customer account. Magento allows it, and the order stays a guest order. It does not appear in that customer's account. This surprises many merchants.
How guests find their orders
Guests do not have an account page, so Magento provides the "Orders and Returns" page at /sales/guest/form/. The customer enters the order number, the billing last name and either the email or the billing ZIP code, and sees the order details, invoices and shipments. The footer link is part of the default Luma theme. If your theme removed it, add it back or link to it from the order confirmation email, because otherwise every "where is my order" question goes to support.
Creating an account after the order
After a guest order, the success page shows a block offering to create an account, rendered by Magento\Checkout\Block\Registration. When the customer clicks it, Magento stores the order data in a delegation storage and redirects to the registration form with name and email already filled in.
When the account is created, an observer in Magento_Sales assigns that order to the new customer through Magento\Sales\Model\Order\CustomerAssignment. The order gets the new customer_id, customer_is_guest becomes 0 and it appears in the account history.
Only the order from that success page is linked. Earlier guest orders with the same email stay as guest orders. Magento Open Source has no built in way to link them.
Linking older guest orders safely
A common request is "when a customer registers, attach all their previous guest orders". It sounds easy: find guest orders with the same email and set the customer id. The risk is security. Anyone can register with someone else's email and, if the account becomes active right away, see that person's order history, addresses and phone number.
So the linking should only happen after the email address is proven to belong to the customer. The safest trigger is account email confirmation, which you enable under Stores, Configuration, Customers, Customer Configuration, Create New Account Options, Require Emails Confirmation. Then run the linking after the account is confirmed, not after it is created.
The linking itself can reuse the same core class the success page flow uses:
<?php
declare(strict_types=1);
namespace Vendor\GuestOrders\Model;
use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Sales\Model\Order\CustomerAssignment;
class LinkGuestOrders
{
public function __construct(
private readonly OrderRepositoryInterface $orderRepository,
private readonly SearchCriteriaBuilder $searchCriteriaBuilder,
private readonly CustomerAssignment $customerAssignment
) {
}
public function execute(CustomerInterface $customer): int
{
$criteria = $this->searchCriteriaBuilder
->addFilter('customer_email', $customer->getEmail())
->addFilter('customer_is_guest', 1)
->addFilter('customer_id', true, 'null')
->create();
$linked = 0;
foreach ($this->orderRepository->getList($criteria)->getItems() as $order) {
if ((int) $order->getStore()->getWebsiteId() !== (int) $customer->getWebsiteId()) {
continue;
}
$this->customerAssignment->execute($order, $customer);
$linked++;
}
return $linked;
}
}
The website check matters when customer accounts are scoped per website. Under Customer Configuration, Account Sharing Options, accounts can be shared globally or per website. With per website accounts, the same email can belong to two different customers on two websites, and an order from one must not end up in the other's account.
Run this from a queue consumer or a cron job, not inside the request that confirms the account, so a customer with hundreds of guest orders does not wait. For an existing customer base, a one time CLI command can run the same class for all confirmed accounts. Test it on a sanitized copy of production first. See sanitizing a staging database.
Email checks at checkout
In the Luma checkout, when a guest types an email, the frontend asks the server if an account exists for it and, if so, shows a password field to log in. This is convenient, but it also tells anyone whether an email has an account on the store, which is a privacy concern. Magento 2.4.7 added a setting under Checkout Options, Enable Guest Checkout Login, which is off by default. When it is off, checkout does not reveal whether the email has an account. Check this setting after an upgrade from an older version, because the checkout behavior changes and merchants sometimes report it as a bug.
Carts when a guest logs in
If a guest adds products and then logs in, Magento merges the guest cart into the customer's active cart. Items that were already in the customer cart stay, and quantities of the same product are added together. Customers sometimes notice old items appear at checkout. That is this merge, not a bug. The "Persistent Shopping Cart" feature, configured under Customers, Persistent Shopping Cart, is a separate mechanism that keeps a logged out customer's cart for a period of time.
On the storefront, what the header and minicart show after login comes from customer data sections loaded by JavaScript. If they look stale after a custom login flow, the sections were probably not invalidated. Customer data sections explains how that works.
Headless and GraphQL
In a headless storefront the same rules apply, but the frontend owns the flow. Guests use a cart id without authentication and must set an email on the cart with setGuestEmailOnCart before placing the order. Logged in customers use a customer token, and merging a guest cart into the customer cart is an explicit call to mergeCarts. The details are in GraphQL cart and checkout mutations.
The post order account creation flow from the Luma success page does not exist in GraphQL. A headless frontend that wants the same behavior has to create the account and assign the order on its own, with the same email verification concerns described above.
FAQ
Why does a guest order not appear in the customer's account?
Guest orders keep customer_id empty even when the email matches an existing account. Only the order linked through the success page registration is assigned automatically. Older orders need custom linking.
Is it safe to link guest orders by email automatically?
Only after the customer has confirmed the email address. Otherwise anyone can register with another person's email and see their orders and addresses.
Why don't guests get the same discount as logged in customers?
Guests always belong to the NOT LOGGED IN customer group. Add that group to the price rules that should apply to guests.
How can a guest check an order status?
Through the Orders and Returns page at /sales/guest/form/, using the order number, billing last name and email or ZIP code.
I am available for freelance Magento and Adobe Commerce work, including checkout and customer account flows. If you need help with this, get in touch.
Related articles
Magento 2 Custom Fee: Write a Totals Collector That Works
Add a custom fee to Magento 2 with a quote totals collector: sales.xml, collect and fetch, cart and checkout display, copying it to orders, invoices and PDFs.
Magento 2 Custom Payment Method with the Payment Gateway API
Build a custom payment method in Magento 2.4 using the Payment Gateway API: facade virtual type, config, commands and the checkout JS renderer, step by step.
Magento 2 Custom Shipping Method: Build a Carrier Module
How to build a custom shipping method in Magento 2.4: config.xml, system.xml, a carrier model with collectRates, free shipping rules and external rate APIs.
Hyvä Checkout Explained: Magewire, Customization, Payments
How Hyvä Checkout works for developers: Magewire components, adding a custom field, payment module support, and when to keep the Luma checkout fallback.