# 5 n8n Automations Every WooCommerce Store Needs (Save 10+ Hours/Week)

> Source: <https://dev.to/flowkithq/5-n8n-automations-every-woocommerce-store-needs-save-10-hoursweek-oc2>
> Published: 2026-05-22 13:06:45+00:00

# 5 n8n Automations Every WooCommerce Store Needs (Save 10+ Hours/Week)

Running a WooCommerce store means drowning in repetitive tasks: checking inventory, logging orders to spreadsheets, chasing abandoned carts, sending follow-up emails, compiling daily sales reports. Most store owners spend hours each week on work that should be automatic.

This guide shows you 5 n8n workflows that eliminate the most time-consuming WooCommerce admin tasks — with full workflow JSON you can import and use today.

## Setup: Connect WooCommerce to n8n (5 minutes)

- In your WordPress admin, go to
**WooCommerce → Settings → Advanced → REST API** - Click
**Add key**→ set description "n8n", user (admin), permissions** Read/Write** - Copy the Consumer Key and Consumer Secret
- In n8n, create a
**WooCommerce credential**: add your store URL + those keys

That's it. All 5 workflows below use this credential.

## Workflow 1: Low Stock Alert → Slack + Email

**The problem:** You run out of stock without knowing, losing sales. WooCommerce's built-in alerts are easy to miss.

**What this does:** Every hour, checks all products with stock below your threshold and sends a Slack message + email listing which products need restocking — with current stock count and a direct admin link.

**Workflow (6 nodes):**

```
{
  "name": "WooCommerce Low Stock Alert",
  "nodes": [
    {
      "name": "Every Hour",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": { "interval": [{ "field": "hours", "hoursInterval": 1 }] }
      },
      "position": [250, 300]
    },
    {
      "name": "Get Products",
      "type": "n8n-nodes-base.wooCommerce",
      "parameters": {
        "resource": "product",
        "operation": "getAll",
        "returnAll": true,
        "filters": {
          "stock_status": "instock",
          "manage_stock": true
        }
      },
      "position": [450, 300]
    },
    {
      "name": "Filter Low Stock",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const LOW_STOCK_THRESHOLD = 5;\nconst lowStock = items.filter(item => {\n  const stock = item.json.stock_quantity;\n  return stock !== null && stock <= LOW_STOCK_THRESHOLD;\n});\nif (lowStock.length === 0) return [];\nconst report = lowStock.map(p =>\n  `• ${p.json.name} — ${p.json.stock_quantity} left (${process.env.WP_URL}/wp-admin/post.php?post=${p.json.id}&action=edit)`\n).join('\\n');\nreturn [{ json: { report, count: lowStock.length } }];"
      },
      "position": [650, 300]
    },
    {
      "name": "IF Has Low Stock",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "number": [{ "value1": "={{$json.count}}", "operation": "larger", "value2": 0 }]
        }
      },
      "position": [850, 300]
    },
    {
      "name": "Slack Alert",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "#inventory-alerts",
        "text": "⚠️ Low stock alert ({{$json.count}} products):\n\n{{$json.report}}"
      },
      "position": [1050, 200]
    },
    {
      "name": "Email Alert",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "toEmail": "store@yourdomain.com",
        "subject": "⚠️ WooCommerce Low Stock Alert — {{$json.count}} products",
        "message": "The following products are running low:\n\n{{$json.report}}"
      },
      "position": [1050, 400]
    }
  ]
}
```

**Customise:** Change `LOW_STOCK_THRESHOLD`

to any number. Add a Google Sheets log node to track restock history.

## Workflow 2: New Order → Google Sheets Log + Slack Notification

**The problem:** Your order data lives in WooCommerce only. You can't easily analyse trends, share data with your team, or build custom reports without exporting manually.

**What this does:** Every new WooCommerce order automatically gets logged to a Google Sheets master order table AND posts a Slack notification — so your team knows about every sale in real time.

