This workflow corresponds to n8n.io template #6650 — we link there as the canonical source.
This workflow follows the Emailsend → Google Sheets 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": "JORMNG6XHP1Akgbo",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Daily Shipment Tracker with Courier API Updates & Customer Alerts",
"tags": [],
"nodes": [
{
"id": "b2117104-5779-441c-937f-bb09ee7b07f9",
"name": "Daily Trigger",
"type": "n8n-nodes-base.cron",
"position": [
-660,
200
],
"parameters": {},
"typeVersion": 1
},
{
"id": "9b0abc15-5ad5-4585-b755-c30b7193dcff",
"name": "Get Shipments List",
"type": "n8n-nodes-base.googleSheets",
"position": [
-440,
200
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "id",
"value": "=iuhgt678io"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "jko9876trde456yhn"
},
"authentication": "serviceAccount",
"combineFilters": "AND"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"typeVersion": 4
},
{
"id": "b4e26387-7f4e-4f5b-846e-36ea97d5cec6",
"name": "Filter Active Shipments",
"type": "n8n-nodes-base.filter",
"position": [
-220,
200
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "condition-1",
"operator": {
"type": "string",
"operation": "notEquals"
},
"leftValue": "={{ $json.status }}",
"rightValue": "delivered"
},
{
"id": "condition-2",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"leftValue": "={{ $json.tracking_number }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2
},
{
"id": "a0d9cf87-83c1-4b3f-b844-8913d7b55ef9",
"name": "Track via Delhivery",
"type": "n8n-nodes-base.httpRequest",
"position": [
220,
100
],
"parameters": {
"url": "https://track.delhivery.com/api/v1/packages/json/",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "waybill",
"value": "={{ $json.tracking_number }}"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "f1853f77-3060-4150-8a35-cefdc20c7ae1",
"name": "Track via DHL",
"type": "n8n-nodes-base.httpRequest",
"position": [
220,
300
],
"parameters": {
"url": "https://api-eu.dhl.com/track/shipments",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "trackingNumber",
"value": "={{ $json.tracking_number }}"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "6b395480-8d71-4492-8b3e-986992b1db3d",
"name": "Route by Courier",
"type": "n8n-nodes-base.if",
"position": [
0,
200
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "condition-1",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.courier }}",
"rightValue": "delhivery"
}
]
}
},
"typeVersion": 2
},
{
"id": "62185200-0431-449d-9b1b-6b96d63c2893",
"name": "Parse Tracking Data",
"type": "n8n-nodes-base.code",
"position": [
440,
200
],
"parameters": {
"jsCode": "// Parse tracking response and extract relevant information\nconst items = [];\n\nfor (const item of $input.all()) {\n const trackingData = item.json;\n \n let status = 'unknown';\n let location = '';\n let lastUpdated = '';\n let estimatedDelivery = '';\n \n // Parse Delhivery response\n if (trackingData.ShipmentData && trackingData.ShipmentData.length > 0) {\n const shipment = trackingData.ShipmentData[0];\n status = shipment.Status?.Status || 'unknown';\n location = shipment.Status?.StatusLocation || '';\n lastUpdated = shipment.Status?.StatusDateTime || '';\n estimatedDelivery = shipment.ExpectedDeliveryDate || '';\n }\n \n // Parse DHL response\n if (trackingData.shipments && trackingData.shipments.length > 0) {\n const shipment = trackingData.shipments[0];\n if (shipment.status) {\n status = shipment.status.statusCode || 'unknown';\n location = shipment.status.location || '';\n lastUpdated = shipment.status.timestamp || '';\n }\n }\n \n // Normalize status values\n const normalizedStatus = {\n 'Delivered': 'delivered',\n 'delivered': 'delivered',\n 'In Transit': 'in_transit',\n 'in_transit': 'in_transit',\n 'Out for Delivery': 'out_for_delivery',\n 'Picked up': 'picked_up',\n 'Exception': 'exception'\n }[status] || 'in_transit';\n \n items.push({\n json: {\n tracking_number: item.json.tracking_number || '',\n customer_email: item.json.customer_email || '',\n customer_phone: item.json.customer_phone || '',\n order_id: item.json.order_id || '',\n current_status: normalizedStatus,\n previous_status: item.json.status || '',\n location: location,\n last_updated: lastUpdated,\n estimated_delivery: estimatedDelivery,\n status_changed: (item.json.status !== normalizedStatus)\n }\n });\n}\n\nreturn items;"
},
"typeVersion": 2
},
{
"id": "3a97de9e-ec0e-4628-adab-2758162bfc6c",
"name": "Check Status Change",
"type": "n8n-nodes-base.filter",
"position": [
660,
200
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "condition-1",
"operator": {
"type": "boolean",
"operation": "equals"
},
"leftValue": "={{ $json.status_changed }}",
"rightValue": true
}
]
}
},
"typeVersion": 2
},
{
"id": "2e53cd9a-9e16-4c9f-87a5-f06ac949596d",
"name": "Update Google Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
880,
0
],
"parameters": {
"columns": {
"value": {},
"schema": [],
"mappingMode": "autoMapInputData",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "=09iuok"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "0iuhgy678o"
},
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"typeVersion": 4
},
{
"id": "dab15a3e-4632-43fa-a5a3-2b39bab593cb",
"name": "Send WhatsApp Update",
"type": "n8n-nodes-base.httpRequest",
"position": [
880,
200
],
"parameters": {
"url": "https://api.whatsapp.com/send",
"options": {},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "phone",
"value": "={{ $json.customer_phone }}"
},
{
"name": "text",
"value": "\ud83d\ude9a Shipment Update for Order #{{ $json.order_id }}\\n\\nTracking: {{ $json.tracking_number }}\\nStatus: {{ $json.current_status }}\\nLocation: {{ $json.location }}\\nLast Updated: {{ $json.last_updated }}\\n\\n{{ $json.estimated_delivery ? 'Estimated Delivery: ' + $json.estimated_delivery : '' }}\\n\\nThank you for choosing us! \ud83d\udce6"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "a23a973c-d76b-4a51-a485-ed65da3da1aa",
"name": "Send Email Update",
"type": "n8n-nodes-base.emailSend",
"position": [
880,
400
],
"parameters": {
"options": {},
"subject": "Shipment Update - Order #{{ $json.order_id }}",
"toEmail": "={{ $json.customer_email }}",
"fromEmail": "user@example.com"
},
"credentials": {
"smtp": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "9acd8aba-d127-4eec-b276-36dce8ef582c",
"name": "Execution Summary",
"type": "n8n-nodes-base.code",
"position": [
1100,
200
],
"parameters": {
"jsCode": "// Log workflow execution summary\nconst processedItems = $input.all().length;\nconst updatedItems = $input.all().filter(item => item.json.status_changed).length;\n\nconsole.log(`Shipment Tracking Summary:`);\nconsole.log(`- Total shipments processed: ${processedItems}`);\nconsole.log(`- Shipments with status updates: ${updatedItems}`);\nconsole.log(`- Execution completed at: ${new Date().toISOString()}`);\n\nreturn [{\n json: {\n summary: {\n processed: processedItems,\n updated: updatedItems,\n timestamp: new Date().toISOString()\n }\n }\n}];"
},
"typeVersion": 2
},
{
"id": "e959e416-7e2e-4848-a9df-deda76a88204",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-580,
-420
],
"parameters": {
"color": 4,
"width": 660,
"height": 320,
"content": "## How it works\n* **Daily Trigger**: Cron node runs workflow every day at 9 AM\n* **Get Shipments List**: Fetches all shipment data from Google Sheet\n* **Filter Active Shipments**: Excludes delivered orders and empty tracking numbers\n* **Route by Courier**: Directs shipments to appropriate API (Delhivery or DHL)\n* **Track via APIs**: Makes real-time tracking calls to courier services\n* **Parse Tracking Data**: Normalizes different API responses and detects status changes\n* **Check Status Change**: Only processes shipments with actual status updates\n* **Update & Notify**: Simultaneously updates Google Sheet, sends WhatsApp message, and email notification\n* **Execution Summary**: Logs workflow performance metrics"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "d01d33c3-9470-4b29-a8bf-1a0509b18d28",
"connections": {
"Daily Trigger": {
"main": [
[
{
"node": "Get Shipments List",
"type": "main",
"index": 0
}
]
]
},
"Track via DHL": {
"main": [
[
{
"node": "Parse Tracking Data",
"type": "main",
"index": 0
}
]
]
},
"Route by Courier": {
"main": [
[
{
"node": "Track via Delhivery",
"type": "main",
"index": 0
}
],
[
{
"node": "Track via DHL",
"type": "main",
"index": 0
}
]
]
},
"Send Email Update": {
"main": [
[
{
"node": "Execution Summary",
"type": "main",
"index": 0
}
]
]
},
"Get Shipments List": {
"main": [
[
{
"node": "Filter Active Shipments",
"type": "main",
"index": 0
}
]
]
},
"Check Status Change": {
"main": [
[
{
"node": "Update Google Sheet",
"type": "main",
"index": 0
},
{
"node": "Send WhatsApp Update",
"type": "main",
"index": 0
},
{
"node": "Send Email Update",
"type": "main",
"index": 0
}
]
]
},
"Parse Tracking Data": {
"main": [
[
{
"node": "Check Status Change",
"type": "main",
"index": 0
}
]
]
},
"Track via Delhivery": {
"main": [
[
{
"node": "Parse Tracking Data",
"type": "main",
"index": 0
}
]
]
},
"Update Google Sheet": {
"main": [
[
{
"node": "Execution Summary",
"type": "main",
"index": 0
}
]
]
},
"Send WhatsApp Update": {
"main": [
[
{
"node": "Execution Summary",
"type": "main",
"index": 0
}
]
]
},
"Filter Active Shipments": {
"main": [
[
{
"node": "Route by Courier",
"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.
googleApihttpHeaderAuthsmtp
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automatically tracks shipments across multiple courier services, updates Google Sheets, and notifies customers via WhatsApp/Email when status changes. Runs daily at 9 AM and only sends notifications when shipment status actually changes API costs may apply for…
Source: https://n8n.io/workflows/6650/ — 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.
Security teams, DevOps engineers, vulnerability analysts, and automation builders who want to eliminate repetitive Nessus scan parsing, AI-based risk triage, and manual reporting. Designed for orgs fo
This n8n workflow automatically finds apartments for rent in Germany, filters them by your city, rent budget, and number of rooms, and applies to them via email. Each application includes: A personali
👤 Who it’s for Blue Team leads, CISOs, and SOC managers who want automated visibility into threat metrics, endpoint alerts, and response actions — without needing a full SIEM or BI platform.
Workflow Overview Zoom Attendance Evaluator with Follow-up is an n8n automation workflow that automatically evaluates Zoom meeting attendance and sends follow-up emails to no-shows and early leavers w
This workflow automatically monitors Amazon product prices, tracks price changes, and sends alerts when significant price fluctuations occur. Built with ScrapeOps' structured data API, it provides a r