Automating WooCommerce with n8n lets you connect your WordPress store to your tools without writing a custom plugin or paying a subscription per integration. Here are 5 concrete n8n workflows, wired to the REST API and webhooks, with their trigger, logic, and the time they save.
I'm Tommy Bordas, a full-stack developer in Nantes (10+ years, freelance via Sumotori). I've been setting up this kind of automation for WooCommerce merchants for years, and the conclusion is always the same: the value isn't in one more plugin, it's in the orchestration. Let's see how to lay this down properly.
Why n8n instead of stacking SaaS plugins
WooCommerce exposes two often-underused entry points: a full REST API (/wp-json/wc/v3/...) to read and write orders, products, stock and customers; and native webhooks that push an event (order.created, order.updated, product.updated...) to a URL the moment it happens. n8n, an open-source automation tool you can self-host, plugs straight into both: it receives the webhooks and calls the API back.
The usual reflex is to install one plugin per need: one for abandoned carts, one for stock sync, one for reviews... Each one adds code inside WordPress, hooks that run on every request, and an extra attack surface. n8n moves all that logic out of WordPress.
| Approach | Cost | Maintenance | Flexibility | WordPress perf impact |
|---|---|---|---|---|
| SaaS plugin per integration | Subscription × N | External, opaque | Limited to plugin scope | Load on every request |
| Custom plugin | Dev + maintenance | On you | Full | Load on every request |
| Self-hosted n8n | Hosting only (~€5/mo) | Centralized, one place | Full | Near zero (logic offloaded) |
Takeaway: every third-party plugin adds weight and a potential vulnerability. n8n centralizes integration logic off the WordPress server, keeping the site lean and maintenance readable: one place to audit instead of ten plugins.
How WooCommerce connects to n8n
Two mechanisms, two uses:
- Webhook (push, real time): WooCommerce calls an n8n URL as soon as an event happens. Ideal for reacting fast: order paid, status changed. Set it up in WooCommerce → Settings → Advanced → Webhooks, or via code.
- REST API (pull, on demand): n8n queries WooCommerce whenever it wants, using an API key (Consumer Key/Secret generated in WooCommerce → Settings → Advanced → REST API). Ideal for scheduled processing: list carts, bulk-update stock.
To register a webhook via code in functions.php (or a small custom plugin):
add_action( 'woocommerce_init', function () {
if ( ! function_exists( 'wc_get_webhook' ) ) {
return;
}
// Created once, idempotent: don't duplicate if the URL already exists.
$existing = wc_get_webhooks( [ 'search' => 'n8n-order-paid' ] );
if ( ! empty( $existing ) ) {
return;
}
$webhook = new WC_Webhook();
$webhook->set_name( 'n8n-order-paid' );
$webhook->set_topic( 'order.updated' );
$webhook->set_delivery_url( 'https://n8n.example.com/webhook/wc-order' );
$webhook->set_secret( getenv( 'N8N_WC_SECRET' ) ); // used to sign the payload
$webhook->set_status( 'active' );
$webhook->save();
} );
The secret is crucial: WooCommerce uses it to sign every delivery (header X-WC-Webhook-Signature). You verify that signature in n8n (more on that in the best practices).
Workflow #1: abandoned cart recovery
The ROI classic. An abandoned cart is a customer one click from buying. A cron checks carts inactive for over an hour and triggers a personalized recovery email with the cart contents.
Trigger: Schedule node every 30 minutes. Gain: 5-15% of "lost" revenue recovered, with no manual work.
{
"trigger": "Schedule (every 30 min)",
"steps": [
"HTTP Request: GET /wp-json/wc/v3/orders?status=pending&after={{1h ago}}",
"Filter: email present AND meta 'reminder_sent' absent",
"Send Email: recovery with cart recap + resume link",
"HTTP Request: PUT /orders/{{id}} → meta_data 'reminder_sent' = now"
]
}
Takeaway: send the reminder only once, and track it with a meta on the order. Without this guard, a customer can get the same reminder every 30 minutes, the opposite of the intended effect.
Workflow #2: supplier stock sync via CSV
Your supplier publishes a stock CSV every night (FTP, email, or URL). n8n fetches it, parses it, maps it onto WooCommerce SKUs and bulk-updates quantities. No more manual re-entry or phantom stockouts.
Trigger: nightly Schedule (e.g. 4:00 AM) or Email Trigger when the supplier sends the file. Gain: removes manual re-entry (often 1-2 hours a day) and reliable stock by morning.
// Function node: map a CSV row → WooCommerce update payload
return items.map((item) => {
const qty = parseInt(item.json["Qty available"], 10) || 0;
return {
json: {
sku: String(item.json["Reference"]).trim(),
stock_quantity: qty,
stock_status: qty > 0 ? "instock" : "outofstock",
manage_stock: true,
},
};
});
WooCommerce doesn't let you write a product by SKU directly: first resolve the SKU to a product_id, then use the batch endpoint to limit the number of calls.
# Grouped update: 1 request for 100 products instead of 100 requests
curl -X POST "https://store.com/wp-json/wc/v3/products/batch" \
-u "$WC_KEY:$WC_SECRET" \
-H "Content-Type: application/json" \
-d '{ "update": [
{ "id": 412, "stock_quantity": 12, "stock_status": "instock" },
{ "id": 588, "stock_quantity": 0, "stock_status": "outofstock" }
] }'
Workflow #3: automatic invoice to accounting
On every paid order, a WooCommerce webhook triggers invoice creation in your accounting tool (QuickBooks, Xero, FreshBooks...), archives it and sends it to the customer.
Trigger: order.updated webhook filtered on status = processing or completed.
Gain: books always up to date, zero misses, no PDF generated by hand.
WooCommerce (webhook order.updated, status=processing)
→ HMAC signature check (shared secret)
→ Idempotency: invoice already created for this order_id? → stop if yes
→ Map order → accounting API schema
→ POST invoice (accounting API) → get the PDF URL
→ Customer email with PDF + Drive/S3 archive
→ PUT /orders/{{id}} → meta 'invoice_id' (trace + idempotency)
The invoice_id meta set on the order plays a double role: it links the invoice to the order and acts as an idempotency lock. If the webhook arrives twice (it happens), the second pass sees the meta and stops.
Workflow #4: review request at the right moment
Asking for a review too early is pointless: the customer hasn't received the product yet. This workflow waits for the order to become "completed" (a proxy for delivery), leaves 3 days, then sends a targeted review request with the product link.
Trigger: order.updated webhook, filtered on status = completed.
Gain: a markedly higher response rate, meaning more qualified reviews and social proof.
{
"trigger": "WooCommerce webhook: order.status = completed",
"steps": [
"Wait: 3 days",
"HTTP Request: confirm status is still 'completed' (no return/refund)",
"Send Email: review request with product link + light incentive",
"If click: tag customer 'potential_advocate'"
]
}
Takeaway: re-check the order status after the wait. Between the trigger and the send, a return or refund may have happened. Asking for a review then is counterproductive.
Workflow #5: low-stock alert on Slack
When a best-seller drops below a threshold, the team is notified instantly on Slack, before the stockout, not after. You avoid the "surprise stockout" on the product that drives revenue.
Trigger: product.updated webhook (reactive), or hourly Schedule that sweeps products under threshold.
Gain: zero surprise stockouts on critical SKUs, restock triggered in time.
// Function node: keep only products below the defined threshold
const THRESHOLD = 5;
return items
.filter((i) => i.json.manage_stock && i.json.stock_quantity <= THRESHOLD)
.map((i) => ({
json: {
sku: i.json.sku,
name: i.json.name,
stock: i.json.stock_quantity,
url: i.json.permalink,
},
}));
// → Slack node: ":warning: Low stock - {{name}} ({{sku}}): {{stock}} left"
Recap: trigger → gain
| Workflow | Trigger | Mechanism | Gain |
|---|---|---|---|
| Abandoned cart | Cron 30 min | REST API (pull) | Recovered revenue (5-15%) |
| Stock sync | Nightly CSV | Schedule + batch API | No more re-entry |
| Invoicing | order.updated webhook |
Webhook (push) | Books up to date, zero misses |
| Review request | completed webhook + delay |
Webhook + Wait | More qualified reviews |
| Stockout alert | product.updated / threshold |
Webhook or Schedule | No surprise stockouts |
Best practices for reliable workflows
A workflow that works in a demo and a workflow that runs in production for six months unattended are two different things. Here's what I apply every time.
Secure webhooks with signature and secret
A public webhook URL is an open door if it isn't authenticated. WooCommerce signs every delivery with the secret via the X-WC-Webhook-Signature header (HMAC-SHA256 of the body, base64-encoded). Verify it in a Function node at the top of the workflow, and reject anything that doesn't match.
// Function node (very start of the workflow): verify the WooCommerce signature
const crypto = require("crypto");
const secret = $env.N8N_WC_SECRET;
const rawBody = $json.body; // raw body received
const received = $headers["x-wc-webhook-signature"];
const expected = crypto
.createHmac("sha256", secret)
.update(JSON.stringify(rawBody), "utf8")
.digest("base64");
if (received !== expected) {
throw new Error("Invalid webhook signature - request rejected");
}
return items;
Make every workflow idempotent
A webhook can arrive twice (network retry, double click, WooCommerce redelivery). Without a guard, you create two invoices or send two emails. The fix: set a trace meta on the order (invoice_id, reminder_sent) and check for it before acting. The idempotency key is order_id + action type.
Log executions and alert on failures
Enable execution history in n8n and wire an error workflow (Error Trigger) that notifies Slack or email the moment an execution fails. Without it, an integration can break silently for weeks, and you only find out when the customer complains.
Version workflows in Git
n8n workflows export to JSON. Commit them to a Git repo: you keep history, you can review changes in a PR, and you can roll back after a mistake. It's also what lets you rebuild the instance identically after a server crash.
Pre-production checklist
- HMAC signature verified on all incoming webhooks.
- Secret and API keys stored in environment variables, never hardcoded in a node.
- Idempotency guaranteed (trace meta or unique key per action).
- Global error workflow wired to Slack/email.
- API calls in batch mode when volume warrants it.
- Workflows exported to JSON and versioned in Git.
- Retry with back-off configured on critical HTTP nodes.
Going further
On connector and integration logic for WooCommerce (ERP, CRM, marketplaces), see also: WooCommerce connectors and integrations.
Want to automate your WooCommerce store and free up time on repetitive tasks, without bloating WordPress? Let's talk about your workflows.