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": "WhatsApp Business Automation - Coedwig Creations",
"nodes": [
{
"parameters": {
"path": "whatsapp-webhook",
"httpMethod": "={{$request.method}}",
"responseMode": "responseNode",
"options": {}
},
"id": "a1b2c3d4-0001-4000-8000-000000000001",
"name": "WhatsApp Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
0,
400
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "verify-check",
"leftValue": "={{ $json.query['hub.mode'] }}",
"rightValue": "subscribe",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "a1b2c3d4-0001-4000-8000-000000000002",
"name": "Is Verification?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
220,
400
]
},
{
"parameters": {
"respondWith": "text",
"responseBody": "={{ $json.query['hub.challenge'] }}",
"options": {
"responseCode": 200
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000003",
"name": "Verify Token Response",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
440,
300
]
},
{
"parameters": {
"respondWith": "text",
"responseBody": "OK",
"options": {
"responseCode": 200
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000004",
"name": "ACK Message",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
440,
500
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "has-messages",
"leftValue": "={{ $json.body?.entry?.[0]?.changes?.[0]?.value?.messages?.[0]?.text?.body }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "isNotEmpty"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "a1b2c3d4-0001-4000-8000-000000000005",
"name": "Has Text Message?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
660,
500
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Extract WhatsApp message details\nconst entry = $input.item.json.body?.entry?.[0];\nconst change = entry?.changes?.[0]?.value;\nconst message = change?.messages?.[0];\nconst contact = change?.contacts?.[0];\n\nreturn {\n json: {\n message_id: message?.id || '',\n from_phone: message?.from || '',\n contact_name: contact?.profile?.name || 'Unknown',\n message_text: message?.text?.body || '',\n message_type: message?.type || 'text',\n timestamp: message?.timestamp || '',\n phone_number_id: change?.metadata?.phone_number_id || '',\n display_phone: change?.metadata?.display_phone_number || '',\n received_at: new Date().toISOString()\n }\n};"
},
"id": "a1b2c3d4-0001-4000-8000-000000000006",
"name": "Extract Message Data",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
880,
400
]
},
{
"parameters": {
"operation": "append",
"tableId": "wa_messages",
"columns": {
"mappingMode": "defineBelow",
"value": {
"message_id": "={{ $json.message_id }}",
"from_phone": "={{ $json.from_phone }}",
"contact_name": "={{ $json.contact_name }}",
"message_text": "={{ $json.message_text }}",
"message_type": "={{ $json.message_type }}",
"timestamp": "={{ $json.timestamp }}",
"received_at": "={{ $json.received_at }}",
"direction": "inbound",
"classification": "",
"responded": "false"
},
"matchingColumns": [],
"schema": []
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000007",
"name": "Log Inbound Message",
"type": "n8n-nodes-base.n8nTable",
"typeVersion": 1,
"position": [
1100,
300
]
},
{
"parameters": {
"url": "={{ $('Extract Message Data').item.json.ollama_url || 'https://single-executives-dedicated-flying.trycloudflare.com' }}/api/chat",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"model\": \"gemma4:26b\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a message classifier for a service business (Coedwig Creations - woodworking, building, renovation, repairs). Classify the incoming WhatsApp message into EXACTLY ONE category:\\n\\n1. LEAD_INQUIRY - New potential customer asking about services, pricing, availability\\n2. BOOKING_REQUEST - Customer wants to book/schedule a job\\n3. QUOTE_REQUEST - Customer asking for a quote or estimate\\n4. FOLLOW_UP - Existing customer following up on previous conversation\\n5. PAYMENT - Related to invoicing or payment\\n6. GENERAL - General conversation, greeting, or unrelated\\n7. COMPLAINT - Customer expressing dissatisfaction\\n8. REFERRAL - Someone recommending or being referred\\n\\nRespond with ONLY a JSON object: {\\\"category\\\": \\\"CATEGORY_NAME\\\", \\\"confidence\\\": 0.0-1.0, \\\"is_lead\\\": true/false, \\\"urgency\\\": \\\"low/medium/high\\\", \\\"suggested_action\\\": \\\"brief action description\\\"}\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Message from {{ $('Extract Message Data').item.json.contact_name }}: {{ $('Extract Message Data').item.json.message_text }}\"\n }\n ],\n \"stream\": false,\n \"options\": {\n \"temperature\": 0.3,\n \"num_ctx\": 4096\n }\n}",
"options": {
"timeout": 120000
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000008",
"name": "Classify Message (Gemma4)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1100,
500
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Parse Gemma4 classification response\nconst response = $input.item.json;\nlet classification = {};\n\ntry {\n const content = response.message?.content || response.choices?.[0]?.message?.content || '';\n // Try to extract JSON from the response\n const jsonMatch = content.match(/\\{[^}]+\\}/);\n if (jsonMatch) {\n classification = JSON.parse(jsonMatch[0]);\n } else {\n classification = {\n category: 'GENERAL',\n confidence: 0.5,\n is_lead: false,\n urgency: 'low',\n suggested_action: 'No clear classification'\n };\n }\n} catch (e) {\n classification = {\n category: 'GENERAL',\n confidence: 0.3,\n is_lead: false,\n urgency: 'low',\n suggested_action: 'Classification failed - review manually'\n };\n}\n\nreturn {\n json: {\n ...classification,\n original_message: $('Extract Message Data').item.json\n }\n};"
},
"id": "a1b2c3d4-0001-4000-8000-000000000009",
"name": "Parse Classification",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1320,
500
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "is-lead",
"leftValue": "={{ $json.is_lead }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "true"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "a1b2c3d4-0001-4000-8000-000000000010",
"name": "Is Lead?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1540,
500
]
},
{
"parameters": {
"operation": "append",
"tableId": "wa_leads",
"columns": {
"mappingMode": "defineBelow",
"value": {
"phone": "={{ $json.original_message.from_phone }}",
"name": "={{ $json.original_message.contact_name }}",
"category": "={{ $json.category }}",
"urgency": "={{ $json.urgency }}",
"message_preview": "={{ $json.original_message.message_text.substring(0, 200) }}",
"suggested_action": "={{ $json.suggested_action }}",
"confidence": "={{ $json.confidence }}",
"status": "new",
"created_at": "={{ new Date().toISOString() }}",
"auto_responded": "false"
},
"matchingColumns": [],
"schema": []
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000011",
"name": "Log Lead",
"type": "n8n-nodes-base.n8nTable",
"typeVersion": 1,
"position": [
1760,
400
]
},
{
"parameters": {
"url": "https://single-executives-dedicated-flying.trycloudflare.com/api/chat",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"model\": \"gemma4:26b\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are the WhatsApp auto-responder for Coedwig Creations, a service business specializing in woodworking, building, renovations, and repairs based in Wales.\\n\\nCommunication style guidelines (learned from actual message history):\\n- Friendly, casual but professional tone\\n- Use 'mate' occasionally in greetings\\n- Be direct and helpful\\n- Keep messages concise for mobile reading\\n- Use emojis sparingly\\n- Always aim to move toward booking a job\\n- If asking about availability, suggest specific times\\n- For quotes, ask for details about the job (size, materials, timeline)\\n\\nIMPORTANT:\\n- This is an AUTO-REPLY. Include a note like 'I'll get back to you personally shortly' or 'Ashley will follow up with more details'\\n- Never make up prices or commit to specific dates without confirmation\\n- For urgent requests, mention you'll prioritise getting back to them\\n- Keep response under 300 characters for WhatsApp readability\\n\\nMessage category: {{ $json.category }}\\nUrgency: {{ $json.urgency }}\\nSuggested action: {{ $json.suggested_action }}\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Generate an auto-reply for this message from {{ $json.original_message.contact_name }}:\\n\\n{{ $json.original_message.message_text }}\"\n }\n ],\n \"stream\": false,\n \"options\": {\n \"temperature\": 0.7,\n \"num_ctx\": 4096\n }\n}",
"options": {
"timeout": 120000
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000012",
"name": "Generate Auto-Reply (Gemma4)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1980,
400
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Extract the reply text from Gemma4 response\nconst response = $input.item.json;\nconst replyText = response.message?.content || response.choices?.[0]?.message?.content || 'Thanks for your message! I\\'ll get back to you shortly.';\n\n// Clean up - remove quotes if wrapped\nlet cleanReply = replyText.trim();\nif (cleanReply.startsWith('\"') && cleanReply.endsWith('\"')) {\n cleanReply = cleanReply.slice(1, -1);\n}\n\n// Truncate for WhatsApp\nif (cleanReply.length > 1000) {\n cleanReply = cleanReply.substring(0, 997) + '...';\n}\n\nreturn {\n json: {\n reply_text: cleanReply,\n to_phone: $('Parse Classification').item.json.original_message.from_phone,\n phone_number_id: $('Parse Classification').item.json.original_message.phone_number_id,\n contact_name: $('Parse Classification').item.json.original_message.contact_name,\n category: $('Parse Classification').item.json.category\n }\n};"
},
"id": "a1b2c3d4-0001-4000-8000-000000000013",
"name": "Prepare Reply",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2200,
400
]
},
{
"parameters": {
"method": "POST",
"url": "=https://graph.facebook.com/v21.0/{{ $json.phone_number_id }}/messages",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"messaging_product\": \"whatsapp\",\n \"recipient_type\": \"individual\",\n \"to\": \"{{ $json.to_phone }}\",\n \"type\": \"text\",\n \"text\": {\n \"preview_url\": false,\n \"body\": {{ JSON.stringify($json.reply_text) }}\n }\n}",
"options": {
"timeout": 30000
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000014",
"name": "Send WhatsApp Reply",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2420,
400
],
"notes": "Uses Meta Graph API. Set up HTTP Header Auth credential with: Name=Authorization, Value=Bearer YOUR_META_API_KEY"
},
{
"parameters": {
"operation": "append",
"tableId": "wa_messages",
"columns": {
"mappingMode": "defineBelow",
"value": {
"message_id": "=auto_reply_{{ Date.now() }}",
"from_phone": "=business",
"contact_name": "=Coedwig Creations",
"message_text": "={{ $('Prepare Reply').item.json.reply_text }}",
"message_type": "auto_reply",
"timestamp": "={{ Math.floor(Date.now() / 1000) }}",
"received_at": "={{ new Date().toISOString() }}",
"direction": "outbound",
"classification": "={{ $('Parse Classification').item.json.category }}",
"responded": "true"
},
"matchingColumns": [],
"schema": []
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000015",
"name": "Log Outbound Reply",
"type": "n8n-nodes-base.n8nTable",
"typeVersion": 1,
"position": [
2640,
400
]
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 2
}
]
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000020",
"name": "Every 2 Hours",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
0,
900
]
},
{
"parameters": {
"method": "GET",
"url": "=https://graph.facebook.com/v21.0/961196760109668/conversations?fields=id,link,message_count,name,updated_time,can_reply,senders&access_token={{ encodeURIComponent('EAAU8x8cnnZCMBRCI95NAWlau8DirfJff2WtCPTyve8jH0zg8AEFCy3K3PpZBACYC7uhQtW8XrXgLhi42ZCaaYdJKBgZB8vs3C76ruL82fqB7UGbIPOVTo9oXAGxIWjW00w4SIDRK8We2vBG6TbJIq7ZCUXZA98oXXJZA8fLS6UDdMy07vhVJjgp0o9i8YubqcZBFzYae7r9eEAi0gwZDZD') }}",
"options": {
"timeout": 30000
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000021",
"name": "Fetch WhatsApp Conversations",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
220,
800
]
},
{
"parameters": {
"method": "GET",
"url": "=https://graph.facebook.com/v21.0/act_{{ '1474203620974579' }}/insights?fields=campaign_name,impressions,clicks,spend,actions,cost_per_action_type,ctr,cpc&date_preset=last_7d&level=campaign&access_token={{ encodeURIComponent('EAAU8x8cnnZCMBRCI95NAWlau8DirfJff2WtCPTyve8jH0zg8AEFCy3K3PpZBACYC7uhQtW8XrXgLhi42ZCaaYdJKBgZB8vs3C76ruL82fqB7UGbIPOVTo9oXAGxIWjW00w4SIDRK8We2vBG6TbJIq7ZCUXZA98oXXJZA8fLS6UDdMy07vhVJjgp0o9i8YubqcZBFzYae7r9eEAi0gwZDZD') }}",
"options": {
"timeout": 30000
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000022",
"name": "Fetch Ad Performance",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
220,
1000
]
},
{
"parameters": {
"method": "GET",
"url": "=https://graph.facebook.com/v21.0/961196760109668?fields=analytics.start({{ $now.minus({days: 7}).toFormat('yyyy-MM-dd') }}).end({{ $now.toFormat('yyyy-MM-dd') }}).granularity(DAY).phone_numbers([])&access_token={{ encodeURIComponent('EAAU8x8cnnZCMBRCI95NAWlau8DirfJff2WtCPTyve8jH0zg8AEFCy3K3PpZBACYC7uhQtW8XrXgLhi42ZCaaYdJKBgZB8vs3C76ruL82fqB7UGbIPOVTo9oXAGxIWjW00w4SIDRK8We2vBG6TbJIq7ZCUXZA98oXXJZA8fLS6UDdMy07vhVJjgp0o9i8YubqcZBFzYae7r9eEAi0gwZDZD') }}",
"options": {
"timeout": 30000
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000023",
"name": "Fetch WhatsApp Analytics",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
220,
1200
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Merge all analytics data for the report\nconst conversations = $('Fetch WhatsApp Conversations').first()?.json || {};\nconst adPerformance = $('Fetch Ad Performance').first()?.json || {};\nconst waAnalytics = $('Fetch WhatsApp Analytics').first()?.json || {};\n\nreturn {\n json: {\n conversations: JSON.stringify(conversations).substring(0, 3000),\n ad_performance: JSON.stringify(adPerformance).substring(0, 3000),\n wa_analytics: JSON.stringify(waAnalytics).substring(0, 3000),\n report_date: new Date().toISOString()\n }\n};"
},
"id": "a1b2c3d4-0001-4000-8000-000000000024",
"name": "Merge Analytics Data",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
500,
1000
]
},
{
"parameters": {
"url": "https://single-executives-dedicated-flying.trycloudflare.com/api/chat",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"model\": \"gemma4:26b\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a business analytics AI for Coedwig Creations, a service business (woodworking, building, renovations, repairs) in Wales.\\n\\nGenerate a concise business intelligence report covering:\\n1. LEAD ANALYSIS - New leads, conversion potential, follow-up priorities\\n2. AD PERFORMANCE - Which campaigns are working, cost per lead, ROI insights\\n3. CONVERSATION INSIGHTS - Response times, message patterns, customer sentiment\\n4. ACTION ITEMS - Top 5 specific actions to take right now\\n5. CONVERSION TIPS - Based on the data, how to convert more leads to paying clients\\n\\nFormat as a clean report with headers and bullet points. Be specific with numbers where available. Focus on actionable insights, not generic advice.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Generate a 2-hourly business report based on this data:\\n\\nWhatsApp Conversations: {{ $json.conversations }}\\n\\nAd Performance: {{ $json.ad_performance }}\\n\\nWhatsApp Analytics: {{ $json.wa_analytics }}\\n\\nReport time: {{ $json.report_date }}\"\n }\n ],\n \"stream\": false,\n \"options\": {\n \"temperature\": 0.5,\n \"num_ctx\": 8192\n }\n}",
"options": {
"timeout": 180000
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000025",
"name": "Generate Report (Gemma4)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
720,
1000
]
},
{
"parameters": {
"operation": "append",
"tableId": "wa_reports",
"columns": {
"mappingMode": "defineBelow",
"value": {
"report_date": "={{ $('Merge Analytics Data').item.json.report_date }}",
"report_content": "={{ $json.message?.content || 'Report generation failed' }}",
"report_type": "bi_report_2h",
"ad_data_snapshot": "={{ $('Merge Analytics Data').item.json.ad_performance.substring(0, 500) }}",
"wa_data_snapshot": "={{ $('Merge Analytics Data').item.json.wa_analytics.substring(0, 500) }}"
},
"matchingColumns": [],
"schema": []
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000026",
"name": "Store Report",
"type": "n8n-nodes-base.n8nTable",
"typeVersion": 1,
"position": [
940,
1000
]
},
{
"parameters": {
"method": "GET",
"url": "=https://graph.facebook.com/v21.0/961196760109668/message_templates?fields=name,status,language,category&access_token={{ encodeURIComponent('EAAU8x8cnnZCMBRCI95NAWlau8DirfJff2WtCPTyve8jH0zg8AEFCy3K3PpZBACYC7uhQtW8XrXgLhi42ZCaaYdJKBgZB8vs3C76ruL82fqB7UGbIPOVTo9oXAGxIWjW00w4SIDRK8We2vBG6TbJIq7ZCUXZA98oXXJZA8fLS6UDdMy07vhVJjgp0o9i8YubqcZBFzYae7r9eEAi0gwZDZD') }}",
"options": {
"timeout": 30000
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000030",
"name": "Fetch Message Templates",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
220,
1500
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Check for leads that need outreach\n// This would check the wa_leads table for leads marked as 'new' that haven't been contacted\n// For now, we build the outreach message structure\n\nconst templates = $input.item.json;\nconst availableTemplates = templates.data || [];\n\n// Find a suitable template for lead outreach\nlet outreachTemplate = availableTemplates.find(t => \n t.status === 'APPROVED' && \n (t.category === 'MARKETING' || t.category === 'UTILITY')\n);\n\nreturn {\n json: {\n has_templates: availableTemplates.length > 0,\n template_count: availableTemplates.length,\n outreach_template: outreachTemplate || null,\n templates_summary: availableTemplates.map(t => ({\n name: t.name,\n status: t.status,\n category: t.category\n }))\n }\n};"
},
"id": "a1b2c3d4-0001-4000-8000-000000000031",
"name": "Check Outreach Templates",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
1500
]
},
{
"parameters": {
"operation": "append",
"tableId": "wa_outreach_log",
"columns": {
"mappingMode": "defineBelow",
"value": {
"run_timestamp": "={{ new Date().toISOString() }}",
"templates_available": "={{ $json.template_count }}",
"outreach_template_used": "={{ $json.outreach_template?.name || 'none' }}",
"status": "checked"
},
"matchingColumns": [],
"schema": []
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000032",
"name": "Log Outreach Run",
"type": "n8n-nodes-base.n8nTable",
"typeVersion": 1,
"position": [
660,
1500
]
},
{
"parameters": {
"operation": "append",
"tableId": "wa_messages",
"columns": {
"mappingMode": "defineBelow",
"value": {
"message_id": "=non_lead_{{ Date.now() }}",
"from_phone": "={{ $('Extract Message Data').item.json.from_phone }}",
"contact_name": "={{ $('Extract Message Data').item.json.contact_name }}",
"message_text": "={{ $('Extract Message Data').item.json.message_text }}",
"message_type": "={{ $('Extract Message Data').item.json.message_type }}",
"timestamp": "={{ $('Extract Message Data').item.json.timestamp }}",
"received_at": "={{ $('Extract Message Data').item.json.received_at }}",
"direction": "inbound",
"classification": "={{ $json.category }}",
"responded": "false"
},
"matchingColumns": [],
"schema": []
}
},
"id": "a1b2c3d4-0001-4000-8000-000000000040",
"name": "Log Non-Lead Message",
"type": "n8n-nodes-base.n8nTable",
"typeVersion": 1,
"position": [
1760,
600
]
}
],
"connections": {
"WhatsApp Webhook": {
"main": [
[
{
"node": "Is Verification?",
"type": "main",
"index": 0
}
]
]
},
"Is Verification?": {
"main": [
[
{
"node": "Verify Token Response",
"type": "main",
"index": 0
}
],
[
{
"node": "ACK Message",
"type": "main",
"index": 0
}
]
]
},
"ACK Message": {
"main": [
[
{
"node": "Has Text Message?",
"type": "main",
"index": 0
}
]
]
},
"Has Text Message?": {
"main": [
[
{
"node": "Extract Message Data",
"type": "main",
"index": 0
}
],
[]
]
},
"Extract Message Data": {
"main": [
[
{
"node": "Log Inbound Message",
"type": "main",
"index": 0
},
{
"node": "Classify Message (Gemma4)",
"type": "main",
"index": 0
}
]
]
},
"Classify Message (Gemma4)": {
"main": [
[
{
"node": "Parse Classification",
"type": "main",
"index": 0
}
]
]
},
"Parse Classification": {
"main": [
[
{
"node": "Is Lead?",
"type": "main",
"index": 0
}
]
]
},
"Is Lead?": {
"main": [
[
{
"node": "Log Lead",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Non-Lead Message",
"type": "main",
"index": 0
}
]
]
},
"Log Lead": {
"main": [
[
{
"node": "Generate Auto-Reply (Gemma4)",
"type": "main",
"index": 0
}
]
]
},
"Generate Auto-Reply (Gemma4)": {
"main": [
[
{
"node": "Prepare Reply",
"type": "main",
"index": 0
}
]
]
},
"Prepare Reply": {
"main": [
[
{
"node": "Send WhatsApp Reply",
"type": "main",
"index": 0
}
]
]
},
"Send WhatsApp Reply": {
"main": [
[
{
"node": "Log Outbound Reply",
"type": "main",
"index": 0
}
]
]
},
"Every 2 Hours": {
"main": [
[
{
"node": "Fetch WhatsApp Conversations",
"type": "main",
"index": 0
},
{
"node": "Fetch Ad Performance",
"type": "main",
"index": 0
},
{
"node": "Fetch WhatsApp Analytics",
"type": "main",
"index": 0
},
{
"node": "Fetch Message Templates",
"type": "main",
"index": 0
}
]
]
},
"Fetch WhatsApp Conversations": {
"main": [
[
{
"node": "Merge Analytics Data",
"type": "main",
"index": 0
}
]
]
},
"Fetch Ad Performance": {
"main": [
[
{
"node": "Merge Analytics Data",
"type": "main",
"index": 0
}
]
]
},
"Fetch WhatsApp Analytics": {
"main": [
[
{
"node": "Merge Analytics Data",
"type": "main",
"index": 0
}
]
]
},
"Merge Analytics Data": {
"main": [
[
{
"node": "Generate Report (Gemma4)",
"type": "main",
"index": 0
}
]
]
},
"Generate Report (Gemma4)": {
"main": [
[
{
"node": "Store Report",
"type": "main",
"index": 0
}
]
]
},
"Fetch Message Templates": {
"main": [
[
{
"node": "Check Outreach Templates",
"type": "main",
"index": 0
}
]
]
},
"Check Outreach Templates": {
"main": [
[
{
"node": "Log Outreach Run",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true,
"callerPolicy": "workflowsFromSameOwner",
"errorWorkflow": ""
},
"staticData": null,
"tags": [],
"triggerCount": 2
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
WhatsApp Business Automation - Coedwig Creations. Uses n8nTable, httpRequest. Webhook trigger; 26 nodes.
Source: https://gist.github.com/Turkey-Dinosaur/7ee83f5219b222716b72946ead2cee7c — 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.
HR teams, IT Operations, and System Administrators managing employee onboarding at scale. It’s perfect if you use Odoo 18 to trigger account requests and need Redmine + GitLab accounts created instant
This workflow is a complete, production-ready solution for recovering abandoned carts in Shopify stores using a multi-channel, multi-touch approach. It automates personalized follow-ups via Email, SMS
qualiopi. Uses airtable, telegram, emailSend, httpRequest. Webhook trigger; 51 nodes.
This workflow automates end-to-end research analysis by coordinating multiple AI models—including NVIDIA NIM (Llama), OpenAI GPT-4, and Claude to analyze uploaded documents, extract insights, and gene
PsyCardv2. Uses executeCommand, telegram, readBinaryFile, googleDrive. Webhook trigger; 41 nodes.