This workflow corresponds to n8n.io template #8696 — we link there as the canonical source.
This workflow follows the Gmail → Google Drive recipe pattern — see all workflows that pair these two integrations.
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 →
{
"id": "5A6KYwXDVVpHC5zH",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Invoice & Receipt Generator with HTML to PDF",
"tags": [],
"nodes": [
{
"id": "b8298f3e-c30a-45bc-b592-08ea4b7b4fd4",
"name": "Shopify Order Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-1296,
112
],
"parameters": {
"path": "shopify-webhook",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 1
},
{
"id": "1db73ee5-13ce-43ca-8cf2-1f4b5bbe4a77",
"name": "Check Payment Status",
"type": "n8n-nodes-base.if",
"position": [
-1072,
112
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "order-paid-check",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.body.financial_status }}",
"rightValue": "paid1"
}
]
}
},
"typeVersion": 2
},
{
"id": "7ae74e75-f2b4-4464-98ff-79a3b1260a40",
"name": "Format Invoice Data",
"type": "n8n-nodes-base.code",
"position": [
-848,
16
],
"parameters": {
"jsCode": "// Extract and format order data for invoice\nconst orderData = $input.first().json.body;\n\n// Calculate totals\nconst lineItems = orderData.line_items.map(item => ({\n name: item.name,\n quantity: item.quantity,\n price: parseFloat(item.price),\n total: parseFloat(item.price) * item.quantity,\n sku: item.sku || 'N/A'\n}));\n\nconst subtotal = lineItems.reduce((sum, item) => sum + item.total, 0);\nconst taxAmount = parseFloat(orderData.total_tax || 0);\nconst shippingAmount = parseFloat(orderData.shipping_lines?.[0]?.price || 0);\nconst total = parseFloat(orderData.total_price);\n\n// Format invoice data\nconst invoiceData = {\n // Order info\n orderNumber: orderData.order_number,\n orderDate: new Date(orderData.created_at).toLocaleDateString(),\n \n // Customer info\n customer: {\n name: `${orderData.customer.first_name} ${orderData.customer.last_name}`,\n email: orderData.customer.email,\n phone: orderData.customer.phone || 'N/A'\n },\n \n // Billing address\n billingAddress: orderData.billing_address ? {\n address1: orderData.billing_address.address1,\n address2: orderData.billing_address.address2 || '',\n city: orderData.billing_address.city,\n province: orderData.billing_address.province,\n zip: orderData.billing_address.zip,\n country: orderData.billing_address.country\n } : null,\n \n // Shipping address\n shippingAddress: orderData.shipping_address ? {\n address1: orderData.shipping_address.address1,\n address2: orderData.shipping_address.address2 || '',\n city: orderData.shipping_address.city,\n province: orderData.shipping_address.province,\n zip: orderData.shipping_address.zip,\n country: orderData.shipping_address.country\n } : null,\n \n // Line items\n items: lineItems,\n \n // Totals\n subtotal: subtotal.toFixed(2),\n tax: taxAmount.toFixed(2),\n shipping: shippingAmount.toFixed(2),\n total: total.toFixed(2),\n currency: orderData.currency,\n \n // Additional info\n paymentMethod: orderData.payment_gateway_names?.[0] || 'Online Payment',\n notes: orderData.note || ''\n};\n\nreturn { invoiceData };"
},
"typeVersion": 2
},
{
"id": "9a5abe26-a8e8-42a9-b851-d14efbbd3c1c",
"name": "Generate HTML Invoice",
"type": "n8n-nodes-base.code",
"position": [
-544,
16
],
"parameters": {
"jsCode": "// Generate professional invoice HTML\nconst data = $input.first().json.invoiceData;\n\nconst html = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Invoice #${data.orderNumber}</title>\n <style>\n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n \n body {\n font-family: 'Arial', sans-serif;\n line-height: 1.6;\n color: #333;\n background: #f8f9fa;\n }\n \n .container {\n max-width: 800px;\n margin: 0 auto;\n background: white;\n padding: 40px;\n box-shadow: 0 0 20px rgba(0,0,0,0.1);\n }\n \n .header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 40px;\n padding-bottom: 20px;\n border-bottom: 3px solid #007bff;\n }\n \n .company-info {\n flex: 1;\n }\n \n .company-name {\n font-size: 28px;\n font-weight: bold;\n color: #007bff;\n margin-bottom: 5px;\n }\n \n .invoice-info {\n text-align: right;\n }\n \n .invoice-title {\n font-size: 36px;\n font-weight: bold;\n color: #333;\n margin-bottom: 10px;\n }\n \n .invoice-number {\n font-size: 18px;\n color: #666;\n }\n \n .details-section {\n display: flex;\n justify-content: space-between;\n margin-bottom: 40px;\n gap: 40px;\n }\n \n .detail-box {\n flex: 1;\n padding: 20px;\n background: #f8f9fa;\n border-radius: 8px;\n }\n \n .detail-title {\n font-weight: bold;\n margin-bottom: 15px;\n color: #007bff;\n font-size: 16px;\n }\n \n .detail-content {\n color: #555;\n }\n \n .items-table {\n width: 100%;\n border-collapse: collapse;\n margin-bottom: 30px;\n }\n \n .items-table th,\n .items-table td {\n padding: 15px;\n text-align: left;\n border-bottom: 1px solid #ddd;\n }\n \n .items-table th {\n background-color: #007bff;\n color: white;\n font-weight: bold;\n text-transform: uppercase;\n font-size: 14px;\n }\n \n .items-table tr:hover {\n background-color: #f5f5f5;\n }\n \n .text-right {\n text-align: right;\n }\n \n .totals-section {\n margin-left: auto;\n width: 300px;\n }\n \n .totals-table {\n width: 100%;\n border-collapse: collapse;\n }\n \n .totals-table td {\n padding: 10px 0;\n border-bottom: 1px solid #eee;\n }\n \n .total-row {\n font-weight: bold;\n font-size: 18px;\n border-top: 2px solid #007bff;\n color: #007bff;\n }\n \n .footer {\n margin-top: 50px;\n padding-top: 20px;\n border-top: 1px solid #ddd;\n text-align: center;\n color: #666;\n font-size: 14px;\n }\n \n .thank-you {\n font-size: 18px;\n color: #007bff;\n margin-bottom: 10px;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"header\">\n <div class=\"company-info\">\n <div class=\"company-name\">Your Company Name</div>\n <div>123 Business Street</div>\n <div>City, State 12345</div>\n <div>Phone: (555) 123-4567</div>\n <div>Email: user@example.com</div>\n </div>\n <div class=\"invoice-info\">\n <div class=\"invoice-title\">INVOICE</div>\n <div class=\"invoice-number\">#${data.orderNumber}</div>\n <div style=\"margin-top: 10px;\">Date: ${data.orderDate}</div>\n </div>\n </div>\n \n <div class=\"details-section\">\n <div class=\"detail-box\">\n <div class=\"detail-title\">Bill To:</div>\n <div class=\"detail-content\">\n <strong>${data.customer.name}</strong><br>\n ${data.customer.email}<br>\n ${data.customer.phone}<br><br>\n ${data.billingAddress ? `\n ${data.billingAddress.address1}<br>\n ${data.billingAddress.address2 ? data.billingAddress.address2 + '<br>' : ''}\n ${data.billingAddress.city}, ${data.billingAddress.province} ${data.billingAddress.zip}<br>\n ${data.billingAddress.country}\n ` : ''}\n </div>\n </div>\n \n ${data.shippingAddress ? `\n <div class=\"detail-box\">\n <div class=\"detail-title\">Ship To:</div>\n <div class=\"detail-content\">\n ${data.shippingAddress.address1}<br>\n ${data.shippingAddress.address2 ? data.shippingAddress.address2 + '<br>' : ''}\n ${data.shippingAddress.city}, ${data.shippingAddress.province} ${data.shippingAddress.zip}<br>\n ${data.shippingAddress.country}\n </div>\n </div>\n ` : ''}\n \n <div class=\"detail-box\">\n <div class=\"detail-title\">Payment Info:</div>\n <div class=\"detail-content\">\n <strong>Method:</strong> ${data.paymentMethod}<br>\n <strong>Currency:</strong> ${data.currency}<br>\n <strong>Status:</strong> Paid\n </div>\n </div>\n </div>\n \n <table class=\"items-table\">\n <thead>\n <tr>\n <th>Item</th>\n <th>SKU</th>\n <th>Qty</th>\n <th>Price</th>\n <th>Total</th>\n </tr>\n </thead>\n <tbody>\n ${data.items.map(item => `\n <tr>\n <td><strong>${item.name}</strong></td>\n <td>${item.sku}</td>\n <td>${item.quantity}</td>\n <td>$${item.price.toFixed(2)}</td>\n <td class=\"text-right\">$${item.total.toFixed(2)}</td>\n </tr>\n `).join('')}\n </tbody>\n </table>\n \n <div class=\"totals-section\">\n <table class=\"totals-table\">\n <tr>\n <td>Subtotal:</td>\n <td class=\"text-right\">$${data.subtotal}</td>\n </tr>\n ${parseFloat(data.shipping) > 0 ? `\n <tr>\n <td>Shipping:</td>\n <td class=\"text-right\">$${data.shipping}</td>\n </tr>\n ` : ''}\n ${parseFloat(data.tax) > 0 ? `\n <tr>\n <td>Tax:</td>\n <td class=\"text-right\">$${data.tax}</td>\n </tr>\n ` : ''}\n <tr class=\"total-row\">\n <td><strong>Total:</strong></td>\n <td class=\"text-right\"><strong>$${data.total}</strong></td>\n </tr>\n </table>\n </div>\n \n ${data.notes ? `\n <div style=\"margin-top: 30px; padding: 20px; background: #f8f9fa; border-radius: 8px;\">\n <strong>Notes:</strong><br>\n ${data.notes}\n </div>\n ` : ''}\n \n <div class=\"footer\">\n <div class=\"thank-you\">Thank you for your business!</div>\n <div>This invoice was generated automatically on ${new Date().toLocaleDateString()}</div>\n <div style=\"margin-top: 10px;\">For questions about this invoice, please contact us at user@example.com</div>\n </div>\n </div>\n</body>\n</html>\n`;\n\nreturn { html };"
},
"typeVersion": 2
},
{
"id": "9d28bb6b-0609-4198-bde5-b5c4fa9f6f3f",
"name": "Save to Google Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
368,
-192
],
"parameters": {
"name": "=Invoice - {{ $('Shopify Order Webhook').item.json.body.id }}",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "1A2B3C4D5E6F7G8H9I0J",
"cachedResultName": "Invoices"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "97e7a02e-3f41-42c7-a724-39f4afe90c90",
"name": "Send Webhook Response",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
864,
16
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={\n \"success\": true,\n \"message\": \"Invoice generated and sent successfully\",\n \"orderNumber\": \"{{ $('Format Invoice Data').first().json.invoiceData.orderNumber }}\",\n \"customerEmail\": \"{{ $('Format Invoice Data').first().json.invoiceData.customer.email }}\",\n \"timestamp\": \"{{ new Date().toISOString() }}\"\n}"
},
"typeVersion": 1
},
{
"id": "f2522594-20a1-4330-81ca-599a96831ee6",
"name": "Response for Unpaid Orders",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
-736,
336
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={\n \"success\": false,\n \"message\": \"Order not paid yet, invoice not generated\",\n \"orderNumber\": \"{{ $('Shopify Order Webhook').item.json.body.order_number }}\",\n \"paymentStatus\": \"{{ $('Shopify Order Webhook').item.json.body.financial_status }}\"\n}"
},
"typeVersion": 1
},
{
"id": "b609d01c-683c-4adc-bc21-ba41615d6860",
"name": "Email to Customer",
"type": "n8n-nodes-base.gmail",
"position": [
368,
112
],
"parameters": {
"sendTo": "={{ $('Shopify Order Webhook').item.json.body.customer.email }}",
"message": "=<!DOCTYPE html> <html lang=\"en\"> <head> <meta charset=\"UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <title>Invoice for Order #{{ $('Shopify Order Webhook').item.json.body.order_number }}</title> <style> body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px; } .header { text-align: center; margin-bottom: 30px; padding-bottom: 20px; border-bottom: 2px solid #007bff; } .company-name { font-size: 24px; font-weight: bold; color: #007bff; margin-bottom: 5px; } .attachment-notice { background: #f8f9fa; padding: 15px; border-left: 4px solid #28a745; margin: 20px 0; } .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; color: #666; font-size: 14px; } </style> </head> <body> <div class=\"header\"> <div class=\"company-name\">Company Name</div> </div> <p>Dear {{ $('Shopify Order Webhook').item.json.body.customer.first_name }},</p> <p>Thank you for your recent order! Your payment has been successfully processed.</p> <div class=\"attachment-notice\"> <strong>\ud83d\udcce Invoice Attached</strong><br> Please find your invoice attached to this email for order #{{ $('Shopify Order Webhook').item.json.body.order_number }}. </div> <p>We're now preparing your order for shipment. You'll receive a tracking notification once your order is on its way.</p> <p>If you have any questions about your order, please don't hesitate to contact us at support@pdfmunk.com.</p> <p>Thank you for choosing Company Name!</p> <p>Best regards,<br> The Company Name Team</p> <div class=\"footer\"> <p>This is an automated email regarding your order. Please save the attached invoice for your records.</p> </div> </body> </html>",
"options": {
"attachmentsUi": {
"attachmentsBinary": [
{}
]
}
},
"subject": "=Invoice for your Order# {{ $('Shopify Order Webhook').item.json.body.order_number }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "523d9859-c735-4344-ad85-42b4b515db82",
"name": "Generate PDF Invoice",
"type": "n8n-nodes-htmlcsstopdf.htmlcsstopdf",
"position": [
-176,
16
],
"parameters": {
"css_content": "/* PDF Page Setup - Add to <style> section in HTML */ @page { /* A4 page size */ size: A4; /* Page margins */ margin-top: 0.5in; margin-bottom: 0.5in; margin-left: 0.5in; margin-right: 0.5in; /* Ensure backgrounds print */ -webkit-print-color-adjust: exact; color-adjust: exact; print-color-adjust: exact; } /* Print-specific styles */ @media print { body { /* Remove any default margins */ margin: 0; padding: 0; /* Ensure backgrounds and colors print */ -webkit-print-color-adjust: exact; color-adjust: exact; print-color-adjust: exact; } /* Hide elements that shouldn't print */ .no-print { display: none !important; } /* Ensure page breaks work properly */ .page-break-before { page-break-before: always; } .page-break-after { page-break-after: always; } .page-break-inside-avoid { page-break-inside: avoid; } }",
"html_content": "={{ $json.html }}"
},
"credentials": {
"htmlcsstopdfApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "6fe6c671-86c2-4693-8194-544efd70ed88",
"name": "Download File PDF",
"type": "n8n-nodes-base.httpRequest",
"position": [
112,
16
],
"parameters": {
"url": "={{ $json.pdf_url }}",
"options": {}
},
"typeVersion": 4.2
},
{
"id": "f4628be8-e2ea-4645-a0e1-53aaa0b86bcc",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1408,
0
],
"parameters": {
"color": 4,
"width": 288,
"height": 272,
"content": "## Webhook from Shopify\nSetup this webhook URL to receive order information from Shopify"
},
"typeVersion": 1
},
{
"id": "4adb5fbe-f18e-4ca9-a1d9-b7df64603513",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-608,
-96
],
"parameters": {
"color": 4,
"height": 272,
"content": "## Create HTML\nGenerate custom HTML for the invoice"
},
"typeVersion": 1
},
{
"id": "3caf4ba7-4643-4cb1-9fe2-7cb5a3da5491",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-304,
-96
],
"parameters": {
"color": 4,
"width": 352,
"height": 272,
"content": "## Generate PDF\n* Convert HTML to PDF Invoice\n* Get your API Key from https://pdfmunk.com"
},
"typeVersion": 1
},
{
"id": "1dffb856-c054-4613-b38f-5f16b054eb7d",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-912,
-96
],
"parameters": {
"color": 4,
"height": 272,
"content": "## Format Data\nPrepare Line Item data for next step"
},
"typeVersion": 1
},
{
"id": "bdfa1ed0-8eec-4102-b0f8-d74daeb0c058",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
272,
96
],
"parameters": {
"color": 4,
"width": 304,
"height": 288,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n## Email Invoice\nSend Invoice PDF Email to the Customer"
},
"typeVersion": 1
},
{
"id": "f555dcd8-9d67-4308-9dec-6ed273959187",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
272,
-288
],
"parameters": {
"color": 4,
"width": 304,
"height": 288,
"content": "## Save Invoice PDF\nStore Invoice PDF to Google Drive"
},
"typeVersion": 1
},
{
"id": "e48faa71-bc4f-4f66-abdb-197ad2cad98e",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-848,
224
],
"parameters": {
"color": 4,
"width": 336,
"height": 272,
"content": "## Notify for unpaid\nSend Webhook response for Unpaid Invoice"
},
"typeVersion": 1
},
{
"id": "f443b7d2-f3e3-4466-b76f-cd6f98c9dc62",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
736,
-80
],
"parameters": {
"color": 4,
"width": 400,
"height": 272,
"content": "## Webhook Acknowledgement\nAcknowledge for successful invoice processing"
},
"typeVersion": 1
},
{
"id": "05be1093-c088-4abe-9828-64eb2ffde51d",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-688,
-480
],
"parameters": {
"color": 6,
"width": 544,
"height": 288,
"content": "## \ud83c\udfaf What This Template Does\n\nTransform your Shopify order fulfillment with complete invoice automation. When a customer places an order, this workflow automatically:\n\n\u2705 Receives order data via Shopify webhook\n\u2705 Validates payment status (only processes paid orders)\n\u2705 Generates professional HTML invoice with your branding\n\u2705 Converts to PDF using HTML to PDF conversion\n\u2705 Saves invoice to Google Drive for record-keeping\n\u2705 Emails PDF invoice to customer automatically\n\u2705 Provides webhook response back to Shopify"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "38c32164-468b-4755-9e16-ae771fc23272",
"connections": {
"Download File PDF": {
"main": [
[
{
"node": "Email to Customer",
"type": "main",
"index": 0
},
{
"node": "Save to Google Drive",
"type": "main",
"index": 0
}
]
]
},
"Email to Customer": {
"main": [
[
{
"node": "Send Webhook Response",
"type": "main",
"index": 0
}
]
]
},
"Format Invoice Data": {
"main": [
[
{
"node": "Generate HTML Invoice",
"type": "main",
"index": 0
}
]
]
},
"Check Payment Status": {
"main": [
[
{
"node": "Format Invoice Data",
"type": "main",
"index": 0
}
],
[
{
"node": "Response for Unpaid Orders",
"type": "main",
"index": 0
}
]
]
},
"Generate PDF Invoice": {
"main": [
[
{
"node": "Download File PDF",
"type": "main",
"index": 0
}
]
]
},
"Save to Google Drive": {
"main": [
[
{
"node": "Send Webhook Response",
"type": "main",
"index": 0
}
]
]
},
"Generate HTML Invoice": {
"main": [
[
{
"node": "Generate PDF Invoice",
"type": "main",
"index": 0
}
]
]
},
"Shopify Order Webhook": {
"main": [
[
{
"node": "Check Payment Status",
"type": "main",
"index": 0
}
]
]
}
}
}
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.
gmailOAuth2googleDriveOAuth2ApihtmlcsstopdfApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automatically generate professional PDF invoices when new orders are placed in Shopify. This template creates beautifully formatted invoices from order data, converts them to PDF, saves to Google Drive, and emails customers - all in one seamless workflow.
Source: https://n8n.io/workflows/8696/ — 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.
A comprehensive n8n workflow template that completely automates the startup pitch deck submission process for accelerators, incubators, VC firms, and startup competitions. This workflow validates foun
This workflow automates the entire parent consent process for school field trips, replacing manual paper forms with a secure, verified, and legally compliant digital system.
Transform new hire onboarding from 3-4 hours of manual document compilation to 3 minutes of automated generation - creates personalized, role-specific document packages including welcome letters, bene
Verified Corporate Training Certificate with CEUs – Fully Automated & Verifiable
Transform account statement management from hours to minutes - automatically compile transaction histories, calculate aging analysis, monitor credit limits, assess payment risk, and deliver profession