Checkout best practices with Composable Commerce

This guide offers insights for creating an optimal checkout experience. Starting with the sign-in and guest checkout process, we analyze their benefits and limitations. We then explore best practices around shipping configuration. On the topic of payment management, we address topics such as multiple payment attempts and inventory considerations. Lastly, we evaluate the significance of order creation timing.

The standard checkout flow

When designing an optimal checkout flow, there are four key stages to consider:

  1. Starting checkout for registered customers or guests
  2. Shipping and taxes
  3. Payment
  4. Creating the order

The 4 steps of a standard checkout flow

Each stage requires you to make specific decisions. By following best practices for the given phases, you can ensure both an enhanced customer experience and streamlined operations. We delve into each of these four sections in detail, offering insights and recommendations in the context of Composable Commerce.

Starting checkout for registered customers or guests

The first step when designing your checkout flow is deciding whether to offer checkout exclusively to signed-in customers or to include a guest (or external authentication) option. Offering a guest checkout option can enhance user experience, reduce cart abandonment rates, and cater to customers who may prefer a quick purchase without the need for account creation.

When deciding to offer guest (or external authentication) checkout, it's important to understand and assess the following limitations:

You can work around those limitations by creating a placeholder Customer entity in Composable Commerce. This entity contains a link to the external customer, identifiable through email or other unique identifiers such as customerNumber or key. The placeholder Customers can have Carts, Customer Groups, and Shopping Lists, which can be linked to the Cart during the checkout process.

As an alternative for Cart Discounts targeting specific Customer Groups, you can set the Customer Group as a Custom Field on the Cart and match the Cart Discount Predicate against the Custom Field, rather than the standard Customer Group.

Shipping and taxes

Another important aspect of the checkout process is the shipping setup. In particular, it's best practice to set the shipping address on the Cart early in the process. This allows Composable Commerce to determine the appropriate Shipping Methods and Tax Rates for the Cart's Line Items. At this point, the API can calculate the Cart's total, including taxes and shipping costs. Multiple shipping addresses and methods can be set on the Cart for each Line Item and quantity. For a detailed understanding, refer to the Multiple Shipping Addresses and Methods tutorial.

Payment

Next, let's look at payments, another area where merchants often encounter challenges during setup. Since credit card processing demands PCI DSS certification, which has significant cost and strict security requirements, we recommend using a payment service provider (PSP).

A standard PSP integration comprises two components:

  • A synchronous component that starts the payment process by exchanging checkout data between the store and the payment provider.
  • An asynchronous component that receives payment-related notifications from the PSP.

The recommended solution to implement a payment integration is using a middleware (backend for frontend), as it limits complexity and third-party constraints.

Although you can create an Order without a Payment resource, it is still beneficial to create a Payment. A Payment stores the details of the chosen payment method, amount, any data exchanged with the PSP (for example, API requests and responses), asynchronous PSP notifications, and related transactions and states (such as authorization, charge, or refund). By consolidating all critical transaction data, the Payment resource enhances transparency and traceability and can help troubleshoot any potential issues.

Multiple payment attempts

During the checkout phase, customers may try different payment methods. For each initiated payment process, even if aborted and restarted, create a dedicated Payment resource and add it to the Cart. Avoid updating or removing older Payments from the Cart, as these might still be relevant for previously initiated payments (for example, in another browser tab).

This approach ensures that regardless of which payment method eventually succeeds, all associated data remains intact. It also allows you to iterate over Payments of a Cart and check which has succeeded so that you can continue with the Order creation process.

Cart amount changes after payment

Promotions with short expirations or prices with limited validity can cause the cart amount to change after a payment. For instance, a promotion might expire during the payment process, leading to a discrepancy in expected amounts. One solution is to freeze the Cart before payment, locking its amount. However, this comes with its own set of challenges; for example, the complexities of unfreezing a Cart if the customer wants to make modifications after payment redirection.

A potential alternative to Cart freeze is to permit Cart changes at any point. If an amount discrepancy arises, you can process a refund automatically and prompt the customer to reinitiate the payment with the adjusted amount. Refunds can be processed asynchronously, relying on PSP notifications and Subscription Messages.

Inventory considerations

