Commerce8 min read

How to Integrate WooCommerce with Your Headless CMS

Connect WooCommerce to a headless CMS so product pages, buying guides, and campaign content stay in sync with your catalog without copying fields by hand.

Published April 29, 2026
01Overview

What is WooCommerce?

WooCommerce is an open-source commerce plugin for WordPress that handles products, carts, checkout, taxes, shipping, coupons, orders, and payments. It's used by small stores, subscription businesses, B2B sellers, and custom commerce teams that want control over their storefront and WordPress-based operations. Its REST API lets external systems create and update products, variations, categories, coupons, and orders.


02The case for integration

Why integrate WooCommerce with a headless CMS?

WooCommerce is good at commerce operations: prices, SKUs, stock status, checkout, taxes, and orders. A headless CMS is better for editorial product content: comparison tables, fit guides, care instructions, localized landing pages, campaign copy, and reusable product storytelling. When those systems aren't connected, teams end up copying the same product title, description, image, and category fields between tools. That creates drift fast, especially when you're updating 50 SKUs for a sale or launching a product in 3 regions.


03Architecture

Architecture overview

A common WooCommerce and Sanity integration starts when an editor publishes or updates product content in Sanity Studio. The product document is structured in the Content Lake with fields like sku, title, slug, shortDescription, productImages, category references, priceCopy, and wooProductId. A GROQ query selects only the fields WooCommerce needs, including joined data from referenced category and image documents. On publish, a Sanity webhook fires with a filtered payload, for example only documents where _type == "product". That event can call a Sanity Function or your own webhook endpoint. The server-side code validates the webhook secret, fetches the latest product document from the Content Lake with @sanity/client, maps Sanity fields to WooCommerce fields, and calls the WooCommerce REST API. For a new product, it sends POST /wp-json/wc/v3/products. For an existing product with wooProductId, it sends PUT /wp-json/wc/v3/products/{id}. For deleted or unpublished content, you can set status to "draft" instead of deleting the WooCommerce product. The end user then sees the result through your storefront. That might be a WordPress theme reading WooCommerce data, a custom Next.js storefront calling WooCommerce for cart and checkout, or a product detail page that combines Sanity editorial content with WooCommerce price and availability. The trade-off is that you need a clear source-of-truth rule. For example, Sanity owns product storytelling and merchandising copy, while WooCommerce owns price, stock, tax, checkout, and orders.


04Use cases

Common use cases

🛍️

Editorial product detail pages

Use Sanity for rich product copy, buying guides, and image storytelling, then sync core fields to WooCommerce products by SKU.

🏷️

Campaign and sale launches

Publish seasonal product collections in Sanity and update WooCommerce categories, tags, and product visibility when the campaign goes live.

🌎

Localized commerce content

Structure regional product names, descriptions, and care instructions in Sanity, then send the right fields to the matching WooCommerce store.

🤖

Shopping agents with product context

Use Agent Context to let production AI agents answer product questions from structured Sanity content while WooCommerce handles cart and checkout.


05Implementation

Step-by-step integration

  1. 1

    Set up WooCommerce API access

    Install WooCommerce in WordPress, finish the store setup flow, then go to WooCommerce > Settings > Advanced > REST API. Create a key with Read/Write access, copy the consumer key and consumer secret, and store them as environment variables. For Node.js projects, install the official REST API client with npm install @woocommerce/woocommerce-rest-api.

  2. 2

    Model product content in Sanity Studio

    Create a product schema with fields that map cleanly to WooCommerce: sku, title, slug, shortDescription, body, images, category references, tags, status, and wooProductId. Keep commerce-owned fields, like live inventory and order data, in WooCommerce unless you have a specific reason to mirror them.

  3. 3

    Create the sync trigger

    Add a Sanity webhook for create, update, and delete events on product documents, using a GROQ filter such as _type == "product". Point it at a Sanity Function or webhook listener, and include a secret so your endpoint can reject unsigned requests.

  4. 4

    Fetch and map the content

    In your handler, use @sanity/client and GROQ to fetch the full product document by _id. Map Sanity fields to WooCommerce fields, such as name, slug, sku, short_description, description, categories, images, status, and tags.

  5. 5

    Call the WooCommerce REST API

    If the Sanity document already has wooProductId, update that product with the WooCommerce API. If it doesn't, create a product, then write the returned WooCommerce id back to Sanity so future publishes update the same product.

  6. 6

    Test the storefront flow

    Publish a test product, confirm it appears in WooCommerce, check product images and categories, then run a test checkout. If you're building a custom frontend, test both sides: Sanity for editorial content and WooCommerce for price, cart, and checkout.