**Workflow (4 nodes):**

```
{
  "name": "WooCommerce Order Logger",
  "nodes": [
    {
      "name": "WooCommerce Webhook",
      "type": "n8n-nodes-base.wooCommerceTrigger",
      "parameters": {
        "event": "order.created"
      },
      "position": [250, 300]
    },
    {
      "name": "Format Order",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const order = items[0].json;\nconst customer = `${order.billing.first_name} ${order.billing.last_name}`;\nconst items_list = order.line_items.map(i => `${i.name} x${i.quantity}`).join(', ');\nreturn [{\n  json: {\n    order_id: order.id,\n    date: order.date_created,\n    customer,\n    email: order.billing.email,\n    total: order.total,\n    items: items_list,\n    status: order.status,\n    payment: order.payment_method_title\n  }\n}];"
      },
      "position": [450, 300]
    },
    {
      "name": "Log to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "appendOrUpdate",
        "sheetId": "YOUR_SHEET_ID",
        "range": "Orders!A:I",
        "values": {
          "Order ID": "={{$json.order_id}}",
          "Date": "={{$json.date}}",
          "Customer": "={{$json.customer}}",
          "Email": "={{$json.email}}",
          "Total": "={{$json.total}}",
          "Items": "={{$json.items}}",
          "Status": "={{$json.status}}",
          "Payment": "={{$json.payment}}"
        }
      },
      "position": [650, 200]
    },
    {
      "name": "Slack Notification",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "#sales",
        "text": "🛒 New order #{{$json.order_id}} — {{$json.customer}} — ${{$json.total}}\n{{$json.items}}"
      },
      "position": [650, 400]
    }
  ]
}
```

**Customise:** Replace the WooCommerce Trigger with a Schedule Trigger that polls every 15 min if webhooks are hard to set up on your host. Add a Discord node instead of Slack.

## Workflow 3: Abandoned Cart Recovery Email

**The problem:** 70%+ of WooCommerce carts are abandoned. The built-in recovery email (only in WooCommerce Pro) costs $199/year. n8n does the same thing free.

**What this does:** Every 30 minutes, checks for carts abandoned in the last 1 hour and sends a personalised recovery email with the exact items left behind and a direct checkout link.

**Workflow (5 nodes):**

