The SDK ecom
module allows you to take advantage of Wix eCommerce services in a site or app you build on any platform. This means you can handle shopping carts and checkout flows for your Wix Store products.
This tutorial shows you how to create a React component with a complete eCommerce flow. The component lists products from a Wix store, allows visitors to add products to a shopping cart, and redirects visitors to a checkout page. The tutorial also demonstrates how to maintain cart sessions.
The tutorial is based on the Wix Headless example site. You can test out the live example site, or fork the site's code repo to use as a starting point for your own site or app.
This implementation focuses on simplicity and understandability, rather than feature richness, performance or completeness. For details about additional functionality, see Wix eCommerce in the API Reference. Looking for a more comprehensive example site integrating Wix Headless APIs for managing an online store? Check out our starter templates.
Note: The code in this tutorial is written in JSX, but you can use the SDK in any JavaScript environment.
Implementing the eCommerce flow includes the following steps:
useEffect
hook.Before using the SDK, there are a few things you need to set up on your Wix account and in your external site or app's coding environment.
To set up the Wix Headless environment, follow these steps:
npm install @wix/sdk npm install @wix/stores npm install @wix/ecom npm install @wix/redirects
yarn add @wix/sdk yarn add @wix/stores yarn add @wix/ecom yarn add @wix/redirects
react
package to handle UI rendering and the js-cookie
package to handle session cookies. Run the following commands:npm install react npm install js-cookie
yarn add react yarn add js-cookie
The next step is to set up your code file to run the SDK functions. To set up the code file, follow these steps:
Add the following import statements to the top of your code file:
import Cookies from "js-cookie";
import { useEffect, useState } from "react";
import { createClient, OAuthStrategy } from "@wix/sdk";
import { products } from "@wix/stores";
import { currentCart } from "@wix/ecom";
import { redirects } from "@wix/redirects";
Create an SDK client by adding the following code to your code file. Replace the value for clientId
with your OAuth app's client ID. You can find the ID in your project's Headless Settings menu.
The value for tokens
is the 'session'
cookie on the visitor's browser. It's used to make calls to the Wix API. This way, you can maintain previous visitor sessions. For information about managing cookies, see Session Token Management.
const myWixClient = createClient({
modules: { products, currentCart, redirects },
auth: OAuthStrategy({
clientId: `<YOUR-CLIENT-ID>`,
tokens: JSON.parse(
Cookies.get("session") || '{"accessToken": {}, "refreshToken": {}}',
),
}),
});
The logic for our eCommerce flow is contained in a React component called Store
. To create the component, follow these steps:
export default function Store() {}
Store
component:productList
variable stores the list of products from your project's Wix Store. The cart
variable stores the current cart session.
const [productList, setProductList] = useState([]);
const [cart, setCart] = useState({});
Define a function to fetch your Wix Store products by adding the following code to the Store
component. This function runs when the component is first rendered. The function uses the queryProducts()
function from the SDK's Stores module to query your store's products.
async function fetchProducts() {
const productList = await myWixClient.products.queryProducts().find();
setProductList(productList.items);
}
Add the following 3 functions for handling cart sessions to the Store
component. Each of these functions use functions from the ecom
CurrentCart
submodule.
fetchCart()
- Fetches the current cart session, if there is one, using the getCurrentCart()
function. Sets the browser's session cookie to the SDK client's current access tokens. fetchCart()
runs when the component is first rendered.
async function fetchCart() {
try {
setCart(await myWixClient.currentCart.getCurrentCart());
} catch {}
}
addToCart()
- Adds a product to the cart using the addToCurrentCart()
function. addToCart()
runs when a product rendered in the UI is clicked.
async function addToCart(product) {
const options = product.productOptions.reduce(
(selected, option) => ({
...selected,
[option.name]: option.choices[0].description,
}),
{},
);
const { cart } = await myWixClient.currentCart.addToCurrentCart({
lineItems: [
{
catalogReference: {
appId: "215238eb-22a5-4c36-9e7b-e7c08025e04e",
catalogItemId: product._id,
options: { options },
},
quantity: 1,
},
],
});
setCart(cart);
}
clearCart()
- Clears the current cart session using the deleteCurrentCart()
function. clearCart()
runs when a Clear Cart button in the rendered UI is clicked.
async function clearCart() {
const { cart } = await myWixClient.currentCart.deleteCurrentCart();
setCart(cart);
}
Add a function called createRedirect()
to the Store
component. This function runs when a Checkout button in the rendered UI is clicked. The function
does the following:
createCheckoutFromCurrentCart()
function to create a checkout for the products currently in the cart and retrieve a checkoutId
.createRedirectSession()
function with the retrieved checkoutId
to retrieve an ecom
checkout URL. This is the URL for a Wix-managed checkout page that the visitor can use to complete the checkout process.postFlowUrl
property when calling the createRedirectSession()
function.async function createRedirect() {
const { checkoutId } =
await myWixClient.currentCart.createCheckoutFromCurrentCart({
channelType: currentCart.ChannelType.WEB,
});
const redirect = await myWixClient.redirects.createRedirectSession({
ecomCheckout: { checkoutId },
callbacks: { postFlowUrl: window.location.href },
});
window.location = redirect.redirectSession.fullUrl;
}
Notes:
useEffect
hookAdd the following code to the Store
component to run the fetchProducts()
fetchCart()
functions after the component is rendered. This ensures that your product data, any existing cart data, and member data are available when the component mounts.
useEffect(() => {
fetchProducts();
}, []);
useEffect(() => {
fetchCart();
}, []);
Add the following code to the Store
component's return
statement to render the UI. The UI displays the following:
<div>
<div>
<h2>Choose Products:</h2>
{productList.map((product) => {
return (
<div key={product._id} onClick={() => addToCart(product)}>
{product.name}
</div>
);
})}
</div>
<div>
<h2>Cart:</h2>
{cart.lineItems?.length > 0 && (
<>
<div onClick={() => createRedirect()}>
<h3>
{cart.lineItems.length} items ({cart.subtotal.formattedAmount})
</h3>
<span>Checkout</span>
</div>
<div onClick={() => clearCart()}>
<span>Clear cart</span>
</div>
</>
)}
</div>
</div>;
You can use the following full code example as a starting point for developing your own site:
import { createClient, OAuthStrategy } from "@wix/sdk";
import { products } from "@wix/stores";
import { currentCart } from "@wix/ecom";
import { redirects } from "@wix/redirects";
import { useEffect, useState } from "react";
import Cookies from "js-cookie";
const myWixClient = createClient({
modules: { products, currentCart, redirects },
auth: OAuthStrategy({
clientId: `<YOUR-CLIENT-ID>`,
tokens: JSON.parse(
Cookies.get("session") || '{"accessToken": {}, "refreshToken": {}}',
),
}),
});
export default function Store() {
const [productList, setProductList] = useState([]);
const [cart, setCart] = useState({});
async function fetchProducts() {
const productList = await myWixClient.products.queryProducts().find();
setProductList(productList.items);
}
async function fetchCart() {
try {
setCart(await myWixClient.currentCart.getCurrentCart());
} catch {}
}
async function addToCart(product) {
const options = product.productOptions.reduce(
(selected, option) => ({
...selected,
[option.name]: option.choices[0].description,
}),
{},
);
const { cart } = await myWixClient.currentCart.addToCurrentCart({
lineItems: [
{
catalogReference: {
appId: "215238eb-22a5-4c36-9e7b-e7c08025e04e",
catalogItemId: product._id,
options: { options },
},
quantity: 1,
},
],
});
setCart(cart);
}
async function clearCart() {
await myWixClient.currentCart.deleteCurrentCart();
setCart({});
}
async function createRedirect() {
const { checkoutId } =
await myWixClient.currentCart.createCheckoutFromCurrentCart({
channelType: currentCart.ChannelType.WEB,
});
const redirect = await myWixClient.redirects.createRedirectSession({
ecomCheckout: { checkoutId },
callbacks: { postFlowUrl: window.location.href },
});
window.location = redirect.redirectSession.fullUrl;
}
useEffect(() => {
fetchProducts();
}, []);
useEffect(() => {
fetchCart();
}, []);
return (
<div>
<div>
<h2>Choose Products:</h2>
{productList.map((product) => {
return (
<div key={product._id} onClick={() => addToCart(product)}>
{product.name}
</div>
);
})}
</div>
<div>
<h2>Cart:</h2>
{cart.lineItems?.length > 0 && (
<>
<div onClick={() => createRedirect()}>
<h3>
{cart.lineItems.length} items ({cart.subtotal.formattedAmount})
</h3>
<span>Checkout</span>
</div>
<div onClick={() => clearCart()}>
<span>Clear cart</span>
</div>
</>
)}
</div>
</div>
);
}