06Code

Code example

typescriptapi/sync-woocommerce-product.ts
import type { NextApiRequest, NextApiResponse } from 'next'
import { createClient } from '@sanity/client'
import WooCommerceRestApi from '@woocommerce/woocommerce-rest-api'

const sanity = createClient({
  projectId: process.env.SANITY_PROJECT_ID!,
  dataset: process.env.SANITY_DATASET!,
  apiVersion: '2025-01-01',
  token: process.env.SANITY_WRITE_TOKEN!,
  useCdn: false
})

const woo = new WooCommerceRestApi({
  url: process.env.WOO_URL!,
  consumerKey: process.env.WOO_KEY!,
  consumerSecret: process.env.WOO_SECRET!,
  version: 'wc/v3'
})

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.headers['x-sanity-secret'] !== process.env.SANITY_WEBHOOK_SECRET) {
    return res.status(401).json({ ok: false })
  }

  const id = req.body._id
  const product = await sanity.fetch(`*[_id == $id][0]{
    _id, title, sku, slug, shortDescription, body, wooProductId,
    "imageUrls": images[].asset->url,
    categories[]->{title, wooCategoryId}
  }`, { id })

  const payload = {
    name: product.title,
    slug: product.slug.current,
    sku: product.sku,
    short_description: product.shortDescription,
    description: product.body?.[0]?.children?.[0]?.text || '',
    images: (product.imageUrls || []).map((src: string) => ({ src })),
    categories: (product.categories || [])
      .filter((c: any) => c.wooCategoryId)
      .map((c: any) => ({ id: c.wooCategoryId })),
    status: 'publish'
  }

  const response = product.wooProductId
    ? await woo.put(`products/${product.wooProductId}`, payload)
    : await woo.post('products', payload)

  if (!product.wooProductId) {
    await sanity.patch(product._id).set({ wooProductId: response.data.id }).commit()
  }

  return res.status(200).json({ ok: true, wooProductId: response.data.id })
}

07Why Sanity

How Sanity + WooCommerce works

Build your WooCommerce integration on Sanity

Sanity gives you the structured content foundation, real-time event system, and flexible APIs to connect product content with WooCommerce.

Start building free →

08Comparison

CMS approaches to WooCommerce

CapabilityTraditional CMSSanity
Product content modelingProduct copy often lives inside page fields or WordPress editor content, which can make reuse across product pages, guides, and apps harder.Schema-as-code in Sanity Studio lets you model SKUs, product families, fit data, care instructions, bundles, and category references as typed content.
WooCommerce sync timingTeams often update WooCommerce manually or run scheduled jobs that can leave product content out of date for minutes or hours.Webhooks and Functions can trigger on publish events, fetch the latest document, and call the WooCommerce REST API without polling.
Field-level API controlIntegrations may receive full pages or rendered HTML, so the sync layer has to extract the fields WooCommerce needs.GROQ can fetch exact fields and resolve references in one query, such as product data plus category ids, image URLs, and merchandising copy.
Multi-channel commerce deliveryThe website is usually the primary target, and extra channels often need duplicated content or custom exports.The same product content can feed web, mobile, WooCommerce, and production AI agents through Agent Context.
Editorial workflow for commerce teamsMerchandising changes can be tied to page editing, which makes staged launches and review steps harder to coordinate.Sanity Studio can be customized for merchandisers, with fields, previews, validation, Comments, Tasks, Content Releases, and scheduled publishing.

09Next steps

Keep building

Explore related integrations to complete your content stack.

Ready to try Sanity?

See how Sanity's Content Operating System powers integrations with WooCommerce and 200+ other tools.