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.
Flujowhatsapp. Uses @aldinokemal2104/n8n-nodes-gowa, postgres, httpRequest. Webhook trigger; 65 nodes.
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
WF_UNIFIED_LEGAL_AUTOMATION. Uses googleSheets, httpRequest, telegram, telegramTrigger. Webhook trigger; 53 nodes.
Backbrief: transcripts (Zoom webhook -> Slack + vault). Uses httpRequest, slack. Webhook trigger; 52 nodes.