n8n Shopify Node: Automate Orders, Customers, and Inventory in Your Workflows [Free Workflow JSON]
If you're running a Shopify store, you're already drowning in repetitive tasks: exporting orders to spreadsheets, tagging customers by purchase history, emailing suppliers when stock runs low, and reconciling payments in your accounting tool. The n8n Shopify node connects your store to every other tool in your stack—without middleware, without Zapier's per-task pricing, and without writing custom API code.
This guide covers every Shopify node operation, the six most common gotchas, three production-ready workflow patterns, and a free downloadable JSON you can import directly into n8n.
What the n8n Shopify Node Can Do
The Shopify node in n8n covers the core Shopify Admin REST API resources. Here's what you can read, create, and update:
Orders
- Get Order: fetch a single order by ID
- Get All Orders: list orders with filters (status, date range, fulfillment status, financial status)
- Create Order: programmatically create an order (useful for phone/offline orders)
- Update Order: change tags, notes, or metafields on existing orders
- Delete Order: remove a draft order
Customers
- Get Customer / Get All Customers: retrieve customer records with purchase history
- Create Customer: add new customers to your Shopify CRM
- Update Customer: add tags, notes, addresses, or metafields
- Delete Customer
Products
- Get Product / Get All Products: list products with variant details, inventory levels, images
- Create Product / Update Product / Delete Product
Triggers (Shopify Trigger node)
- Order Created / Updated / Paid / Fulfilled / Cancelled / Partially Fulfilled
- Customer Created / Updated
- Product Created / Updated / Deleted
- Checkout Created / Updated
Prerequisites
- A Shopify store (any plan — even development stores work for testing)
- A Custom App with the scopes your workflow needs
- The Admin API access token from that app
Creating the credential in n8n
- In Shopify Admin: Settings → Apps and sales channels → Develop apps → Create an app
- Configure API scopes:
- Orders:
read_orders,write_orders - Customers:
read_customers,write_customers - Products:
read_products,write_products - Inventory:
read_inventory,write_inventory
- Orders:
- Install the app → copy the Admin API access token (shown only once)
- In n8n: Credentials → New → Shopify API
- Shop subdomain:
your-store(notyour-store.myshopify.com) - Access token: paste the token
- Shop subdomain:
Scope tip: Request only the scopes your workflow actually needs. Shopify logs scope usage — over-permissioned apps get flagged in security reviews.
The Six Gotchas That Will Bite You
1. The API rate limit is 40 requests/second — not per minute
Shopify's REST API uses a leaky-bucket rate limiter: 40 requests/second per store, replenishing at 2/second. For bulk operations (Get All Orders, syncing large product catalogs), n8n will hit this fast. Add a Wait node (500ms–1000ms delay) between batches, or use Split In Batches with a 10-item chunk and a pause. Hitting the limit returns 429 Too Many Requests and n8n will retry — but repeated retries can cascade into longer delays.
2. "Get All" has a default limit of 250 records — pagination is manual
The Shopify node's Get All operation fetches up to 250 records per call and doesn't auto-paginate. For stores with thousands of orders or customers, you need to implement cursor-based pagination manually using page_info from the response headers or switch to the Shopify GraphQL Admin API (via the HTTP Request node) which supports proper pagination. For most small-to-mid stores, 250 is enough for recent records.
3. Order financial_status vs fulfillment_status — they're independent
financial_status (pending, paid, refunded, partially_refunded) and fulfillment_status (fulfilled, partial, unfulfilled) are separate fields. A common mistake: filtering for status=any to get "all paid unfulfilled orders" — this requires filtering on both fields. Use Get All Orders with financial_status=paid and then a Filter node to check fulfillment_status != 'fulfilled'.
4. Webhooks need a public URL — use ngrok or a cloud n8n instance for development
The Shopify Trigger node registers a webhook with Shopify, which requires a publicly reachable URL. localhost:5678 won't work — Shopify can't reach it. Options:
- n8n Cloud: URL is already public
- Self-hosted on a VPS: public IP + the n8n webhook path works
-
Local dev: use ngrok (
ngrok http 5678) — but the tunnel URL changes on restart, which re-registers the webhook
5. Webhook deduplication is your responsibility
Shopify guarantees at-least-once delivery, not exactly-once. During high-traffic events (flash sales, Black Friday), the same order.paid webhook can fire twice. Build deduplication into your workflow: use a Redis Set node or a Google Sheet to check order_id before processing. Without this, you'll send duplicate fulfillment emails, double-count revenue in sheets, or create duplicate CRM records.
6. Customer email is not always present
Guest checkouts in Shopify can produce orders where customer.email is null (the email lives at order.email instead). If your workflow sends confirmation or fulfillment emails, always fall back to {{ $json.order.email || $json.customer.email }} — never assume customer.email is populated.
Pattern 1: Order → Google Sheets Revenue Sync
Use case: Append every paid Shopify order to a Google Sheet for daily revenue tracking without exporting CSVs.
Trigger: Shopify Trigger node → Event: order/paid
Workflow:
Shopify Trigger (order/paid)
→ Set node: extract order_id, created_at, total_price, customer.email, line_items count, financial_status
→ Google Sheets (Append Row): sheet "Orders Log", columns: Date | Order ID | Customer Email | Total | Items | Status
Why it works: The order/paid webhook fires the instant payment is confirmed — not when the order is created (which may be unpaid). This avoids syncing abandoned checkouts or pending orders.
Dedup guard: Add a Google Sheets lookup (Get Row) before the append to check if order_id already exists in column B. If it does, stop execution. This handles Shopify's at-least-once delivery.
Free JSON: [included at end of article]
Pattern 2: Low-Stock Alert → Slack + Supplier Email
Use case: When a product variant drops below a stock threshold, alert the team on Slack and email the supplier automatically.
Trigger: Schedule Trigger → every 6 hours (or Shopify Trigger → product/updated if you want real-time)
Workflow:
Schedule Trigger (every 6h)
→ Shopify (Get All Products): limit=250
→ Split Out (operation: Split Out, field: variants)
→ Filter: inventory_quantity < 10 AND inventory_management == "shopify"
→ IF: no items pass filter → stop
→ Set node: build alert message with title, SKU, quantity, product URL
→ Slack (Send Message): channel #ops, message "⚠️ Low stock: {title} SKU {sku} — {qty} remaining"
→ Gmail (Send Email): to supplier@example.com, subject "Reorder needed: {title}", body with qty + Shopify admin link
Threshold config tip: Store the threshold (10) in a Set node at the top so you can change it without editing the Filter. Or use a Google Sheet as a config store — one row per SKU with its reorder point.
Pattern 3: New Order → CRM Contact Sync + Tag Enrichment
Use case: When a customer places their first order, create or update their record in HubSpot (or Airtable), add a "buyer" tag in Shopify, and trigger a post-purchase email sequence in Brevo.
Trigger: Shopify Trigger → order/paid
Workflow:
Shopify Trigger (order/paid)
→ IF: customer.orders_count == 1 (first-time buyer)
YES →
→ HubSpot (Create/Update Contact): email, first/last name, "buyer" lifecycle stage
→ Shopify (Update Customer): add tag "buyer-first-order"
→ Brevo (Add Contact to List): list "post-purchase-sequence-new"
NO → (repeat buyer path)
→ HubSpot (Update Contact): increment purchase_count property
→ IF: orders_count == 3
YES → Shopify (Update Customer): add tag "loyal-customer"
YES → Brevo (Add to List): "vip-sequence"
Why tag in Shopify too: Tags in Shopify make it easy to segment customers for future discount campaigns directly inside Shopify without needing to query your CRM.
Shopify Node vs HTTP Request Node (GraphQL)
| Capability | Shopify Node | HTTP Request (GraphQL) |
|---|---|---|
| Setup complexity | Low — credential + select operation | Medium — GraphQL query syntax |
| Pagination | Manual (250/page limit) | Cursor-based (proper pagination) |
| Bulk exports (10K+ records) | Impractical | ✅ via Bulk Operations API |
| Metafields | Limited | ✅ Full access |
| Custom storefronts | ❌ | ✅ Storefront API |
| Best for | Triggers + small CRUD ops | Large catalog syncs, complex queries |
For most automation workflows (order events, customer tagging, stock checks), the native Shopify node is sufficient. Switch to GraphQL via HTTP Request only when you need bulk exports or metafield depth.
Free Workflow JSON
Import this directly into n8n (Settings → Import from clipboard):
{
"name": "Shopify Order Revenue Sync + Low Stock Alert",
"nodes": [
{
"parameters": {
"event": "order/paid"
},
"name": "Shopify Trigger",
"type": "n8n-nodes-base.shopifyTrigger",
"typeVersion": 1,
"position": [250, 300]
},
{
"parameters": {
"assignments": {
"assignments": [
{ "name": "order_id", "value": "={{ $json.id }}", "type": "string" },
{ "name": "created_at", "value": "={{ $json.created_at }}", "type": "string" },
{ "name": "total_price", "value": "={{ $json.total_price }}", "type": "string" },
{ "name": "customer_email", "value": "={{ $json.email }}", "type": "string" },
{ "name": "item_count", "value": "={{ $json.line_items.length }}", "type": "number" },
{ "name": "financial_status", "value": "={{ $json.financial_status }}", "type": "string" }
]
}
},
"name": "Extract Fields",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [450, 300]
},
{
"parameters": {
"operation": "append",
"documentId": { "__rl": true, "mode": "list", "value": "YOUR_SHEET_ID" },
"sheetName": { "__rl": true, "mode": "list", "value": "Orders Log" },
"columns": {
"mappingMode": "defineBelow",
"value": {
"Date": "={{ $json.created_at }}",
"Order ID": "={{ $json.order_id }}",
"Customer Email": "={{ $json.customer_email }}",
"Total": "={{ $json.total_price }}",
"Items": "={{ $json.item_count }}",
"Status": "={{ $json.financial_status }}"
}
}
},
"name": "Log to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [650, 300]
}
],
"connections": {
"Shopify Trigger": { "main": [[{ "node": "Extract Fields", "type": "main", "index": 0 }]] },
"Extract Fields": { "main": [[{ "node": "Log to Google Sheets", "type": "main", "index": 0 }]] }
}
}
Replace
YOUR_SHEET_IDwith your Google Sheets document ID. Add a Google Sheets credential and a Shopify API credential before running.
Where to Go From Here
The Shopify node handles the most common e-commerce automations well. For production stores, consider these additions:
-
Inventory webhooks (
inventory_levels/update) for real-time stock alerts instead of polling - Fulfillment automation: when an order is marked paid, trigger a fulfillment request to your 3PL via HTTP Request
-
Abandoned checkout recovery: use the
checkouts/createtrigger to start a Brevo sequence for carts left behind - Metafield sync: use the HTTP Request node (GraphQL) to read/write product metafields for custom attribute management
Get the Pre-Built n8n Workflow Pack
The free JSON above gives you the basics. If you want a complete Shopify automation bundle — order sync, customer tagging, low-stock alerts, and post-purchase sequences — all pre-wired and documented:
👉 n8n Workflow Starter Pack ($29) — pirateprentice.gumroad.com/l/sxcoe
Or if you'd rather have it built specifically for your store:
👉 Done-For-You n8n Workflow Build ($99) — buy.stripe.com/4gMdRaetT3Yv3yxbOs2go03
Send your store setup and what you want automated — I'll deliver a working n8n workflow within 48 hours.
Top comments (1)
Are you using the Shopify node to sync orders into a spreadsheet, trigger low-stock alerts, or push new customers into your CRM? Drop your use case in the comments — always curious what automation people are building on top of Shopify.