AutomationFlowsSlack & Telegram › Send Shopify Shipping Tracking Whatsapp Notifications with Full Tracking Info

Send Shopify Shipping Tracking Whatsapp Notifications with Full Tracking Info

ByMira Melhem @melhem on n8n.io

Automatically notify customers via WhatsApp when their orders ship, with intelligent phone validation, multi-country support, and bilingual messaging including complete tracking information.

Event trigger★★★★☆ complexity12 nodesPostgresHTTP RequestShopify Trigger
Slack & Telegram Trigger: Event Nodes: 12 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #12078 — we link there as the canonical source.

This workflow follows the HTTP Request → Postgres 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 →

Download .json
{
  "nodes": [
    {
      "id": "c7138ff9-2c46-4e55-bef7-19f466c5fd7d",
      "name": "Phone Validator",
      "type": "n8n-nodes-base.code",
      "position": [
        2064,
        1152
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// \u0642\u0627\u0626\u0645\u0629 \u0623\u0643\u0648\u0627\u062f \u0627\u0644\u062f\u0648\u0644\nconst countryCodes = {\n  'OM': '968', 'JO': '962', 'AE': '971', 'SA': '966', 'KW': '965',\n  'QA': '974', 'BH': '973', 'EG': '20', 'IQ': '964', 'LB': '961',\n  'SY': '963', 'PS': '970', 'YE': '967', 'US': '1', 'GB': '44',\n  'DE': '49', 'FR': '33', 'IT': '39', 'ES': '34', 'TR': '90',\n  'IN': '91', 'PK': '92'\n};\n\n// \u062c\u0644\u0628 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0645\u0646 fulfilment trigger\nconst fulfillmentData = $('fulfilment').item.json;\n\nconst phone = fulfillmentData.destination?.phone ||\n              fulfillmentData.shipping_address?.phone ||\n              fulfillmentData.phone || \n              '';\n\nconst countryCode = fulfillmentData.destination?.country_code ||\n                    fulfillmentData.shipping_address?.country_code ||\n                    'OM';\n\n// \u062a\u0646\u0636\u064a\u0641 \u0627\u0644\u0631\u0642\u0645\nlet formattedPhone = phone.trim().replace(/\\s+/g, '').replace(/[^0-9+]/g, '');\n\n// \u0644\u0648 \u0627\u0644\u0631\u0642\u0645 \u0641\u0627\u0636\u064a\nif (!formattedPhone || formattedPhone.length < 5) {\n  return {\n    phone: phone,\n    original_phone: phone,\n    country_code: countryCode,\n    validation_status: 'empty_or_invalid'\n  };\n}\n\n// \u0646\u0634\u064a\u0643 \u0625\u0630\u0627 \u0627\u0644\u0631\u0642\u0645 \u0628\u064a\u0628\u062f\u0623 \u0628\u0643\u0648\u062f \u062f\u0648\u0644\u0629\nconst startsWithCode = Object.values(countryCodes).some(code => {\n  const cleanPhone = formattedPhone.replace('+', '');\n  return cleanPhone.startsWith(code);\n});\n\nif (!startsWithCode) {\n  // \u0627\u0644\u0631\u0642\u0645 \u0645\u0627 \u0628\u064a\u0628\u062f\u0623 \u0628\u0643\u0648\u062f - \u0646\u0636\u064a\u0641 \u0627\u0644\u0643\u0648\u062f \u062d\u0633\u0628 \u0627\u0644\u0628\u0644\u062f\n  const defaultCode = countryCodes[countryCode] || '968';\n  const cleanPhone = formattedPhone.replace('+', '');\n  formattedPhone = '+' + defaultCode + cleanPhone;\n} else if (!formattedPhone.startsWith('+')) {\n  // \u0627\u0644\u0643\u0648\u062f \u0645\u0648\u062c\u0648\u062f \u0628\u0633 \u0645\u0627 \u0641\u064a \u0639\u0644\u0627\u0645\u0629 +\n  formattedPhone = '+' + formattedPhone;\n}\n\nreturn {\n  phone: formattedPhone,\n  original_phone: phone,\n  country_code: countryCode,\n  validation_status: 'success'\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "a65aa462-8570-4162-b5a0-63f533f69fa6",
      "name": "Update Order Shipped1",
      "type": "n8n-nodes-base.postgres",
      "position": [
        1632,
        1152
      ],
      "parameters": {
        "query": "UPDATE orders SET status = 'shipped', shipping_company = '{{ ($('fulfilment').item.json.tracking_company || '').replace(/'/g, \"''\") }}', tracking_number = '{{ $('fulfilment').item.json.tracking_number || '' }}' WHERE order_id = {{ $('fulfilment').item.json.order_id }} RETURNING customer_id",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "2b0bb6ff-c294-46f8-b8cd-db64aaa22248",
      "name": "Select rows from a table6",
      "type": "n8n-nodes-base.postgres",
      "position": [
        1872,
        1152
      ],
      "parameters": {
        "limit": 1,
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "customers",
          "cachedResultName": "customers"
        },
        "where": {
          "values": [
            {
              "value": "={{ $('fulfilment').item.json.destination.phone }}",
              "column": "phone"
            }
          ]
        },
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "options": {},
        "operation": "select"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "fa7ad08f-3440-4c37-ae50-dcf3bf525aa2",
      "name": "Get Customer1",
      "type": "n8n-nodes-base.postgres",
      "position": [
        2256,
        1152
      ],
      "parameters": {
        "query": "SELECT phone, language, first_name FROM customers WHERE website_id = {{ $('Select rows from a table6').item.json.website_id }}",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "5f221872-1c2e-4f0e-90f0-d1fd83b4b142",
      "name": "Check Language",
      "type": "n8n-nodes-base.if",
      "position": [
        2464,
        1152
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ ($('Get Customer1').item.json.language || 'en').trim().substring(0, 2) }}",
              "value2": "ar"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a95ed7ff-3755-4f60-bc45-757436a953b5",
      "name": "If10",
      "type": "n8n-nodes-base.if",
      "position": [
        2672,
        960
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "4e62f9c7-e498-4f22-8b94-2d9d2f72a806",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Phone Validator').item.json.phone }}",
              "rightValue": "=+96897666604"
            },
            {
              "id": "fe42ee4c-90fa-4daa-a7fb-be978382acb7",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Phone Validator').item.json.phone }}",
              "rightValue": "+1234567890"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "b63cc981-23db-413b-82ce-368981374730",
      "name": "If11",
      "type": "n8n-nodes-base.if",
      "position": [
        2672,
        1344
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "4e62f9c7-e498-4f22-8b94-2d9d2f72a806",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Phone Validator').item.json.phone }}",
              "rightValue": "=+96897666604"
            },
            {
              "id": "fe42ee4c-90fa-4daa-a7fb-be978382acb7",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Phone Validator').item.json.phone }}",
              "rightValue": "+1234567890"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "431ba0fb-59f1-43c9-80f4-239525e516d2",
      "name": "WhatsApp Shipped AR",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2912,
        944
      ],
      "parameters": {
        "url": "https://graph.facebook.com/v18.0/819420977915834/messages",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"messaging_product\": \"whatsapp\",\n  \"to\": \"{{ $('Phone Validator').item.json.phone.replace('+', '') }}\",\n  \"type\": \"text\",\n  \"text\": {\n    \"body\": \"\u0645\u0631\u062d\u0628\u064b\u0627 {{ $('Get Customer1').item.json.first_name }}\u060c\\n\\n\u064a\u0633\u0631\u0651\u0646\u0627 \u0625\u0639\u0644\u0627\u0645\u0643\u0645 \u0628\u0623\u0646\u0647 \u062a\u0645 \u0634\u062d\u0646 \u0637\u0644\u0628\u0643\u0645 \u0628\u0646\u062c\u0627\u062d.\\n\u0631\u0642\u0645 \u0627\u0644\u0637\u0644\u0628: {{ $('fulfilment').item.json.order_id }}\\n\u0631\u0642\u0645 \u0627\u0644\u062a\u062a\u0628\u0639: {{ $('fulfilment').item.json.tracking_number }}\\n\u0634\u0631\u0643\u0629 \u0627\u0644\u0634\u062d\u0646: {{ $('fulfilment').item.json.tracking_company }}\\n\u0631\u0627\u0628\u0637 \u0627\u0644\u062a\u062a\u0628\u0639 : {{ $('fulfilment').item.json.tracking_url }}\\n\u0627\u0644\u0645\u062f\u0629 \u0627\u0644\u0645\u062a\u0648\u0642\u0639\u0629 \u0644\u0644\u062a\u0648\u0635\u064a\u0644: \u0645\u0646 7 \u0625\u0644\u0649 12 \u064a\u0648\u0645 \u0639\u0645\u0644.\\n\\n\u064a\u0645\u0643\u0646\u0643\u0645 \u0645\u062a\u0627\u0628\u0639\u0629 \u062d\u0627\u0644\u0629 \u0627\u0644\u0634\u062d\u0646\u0629 \u0639\u0628\u0631 \u0631\u0642\u0645 \u0627\u0644\u062a\u062a\u0628\u0639\u060c \u0648\u0633\u0646\u062d\u0631\u0635 \u0639\u0644\u0649 \u0625\u0628\u0642\u0627\u0626\u0643\u0645 \u0639\u0644\u0649 \u0627\u0637\u0644\u0627\u0639 \u062d\u062a\u0649 \u0627\u0633\u062a\u0644\u0627\u0645 \u0627\u0644\u0637\u0644\u0628.\\n\u0646\u0634\u0643\u0631\u0643\u0645 \u0639\u0644\u0649 \u062b\u0642\u062a\u0643\u0645 \u0628\u0639\u064f\u0645\u0627\u0646 \u0644\u0627\u0643\u062c\u0631\u064a.\\n\\n\u0645\u0639 \u0623\u0637\u064a\u0628 \u0627\u0644\u062a\u062d\u064a\u0627\u062a\u060c\\n\u0639\u064f\u0645\u0627\u0646 \u0644\u0627\u0643\u062c\u0631\u064a\"\n  }\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "6d6fac70-72c3-4c35-9291-11e0b63bd4dd",
      "name": "WhatsApp Shipped EN1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2912,
        1328
      ],
      "parameters": {
        "url": "https://graph.facebook.com/v18.0/819420977915834/messages",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"messaging_product\": \"whatsapp\",\n  \"to\": \"{{ $('Phone Validator').item.json.phone.replace('+', '') }}\",\n  \"type\": \"text\",\n  \"text\": {\n    \"body\": \"Hello {{ $('Get Customer1').item.json.first_name }},\\n\\nWe are pleased to inform you that your order has been shipped successfully.\\n\\nOrder No: {{ $('fulfilment').item.json.order_id }}\\nTracking No: {{ $('fulfilment').item.json.tracking_number }}\\nCourier Company: {{ $('fulfilment').item.json.tracking_company }}\\nTracking Url: {{ $('fulfilment').item.json.tracking_url }}\\nEstimated delivery time: 7\u201312 business days.\\n\\nYou may track your shipment using the tracking number provided. We will continue to keep you informed until your order is delivered.\\nT  }\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "8ba4a7f3-90d8-4a9f-81d5-6c0aba6b5cc2",
      "name": "fulfilment",
      "type": "n8n-nodes-base.shopifyTrigger",
      "position": [
        1472,
        1152
      ],
      "parameters": {
        "topic": "fulfillments/create",
        "authentication": "accessToken"
      },
      "credentials": {
        "shopifyAccessTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "474ccf63-f94e-40e6-bc63-b41448e7c222",
      "name": "Sticky Note15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        736,
        320
      ],
      "parameters": {
        "width": 560,
        "height": 1744,
        "content": "---\n\n## \ud83c\udfaf Key Features\n- \u2705 **Real-time Fulfillment Sync:** Instant database update when order ships\n- \u2705 **Complete Tracking Info:** Includes tracking number, company, and URL\n- \u2705 **Bilingual Support:** Auto-detects customer language preference from database\n- \u2705 **Phone Validation:** Handles 23+ country codes with auto-formatting\n- \u2705 **Test Protection:** Prevents notifications to development numbers\n- \u2705 **Personalization:** Uses customer first name in greeting\n- \u2705 **Delivery Expectations:** Sets clear 7-12 day timeline\n- \u2705 **Professional Branding:** Luxury brand tone in both languages\n- \u2705 **Trackable Links:** Includes clickable tracking URL\n\n---\n\n## \ud83d\udcca Database Operations\n\n### **Orders Table Update**\n- **Status Change:** 'open/paid' \u2192 'shipped'\n- **New Fields Added:**\n  - shipping_company: Courier service name\n  - tracking_number: Package tracking ID\n- **Lookup Key:** order_id (from Shopify)\n- **Returns:** customer_id for subsequent queries\n\n### **Customers Table Query**\n- **Lookup:** By website_id (Shopify customer ID)\n- **Retrieved:** phone, language, first_name\n- **Purpose:** Get communication preferences\n\n---\n\n## \ud83d\udcde Technical Details\n- **WhatsApp API Version:** v18.0\n- **API Endpoint:** graph.facebook.com/v18.0/819420977915834/messages\n- **Authentication:** Bearer YOUR_TOKEN_HERE (credential: \"whatsapp mira\")\n- **Phone Format:** International format with country code (+CountryCode + Number)\n- **API Phone Format:** Removes '+' before sending to WhatsApp API\n- **Database:** PostgreSQL\n- **Credential Name:** \"Postgres account\"\n- **Default Country:** Oman (+968) if country_code not detected\n- **Test Numbers Blocked:** \n  - +96897666604 (Oman)\n  - +962798087441 (Jordan)\n\n---\n\n## \ud83d\udd04 Data Flow Summary\n1. **Fulfillment created** \u2192 Shopify webhook fires\n2. **Update order status** \u2192 Mark as 'shipped' with tracking details\n3. **Lookup customer** \u2192 Find by phone from fulfillment data\n4. **Validate phone** \u2192 Format with country code\n5. **Get preferences** \u2192 Retrieve language and name from database\n6. **Detect language** \u2192 Route to AR or EN path\n7. **Filter tests** \u2192 Skip internal phone numbers\n8. **Send notification** \u2192 WhatsApp message with tracking info\n\n---\n\n## \ud83d\udcbc Business Logic\n- **Delivery Window:** Consistently communicates 7-12 business days\n- **Brand Voice:** Professional luxury brand tone\n- **Customer Service:** Proactive communication at shipping milestone\n- **Tracking Empowerment:** Provides all tools for self-service tracking\n- **Multi-channel Sync:** Database, Shopify, and WhatsApp aligned\n\n---\n\n## \ud83c\udf10 Multi-language Support\n| Element | Arabic | English |\n|---------|--------|---------|\n| Greeting | \u0645\u0631\u062d\u0628\u064b\u0627 | Hello |\n| Status | \u062a\u0645 \u0634\u062d\u0646 \u0637\u0644\u0628\u0643\u0645 \u0628\u0646\u062c\u0627\u062d | Successfully shipped |\n| Order No | \u0631\u0642\u0645 \u0627\u0644\u0637\u0644\u0628 | Order No |\n| Tracking No | \u0631\u0642\u0645 \u0627\u0644\u062a\u062a\u0628\u0639 | Tracking No |\n| Courier | \u0634\u0631\u0643\u0629 \u0627\u0644\u0634\u062d\u0646 | Courier Company |\n| Delivery | \u0645\u0646 7 \u0625\u0644\u0649 12 \u064a\u0648\u0645 \u0639\u0645\u0644 | 7\u201312 business days |\n"
      },
      "typeVersion": 1
    },
    {
      "id": "a2592b35-7df6-48c8-b193-48483233cc50",
      "name": "Sticky Note18",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3168,
        832
      ],
      "parameters": {
        "color": 6,
        "width": 672,
        "height": 864,
        "content": "\n### **8A. Arabic Shipping Notification - \"WhatsApp Shipped AR\"**\n- **Type:** HTTP Request (POST)\n- **Endpoint:** Facebook Graph API v18.0 (WhatsApp Business)\n- **Phone Format:** Removes '+' prefix before API call\n- **Message Content (Arabic):**\n  - **Greeting:** \"\u0645\u0631\u062d\u0628\u064b\u0627 [first_name]\" (Hello)\n  - **Status:** \"\u062a\u0645 \u0634\u062d\u0646 \u0637\u0644\u0628\u0643\u0645 \u0628\u0646\u062c\u0627\u062d\" (Your order has been shipped successfully)\n  - **Order Details:**\n    - \u0631\u0642\u0645 \u0627\u0644\u0637\u0644\u0628 (Order No): order_id\n    - \u0631\u0642\u0645 \u0627\u0644\u062a\u062a\u0628\u0639 (Tracking No): tracking_number\n    - \u0634\u0631\u0643\u0629 \u0627\u0644\u0634\u062d\u0646 (Courier): tracking_company\n    - \u0631\u0627\u0628\u0637 \u0627\u0644\u062a\u062a\u0628\u0639 (Tracking URL): tracking_url\n  - **Delivery Time:** 7-12 business days (in Arabic)\n  - **Instructions:** Can track via tracking number\n- **Tone:** Formal, professional Arabic suitable for luxury brand\n- **Purpose:** Send comprehensive shipping notification to Arabic-speaking customers\n\n---\n\n### **8B. English Shipping Notification - \"WhatsApp Shipped EN1\"**\n- **Type:** HTTP Request (POST)\n- **Endpoint:** Same WhatsApp Business API\n- **Phone Format:** Removes '+' prefix\n- **Message Content (English):**\n  - **Greeting:** \"Hello [first_name]\"\n  - **Status:** \"Your order has been shipped successfully\"\n  - **Order Details:**\n    - Order No: order_id\n    - Tracking No: tracking_number\n    - Courier Company: tracking_company\n    - Tracking URL: tracking_url\n  - **Delivery Time:** 7-12 business days\n  - **Instructions:** Track shipment using tracking number\n  \"\n- **Tone:** Professional, informative English\n- **Purpose:** Send comprehensive shipping notification to English-speaking customers\n\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "If10": {
      "main": [
        [
          {
            "node": "WhatsApp Shipped AR",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If11": {
      "main": [
        [
          {
            "node": "WhatsApp Shipped EN1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fulfilment": {
      "main": [
        [
          {
            "node": "Update Order Shipped1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Customer1": {
      "main": [
        [
          {
            "node": "Check Language",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Language": {
      "main": [
        [
          {
            "node": "If10",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "If11",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Phone Validator": {
      "main": [
        [
          {
            "node": "Get Customer1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Order Shipped1": {
      "main": [
        [
          {
            "node": "Select rows from a table6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select rows from a table6": {
      "main": [
        [
          {
            "node": "Phone Validator",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Automatically notify customers via WhatsApp when their orders ship, with intelligent phone validation, multi-country support, and bilingual messaging including complete tracking information.

Source: https://n8n.io/workflows/12078/ — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

Pede Ai. Uses httpRequest, telegram, postgres, telegramTrigger. Event-driven trigger; 53 nodes.

HTTP Request, Telegram, Postgres +1
Slack & Telegram

Create-Issue-Linear-Slack. Uses linear, postgres, slackTrigger, httpRequest. Event-driven trigger; 33 nodes.

Linear, Postgres, Slack Trigger +2
Slack & Telegram

02 - Photo OCR Handler. Uses telegramTrigger, telegram, httpRequest, readBinaryFile. Event-driven trigger; 16 nodes.

Telegram Trigger, Telegram, HTTP Request +2
Slack & Telegram

Handle_Error. Uses errorTrigger, postgres, httpRequest, discord. Event-driven trigger; 9 nodes.

Error Trigger, Postgres, HTTP Request +1
Slack & Telegram

Worflow. Uses whatsAppTrigger, httpRequest, whatsApp. Event-driven trigger; 94 nodes.

WhatsApp Trigger, HTTP Request, WhatsApp