Headless WooCommerce & Next.js: Display Products and Create Orders
So far we have fetched our products from WooCommerce and set up styled-components. Next up is to display these products and show you the basics of how to create an order.
Display your Products
We have already fetched an array of products that we can manipulate in any way our creative minds like. For this project, the home page will be a simple menu page where you can scroll through available products.
The most important part of the menu is to indicate what product the user wants to select and so you will need to extract the WooCommerce product ID.
I created a very simple, mobile-first, display by creating a product card component and using CSS Grid to layout the products. I would like to include breakpoints and media-queries to create a responsive app but I want to keep things simple for now.
Now that we have a Product Card component to display our product we can map through the array of products we have already fetched and use our Product Card component.
{ products.map((product) => { return <ProductCard product={product} key={product.id} />;})}
Remember we need to pass a key when using the map function and I chose product.id
as a unique identifier.
I used CSS Grid layout to manage the newly returned array of ProductCard
but you can do whatever you like!

A brief word on image optimization
Before we move on, some of you may have noticed that I used the <Image />
component from Next.js rather than the standard <img />
HTML tag. The reason for this is because, since v.10.0.0, Next.js has built-in Automatic Image Optimization. Images often make up a significant portion of a website’s weight so optimising images will improve your page loading speed and performance. Next.js also lazy-loads the images by default so images only load as they are scrolled into viewport.
Create Orders
You may be wondering why we are going straight to creating orders when the UI and UX has barely been touched. The reason for doing this now is to show you that we can create orders with minimal data. For some of you it means you can ditch these tutorials, arm yourself with the WooCommerce developer docs and run off on your own steam.
The goal of e-commerce is to show people your products and get them to place an order with you. There’s a lot of scaffolding that goes into place that ensures that order gets placed (e.g. nice way to browse the range of products, showcase specific product details, track and manage cart items, easy checkout process).
Many of us are intrinsically familiar with the scaffolding that’s put in place and there’s a lot to consider and a lot to build. However, not all of it is technically necessary. By stripping it all the way back, you can see how easy it is to place an order and then we can add layer by layer until you have the e-commerce experience you are looking for.
Using WooCommerceRestApi
When we fetched the products from WooCommerce we used WooCommerceRestApi
from their official Javascript SDK. We want to use this client again to make a POST
request to the /orders
endpoint. In the WooCommerce developer docs you can see an example of the data
object that can be passed to the endpoint — it is a subset of a WooCommerce order object.
Check the docs to see all properties that exist for an order and you might notice that none of them are required fields. That’s right, you can pass an empty JSON object and you will be able to create a new order.
There’s obviously not much point in a new order with zero information but at least you know you can include as little or as much information as you need. If you don’t require a billing address or a shipping address — perhaps an email address is all you need — then don’t create a form to grab that information. We’re so used to seeing address forms in checkouts but if you don’t need it then leave it out.
In my example I want to show you how to add some products to the order. To do this, WooCommerce is expecting an array of Line Items
. Again, check the WooCommerce developer docs for Line Items
properties and you’ll notice there are a number of read-only fields but we can pass key fields such as product_id
, quantity
and subtotal
. Actually, when adding a new line item all you need to do is pass product_id
and quantity
and WooCommerce will work out the rest of the data.
Things get a little trickier when you are updating a line item but we can come back to this later — if you are updating the quantity for an existing line item just double-check the subtotal
, total
and price
after.
In my example above I also added a few extra fields to show information about the payment method and also whether the order is paid or not. If you assign set_paid
as true
then the WooCommerce order status will be set to Processing
. If you assign set_paid
as false
then the order status will be set to Pending payment
.
With a hard-coded data object in place (for dev purposes) we can now use the WooCommerceRestApi
client with the POST
method on the /orders
endpoint.
I’ve included the code we used to initialise the WooCommerceRestApi
. I like to keep this at the top of the file so I have access to the api
client in all subsequent functions in wooCommerceApi.ts
.
Pay attention to the comment in the code reminding us these API calls must be made server side in order to access the environment variables. I manage this by creating a custom API endpoint in Next.js that calls the createWooCommerceOrder
on the server-side. If you would rather skip this for testing and development purposes then try putting your consumerKey
and consumerSecret
directly into the WooCommerceRestApi
configuration and call it from the front-end. (Let me know if you want me to cover the custom API endpoint.)
In this example I passed along the hard-coded data
object to createWooCommerceOrder
and called the function using a temporary dev button.
Now, if you check the orders in the WooCommerce dashboard of your Wordpress site you should see your new order. You’ll notice you can manually change the order status in the WooCommerce dashboard alongside a whole host of other functions. Useful if you need to make any changes without diving into code.
We will want to make a more sophisticated e-commerce platform with a checkout that allows for card payment and a cart that allows the user to check and manage their wanted items. To help with future marketing we will want to at least get the customer’s name and email and/or phone so we can contact them at a later date.