Composable Commerce doesn't validate stock availability when an item is added to the Cart. The validation typically occurs during Order creation, depending on the selected inventoryMode. Consequently, there is a risk that a customer might complete the payment, but the Order fails due to insufficient stock. To mitigate this, we recommend a continuously updated external Inventory Management System (IMS), or alternatively a real-time inventory check before initiating payment.

Creating the Order

The implementation details around when an order is created (before or after successful payment) influence customer experience, stock management, and revenue tracking. Both methods have their own benefits and challenges. After considering the complexities and challenges of each approach, creating an order after a successful payment often stands out as the preferred method. Not only does it offer a more streamlined operational flow, but it also allows for easier and more elegant handling of edge cases. Let's explore a few scenarios arising from both approaches, to gain a deeper understanding and actionable solutions for potential issues.

Creating an order after successful payment

Unreachable redirect URL

There might be instances where the order-success redirect URL of the web store is not accessible due to network issues or if the customer accidentally closes the browser tab. This can result in a successful payment without the corresponding order creation.

A viable method to address this is by asynchronously creating an order based on payment transaction changes. These changes are guaranteed through asynchronous notifications from the PSP. You can either query for the latest Messages of type PaymentTransactionAdded, PaymentTransactionStateChanged, or subscribe to these Message types. These Messages link to the Payment through the resource field. Since every Payment correlates with a Cart, you have all the necessary information to decide if a Cart should be converted to an Order.

Multiple successful payments

There's a possibility of having multiple successful payments on a single cart or order. This can occur, for example, when a customer initiates payment in two separate tabs for the same cart, and both payments are of the redirect type (for example, credit card and PayPal). Both payments can be completed independently, resulting in double payment.

To address this, refund one of the successful payments. You can use the Payment Message to determine if a Cart has too many successful Payments and subsequently initiate a refund.

Mismatched payment and cart amounts

During checkout, a customer might navigate with two browser tabs, one displaying the cart and the other showing a redirected payment with a fixed amount. If the customer adds more items to the cart, there can be a discrepancy between the cart value and the amount displayed (and eventually paid) in the payment tab.

As a solution, validate the cart post-payment to ensure the cart amount aligns with the paid amount. If there's a discrepancy, cancel the payment and request the customer to pay again. Refunds can also be executed asynchronously through the PSP notifications.

Creating an order before successful payment

Unfinished payments and stock issues

If a customer doesn't complete the checkout process or cancels a payment, the reserved stock within an Order won't automatically release. This poses a risk, as automation or high user activity can deplete the web store's stock.

False revenue display

Orders that remain unpaid might still display in the Merchant Center dashboard (or a similar monitoring tool) as revenue, providing an inaccurate representation of actual earnings.

Bestsellers misrepresentation

Unpaid orders can incorrectly influence data representations around what the best-selling products are.

Order modification restrictions

Once an Order is created, modifications to the original Cart become unavailable. This poses a challenge if a customer wants to adjust the cart after the payment was initiated.

Voucher limitations

There could be difficulties managing vouchers that have a one-time application; for instance, if a customer decides not to finalize the payment after a payment redirect and chooses to modify the cart instead. Creating a new cart based on the previous one might present challenges, especially if a product has limited stock and is already linked to an unpaid order.

Generating a unique order number

A unique and human-readable order number is an important part of the order creation process. It often represents a link between the payment provider and Composable Commerce and it also acts as a reference number for customers.

To generate such order numbers, you have several options:

  • Custom Objects: use Custom Objects to both produce and monitor order numbers. Create an object with a container named orderNumbers and a key titled orderCounter. To derive an order number, retrieve the current value of orderCounter, increment it by one, and use this number for the Order. When updating, always specify the version of the Custom Object.

    This method ensures that simultaneous requests do not result in duplicate numbers. If a 409 ConcurrentModification error arises, the system should retry, repeating the entire procedure. To avoid frequent 409 errors due to high order number generation rates, each BFF instance might reserve a set of numbers to use over a period before requesting more.

  • Third-party service: use your BFF to call a third-party service to produce the order number or generate it directly within the BFF.

  • Generating numbers asynchronously: generate order numbers during post-order processes, such as exporting to an order management system (OMS) or importing from an external system.

Conclusion

The checkout process in Composable Commerce presents several options and strategies to cater to varying business needs. Incorporating the best practices from this guide will not only optimize the checkout experience for your customers but also streamline your business processes.