The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "07 - Shopify Order \u2192 Fulfillment + Thank You Email",
"nodes": [
{
"parameters": {
"topic": "orders/create",
"options": {}
},
"id": "node-shopify-trigger",
"name": "Shopify - New Order",
"type": "n8n-nodes-base.shopifyTrigger",
"typeVersion": 1,
"position": [
260,
300
],
"credentials": {
"shopifyApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const order = $input.first().json;\n\nconst lineItems = (order.line_items || []).map(item => ({\n name: item.name,\n quantity: item.quantity,\n price: parseFloat(item.price),\n sku: item.sku || '',\n requiresShipping: item.requires_shipping !== false,\n vendor: item.vendor || ''\n}));\n\nconst shippingAddress = order.shipping_address || order.billing_address || {};\nconst requiresFulfillment = lineItems.some(i => i.requiresShipping);\nconst isDigitalOnly = lineItems.every(i => !i.requiresShipping);\n\nconst itemsHtml = lineItems.map(item =>\n `<tr>\n <td style=\"padding:8px 12px;\">${item.name}</td>\n <td style=\"padding:8px 12px; text-align:center;\">${item.quantity}</td>\n <td style=\"padding:8px 12px; text-align:right;\">$${(item.price * item.quantity).toFixed(2)}</td>\n </tr>`\n).join('');\n\nreturn [{\n json: {\n orderId: order.id,\n orderName: order.name,\n orderNumber: order.order_number,\n email: order.email,\n firstName: order.customer?.first_name || shippingAddress.first_name || 'Customer',\n lastName: order.customer?.last_name || shippingAddress.last_name || '',\n phone: order.customer?.phone || shippingAddress.phone || '',\n totalPrice: parseFloat(order.total_price || 0).toFixed(2),\n subtotalPrice: parseFloat(order.subtotal_price || 0).toFixed(2),\n shippingPrice: parseFloat(order.total_shipping_price_set?.shop_money?.amount || 0).toFixed(2),\n currency: order.currency || 'USD',\n paymentStatus: order.financial_status,\n fulfillmentStatus: order.fulfillment_status || 'unfulfilled',\n requiresFulfillment,\n isDigitalOnly,\n shippingName: [shippingAddress.first_name, shippingAddress.last_name].join(' ').trim(),\n shippingStreet: shippingAddress.address1 || '',\n shippingCity: shippingAddress.city || '',\n shippingProvince: shippingAddress.province || '',\n shippingZip: shippingAddress.zip || '',\n shippingCountry: shippingAddress.country || '',\n lineItems,\n itemsHtml,\n itemCount: lineItems.reduce((s, i) => s + i.quantity, 0),\n tags: order.tags || '',\n createdAt: order.created_at\n }\n}];"
},
"id": "node-parse-order",
"name": "Code - Parse Order Data",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
480,
300
]
},
{
"parameters": {
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.requiresFulfillment }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
},
{
"leftValue": "={{ $json.paymentStatus }}",
"rightValue": "paid",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
}
},
"id": "node-if-needs-shipping",
"name": "IF - Paid & Needs Shipping?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
700,
300
]
},
{
"parameters": {
"resource": "fulfillmentOrder",
"operation": "create",
"orderId": "={{ $json.orderId }}",
"additionalFields": {
"notifyCustomer": true,
"trackingInfo": {
"trackingInfoDetails": {
"company": "Standard Shipping",
"number": "",
"url": ""
}
}
}
},
"id": "node-shopify-fulfill",
"name": "Shopify - Create Fulfillment",
"type": "n8n-nodes-base.shopify",
"typeVersion": 1,
"position": [
920,
180
],
"credentials": {
"shopifyApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"sendTo": "={{ $('Code - Parse Order Data').item.json.email }}",
"subject": "Thank you for your order, {{ $('Code - Parse Order Data').item.json.firstName }}! \ud83c\udf89 Order {{ $('Code - Parse Order Data').item.json.orderName }}",
"message": "<html><body style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; color: #333;\">\n<div style=\"background: #1a1a2e; padding: 24px; text-align: center; border-radius: 8px 8px 0 0;\">\n <h1 style=\"color: white; margin: 0;\">Order Confirmed! \ud83c\udf89</h1>\n <p style=\"color: #c7d2fe; margin: 8px 0 0;\">{{ $('Code - Parse Order Data').item.json.orderName }}</p>\n</div>\n<div style=\"padding: 24px; background: #f9fafb;\">\n <p>Hey {{ $('Code - Parse Order Data').item.json.firstName }},</p>\n <p>Thank you so much for your order! We're getting it ready and will notify you when it ships.</p>\n\n <h3 style=\"border-bottom: 2px solid #e5e7eb; padding-bottom: 8px;\">Order Summary</h3>\n <table style=\"width:100%; border-collapse:collapse; background:white; border-radius:8px; overflow:hidden;\">\n <thead><tr style=\"background:#4f46e5; color:white;\">\n <th style=\"padding:10px 12px; text-align:left;\">Item</th>\n <th style=\"padding:10px 12px; text-align:center;\">Qty</th>\n <th style=\"padding:10px 12px; text-align:right;\">Price</th>\n </tr></thead>\n <tbody>{{ $('Code - Parse Order Data').item.json.itemsHtml }}</tbody>\n <tfoot>\n <tr style=\"border-top:2px solid #e5e7eb;\">\n <td colspan=\"2\" style=\"padding:10px 12px; text-align:right;\"><strong>Total:</strong></td>\n <td style=\"padding:10px 12px; text-align:right;\"><strong>${{ $('Code - Parse Order Data').item.json.totalPrice }} {{ $('Code - Parse Order Data').item.json.currency }}</strong></td>\n </tr>\n </tfoot>\n </table>\n\n {{ $('Code - Parse Order Data').item.json.requiresFulfillment ? '<h3 style=\"margin-top:24px;\">Shipping To</h3><p>' + $('Code - Parse Order Data').item.json.shippingStreet + '<br>' + $('Code - Parse Order Data').item.json.shippingCity + ', ' + $('Code - Parse Order Data').item.json.shippingProvince + ' ' + $('Code - Parse Order Data').item.json.shippingZip + '</p>' : '<p><strong>Your digital items are ready to access in your account.</strong></p>' }}\n\n <p style=\"margin-top:24px;\">Questions? Reply to this email or visit our <a href=\"https://yourstore.com/help\">Help Center</a>.</p>\n <p>With gratitude,<br><strong>Your Store Team</strong></p>\n</div>\n</body></html>",
"options": {}
},
"id": "node-gmail-thanks",
"name": "Gmail - Thank You Email",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
920,
420
],
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Shopify - New Order": {
"main": [
[
{
"node": "Code - Parse Order Data",
"type": "main",
"index": 0
}
]
]
},
"Code - Parse Order Data": {
"main": [
[
{
"node": "IF - Paid & Needs Shipping?",
"type": "main",
"index": 0
}
]
]
},
"IF - Paid & Needs Shipping?": {
"main": [
[
{
"node": "Shopify - Create Fulfillment",
"type": "main",
"index": 0
},
{
"node": "Gmail - Thank You Email",
"type": "main",
"index": 0
}
],
[
{
"node": "Gmail - Thank You Email",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"tags": [
{
"name": "shopify"
},
{
"name": "ecommerce"
},
{
"name": "fulfillment"
}
],
"meta": {
"description": "Triggers on new Shopify orders, parses all order details, checks if items need physical shipping and payment is confirmed, then auto-creates fulfillment and sends a branded thank-you email.",
"prerequisites": [
"Shopify API credentials (Private App or Custom App)",
"Gmail OAuth2 credentials",
"Shopify webhook configured for orders/create topic",
"Update email template with your store name/URL"
],
"testingScenario": {
"happy_path": "Create test order in Shopify \u2192 fulfillment created, thank you email sent",
"edge_cases": [
"Unpaid order (pending) \u2192 IF prevents fulfillment, still sends email",
"Digital-only order \u2192 skips fulfillment, email says 'check your account'",
"Missing customer email \u2192 Gmail node will fail, add IF check",
"Shopify fulfillment already exists \u2192 may return 422"
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2shopifyApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
07 - Shopify Order → Fulfillment + Thank You Email. Uses shopifyTrigger, shopify, gmail. Event-driven trigger; 5 nodes.
Source: https://github.com/satmakuru222/TheAIStackk/blob/main/n8n-workflows/07-shopify-order-fulfillment-email.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow automates the synchronization of product prices across Shopify and WooCommerce platforms to ensure retail consistency. It triggers when a price change is detected in either system, appli
The workflow triggers on a new checkout event from Shopify and extracts all relevant cart data. It filters carts based on value and age to isolate qualified abandoned checkouts. For each qualified car
This n8n template automatically sends personalized recovery emails to customers who abandon their shopping carts. Recover 15-25% of lost sales with intelligent, well-timed follow-up emails that includ
This automation triggers when a new order is placed in your Shopify store. It then waits a short period, intelligently identifies complementary products based on the customer's purchase, retrieves tho
This workflow automates inventory management and predictive reordering for Shopify stores. It integrates Shopify, Google Sheets, and Slack to monitor inventory levels, calculate dynamic reorder points