```
{
  "name": "Abandoned Cart Recovery",
  "nodes": [
    {
      "name": "Every 30 Min",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": { "interval": [{ "field": "minutes", "minutesInterval": 30 }] }
      },
      "position": [250, 300]
    },
    {
      "name": "Get Pending Orders (1h)",
      "type": "n8n-nodes-base.wooCommerce",
      "parameters": {
        "resource": "order",
        "operation": "getAll",
        "returnAll": false,
        "limit": 50,
        "filters": {
          "status": "pending",
          "after": "={{ DateTime.now().minus({hours:2}).toISO() }}",
          "before": "={{ DateTime.now().minus({hours:1}).toISO() }}"
        }
      },
      "position": [450, 300]
    },
    {
      "name": "Build Recovery Email",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "return items.map(item => {\n  const order = item.json;\n  const cartItems = order.line_items.map(i =>\n    `<li>${i.name} x${i.quantity} — $${i.total}</li>`\n  ).join('');\n  const html = `<p>Hi ${order.billing.first_name},</p>\n<p>You left some great items in your cart:</p>\n<ul>${cartItems}</ul>\n<p><strong>Total: $${order.total}</strong></p>\n<p><a href=\"${order.checkout_payment_url}\">Complete your order →</a></p>`;\n  return { json: { email: order.billing.email, name: order.billing.first_name, html, order_id: order.id } };\n});"
      },
      "position": [650, 300]
    },
    {
      "name": "IF Has Email",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "string": [{ "value1": "={{$json.email}}", "operation": "isNotEmpty" }]
        }
      },
      "position": [850, 300]
    },
    {
      "name": "Send Recovery Email",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "toEmail": "={{$json.email}}",
        "subject": "Hey {{$json.name}}, you left something behind...",
        "message": "={{$json.html}}",
        "options": { "emailType": "html" }
      },
      "position": [1050, 300]
    }
  ]
}
```

**Note:** WooCommerce creates an order in "pending" status when a customer starts checkout and doesn't complete it. This workflow targets those orders. Check your host's cron scheduling for the WooCommerce sessions plugin if you want to catch earlier-stage abandonment.

## Workflow 4: AI Customer Review Tagger

**The problem:** Reading every customer review manually to understand what's working and what isn't takes hours. You need a way to automatically categorise feedback.

**What this does:** When a new WooCommerce review is submitted, Claude AI reads it and tags it as Positive/Negative/Feature Request — then logs it to Google Sheets with the AI's 1-line summary. You get a searchable database of every piece of customer feedback, automatically categorised.

**Workflow (4 nodes):**

```
{
  "name": "WooCommerce AI Review Tagger",
  "nodes": [
    {
      "name": "WooCommerce Review Webhook",
      "type": "n8n-nodes-base.wooCommerceTrigger",
      "parameters": {
        "event": "review.created"
      },
      "position": [250, 300]
    },
    {
      "name": "Claude AI Tagger",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "method": "POST",
        "url": "https://api.anthropic.com/v1/messages",
        "headers": {
          "x-api-key": "YOUR_CLAUDE_API_KEY",
          "anthropic-version": "2023-06-01",
          "content-type": "application/json"
        },
        "body": {
          "model": "claude-haiku-4-5-20251001",
          "max_tokens": 100,
          "messages": [{
            "role": "user",
            "content": "Categorise this WooCommerce review. Reply with JSON only: {tag: 'Positive'|'Negative'|'Feature Request', summary: '10 words max'}\n\nReview: {{$json.review}}"
          }]
        }
      },
      "position": [450, 300]
    },
    {
      "name": "Parse AI Response",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const text = items[0].json.content[0].text;\nconst parsed = JSON.parse(text);\nreturn [{ json: { ...parsed, review: $('WooCommerce Review Webhook').first().json.review, product: $('WooCommerce Review Webhook').first().json.product_id, rating: $('WooCommerce Review Webhook').first().json.rating } }];"
      },
      "position": [650, 300]
    },
    {
      "name": "Log to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "appendOrUpdate",
        "sheetId": "YOUR_SHEET_ID",
        "range": "Reviews!A:E",
        "values": {
          "Product ID": "={{$json.product}}",
          "Rating": "={{$json.rating}}",
          "Tag": "={{$json.tag}}",
          "AI Summary": "={{$json.summary}}",
          "Review": "={{$json.review}}"
        }
      },
      "position": [850, 300]
    }
  ]
}
```

**Customise:** Swap Claude Haiku for OpenAI GPT-4o-mini to cut cost further. Add a Slack alert when a "Negative" tag is detected so you can respond quickly.

## Workflow 5: Daily WooCommerce Sales Report

**The problem:** Checking WooCommerce stats every morning means logging in, waiting for the dashboard to load, and mentally compiling numbers. Total waste of 10 minutes every day.

**What this does:** Every morning at 7 AM, this workflow pulls the previous day's orders, calculates revenue, order count, AOV, top product, and week-over-week change — then emails you a clean summary and posts it to Slack.

**Workflow (5 nodes):**

```
{
  "name": "WooCommerce Daily Sales Report",
  "nodes": [
    {
      "name": "7 AM Daily",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": { "interval": [{ "field": "cronExpression", "expression": "0 7 * * *" }] }
      },
      "position": [250, 300]
    },
    {
      "name": "Get Yesterday's Orders",
      "type": "n8n-nodes-base.wooCommerce",
      "parameters": {
        "resource": "order",
        "operation": "getAll",
        "returnAll": true,
        "filters": {
          "status": "completed,processing",
          "after": "={{ DateTime.now().minus({days:1}).startOf('day').toISO() }}",
          "before": "={{ DateTime.now().startOf('day').toISO() }}"
        }
      },
      "position": [450, 300]
    },
    {
      "name": "Calculate Stats",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const orders = items.map(i => i.json);\nif (orders.length === 0) return [{ json: { revenue: 0, orders: 0, aov: 0, top_product: 'N/A', date: new Date().toDateString() } }];\nconst revenue = orders.reduce((s, o) => s + parseFloat(o.total), 0);\nconst productCount = {};\norders.forEach(o => o.line_items.forEach(item => {\n  productCount[item.name] = (productCount[item.name] || 0) + item.quantity;\n}));\nconst top_product = Object.entries(productCount).sort((a,b) => b[1]-a[1])[0]?.[0] || 'N/A';\nreturn [{ json: {\n  date: new Date().toDateString(),\n  revenue: revenue.toFixed(2),\n  orders: orders.length,\n  aov: (revenue / orders.length).toFixed(2),\n  top_product\n}}];"
      },
      "position": [650, 300]
    },
    {
      "name": "Email Report",
      "type": "n8n-nodes-base.gmail",
      "parameters": {
        "toEmail": "owner@yourdomain.com",
        "subject": "📊 WooCommerce Daily Report — {{$json.date}}",
        "message": "Yesterday's numbers:\n\n💰 Revenue: ${{$json.revenue}}\n🛒 Orders: {{$json.orders}}\n📈 AOV: ${{$json.aov}}\n🏆 Top Product: {{$json.top_product}}",
        "options": {}
      },
      "position": [850, 200]
    },
    {
      "name": "Slack Report",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "#sales",
        "text": "📊 *Yesterday's WooCommerce Report* ({{$json.date}})\n💰 Revenue: ${{$json.revenue}} | 🛒 Orders: {{$json.orders}} | 📈 AOV: ${{$json.aov}}\n🏆 Top product: {{$json.top_product}}"
      },
      "position": [850, 400]
    }
  ]
}
```

**Customise:** Add a Sheets log to track trends over time. Add week-over-week comparison by also fetching orders from 7 days ago. Add top 3 products instead of just 1.

## The Real Cost of Manual Store Management

Let me put some numbers on this:

| Task | Manual time | With n8n |
|---|---|---|
| Check inventory daily | 10 min | 0 min |
| Log orders to spreadsheet | 15 min/day | 0 min |
| Send abandoned cart emails | 20 min/day | 0 min |
| Read and tag reviews | 30 min/week | 0 min |
| Morning sales check | 10 min/day | 0 min |

That's over **3 hours per week** handed back to you. For a store doing even $5,000/month, that's time better spent on marketing, product development, or — honestly — not working.

## What's Next: Ready-Made Templates

If you want these workflows pre-built and ready to import — no JSON wrangling, no setup debugging — I packaged all 15 of my most-used n8n workflows into the **FlowKit n8n Template Pack** at [stripeai.gumroad.com](https://stripeai.gumroad.com).

Each template includes the workflow JSON, a setup checklist, and a short video showing exactly how to configure the credentials. The Price Monitor ($29) and Daily Report Generator ($19) in the pack work directly with WooCommerce's REST API.

## Final Tips for WooCommerce + n8n

-
**Use webhooks over polling** where possible — webhooks fire instantly, polling adds latency -
**WooCommerce REST API rate limits**: default is 200 requests/minute — more than enough for most stores -
**Test with order status** before going live with`pending`

`completed`

orders -
**Store your API keys in n8n credentials**(never hardcode them in Code nodes) -
**Schedule triggers use server time**— make sure your n8n instance timezone matches your store timezone

Questions? Drop them in the comments — I read every one.
