Managing the cart (Shopify Hydrogen)
Managing the cart (Shopify Hydrogen)
When building Coveo-powered commerce interfaces using server-side rendering (SSR), it’s crucial to keep the Headless cart state synchronized with the Shopify cart.
When a user interacts with the cart, such as adding or removing a product, the cart state must be updated in the Headless engine and the Shopify cart.
Convert the Shopify cart to a Headless cart
When fetching the static state of the app, you must retrieve the Shopify cart state and convert it to the Headless cart state.
The following example shows how to convert the Shopify cart to a Headless cart:
// lib/map-coveo-shopify.cart-ts
import type {CartItem as HeadlessCartItem} from '@coveo/headless-react/ssr-commerce';
import type {
CartLine,
ComponentizableCartLine,
CartReturn,
} from '@shopify/hydrogen/storefront-api-types';
function mapShopifyCartToCoveoCart(cart: CartReturn | null) {
return {
items: cart?.lines.nodes.map((node) => {
return mapShopifyMerchandiseToCoveoCartItem(node);
}),
};
}
export function mapShopifyMerchandiseToCoveoCartItem(
node: CartLine | ComponentizableCartLine,
): HeadlessCartItem {
const {merchandise} = node;
const selectedColor = merchandise.selectedOptions.find(
(opt) => opt.name === 'Color',
);
return {
productId: `${merchandise.product.handle.toUpperCase()}_${colorToShorthand(
selectedColor?.value || '',
)}`,
name: merchandise.product.title,
price: Number(merchandise.price.amount),
quantity: node.quantity,
};
}
export function colorToShorthand(color: string) {
const colorMap: {[key: string]: string} = {
'birchwood brown': 'BB',
black: 'BK',
blue: 'BL',
brown: 'BR',
clear: 'CL',
cyan: 'CY',
'deep red': 'DR',
'forest green': 'FG',
gray: 'GY',
green: 'GN',
grey: 'GY',
khaki: 'KH',
lime: 'LM',
'multi color': 'MC',
'multi-colored': 'MC',
natural: 'NT',
navy: 'NY',
'olive green': 'OG',
olive: 'OL',
one: '01',
orange: 'OR',
pink: 'PK',
purple: 'PL',
red: 'RD',
'rustic yellow': 'RY',
silver: 'SV',
'sky blue': 'SB',
white: 'WH',
yellow: 'YL',
beige: 'BG',
gold: 'GD',
striped: 'ST',
neon: 'NE',
pastel: 'PS',
tan: 'TN',
};
return colorMap[color.toLowerCase() as keyof typeof colorMap] || 'BK';
}
Modify the cart state based on user interactions
When a user interacts with the cart, such as adding or removing a product, you must update both the Shopify cart and the Headless cart state.
This section focuses on the Headless-specific implementation.
For details on updating the Shopify cart, refer to the Shopify documentation.
|
Note
To use the components defined in the following section, make sure you have set up a cart handler This setup provides access to the Shopify cart, which is passed to the components as a prop to access objects such as |
Add cart items
The add-to-cart button component is often included directly on the product listing page (PLP), product detail page (PDP), or the search results page.
import {CartForm} from '@shopify/hydrogen';
import {useCart} from '~/lib/commerce-engine.ts';
import {Product} from '@coveo/headless-react/ssr-commerce';
export default function AddToCartButton({
product,
lines,
}: {
product: Product;
lines: { quantity: number }[];
}) {
const coveoCart = useCart();
const currentQuantity =
coveoCart.state.items.find((item) => item.productId === product.id)
?.quantity || 0;
const quantityToAdd = lines[0]?.quantity ?? 0;
const newQuantity = currentQuantity + quantityToAdd;
return (
<CartForm
route="/cart"
action={CartForm.ACTIONS.LinesAdd}
inputs=
>
<button
onClick={() => {
coveoCart.methods?.updateItemQuantity({
name: product.title,
price: product.price,
productId: product.id,
quantity: newQuantity,
});
}}
>
Add to cart
</button>
</CartForm>
);
}
Use the useCart hook to retrieve the Headless cart state.
Ensure that the cart controller was defined when creating your engine configuration. |
|
Calculate the current quantity of the product in the cart. | |
Use the CartForm component to submit the cart update as specified in the Shopify documentation |
|
Update the cart item quantity by calling the updateItemQuantity method. |
Update cart items
When a user updates an item’s quantity in the cart, ensure the Headless cart state reflects the new quantity.
import {CartForm} from '@shopify/hydrogen';
import type {CartLineUpdateInput} from '@shopify/hydrogen/storefront-api-types';
import type {CartItem} from '@coveo/headless-react/ssr-commerce';
import {useCart} from '~/lib/commerce-engine.ts';
export default function UpdateCartItemsButton({
cartItem,
lines,
newQuantity,
}: {
cartItem: CartItem;
lines: CartLineUpdateInput[];
newQuantity: number;
}) {
const coveoCart = useCart();
return (
<CartForm
route="/cart"
action={CartForm.ACTIONS.LinesUpdate}
inputs=
>
<button
type="button"
onClick={() => {
coveoCart.methods?.updateItemQuantity({
...cartItem,
quantity: newQuantity,
});
}}
>
Update cart
</button>
</CartForm>
);
}
Use the CartForm component to submit the cart update as specified in the Shopify documentation |
|
Update the cart item quantity using the updateItemQuantity method. |
Remove cart items
When a user removes an item from the cart, update the Headless cart state by setting the item’s quantity to 0
.
import { CartForm } from '@shopify/hydrogen';
import type { CartItem } from '@coveo/headless-react/ssr-commerce';
import { useCart } from '~/lib/commerce-engine.ts';
export default function RemoveCartItemButton({
lineIds,
cartItem,
}: { lineIds: string[]; cartItem: CartItem }) {
const coveoCart = useCart();
return (
<CartForm
route="/cart"
action={CartForm.ACTIONS.LinesRemove}
inputs=
>
<button
type="button"
onClick={() => {
coveoCart.methods?.updateItemQuantity({ ...cartItem, quantity: 0 });
}}
>
Remove items
</button>
</CartForm>
);
}
Use the CartForm component to submit the cart update as specified in the Shopify documentation |
|
Update the cart item quantity to 0 using the updateItemQuantity method. |