{ "name": "🔄 Follow-up Automático | Leads Inativos WhatsApp", "nodes": [ { "parameters": { "rule": { "interval": [ { "field": "cronExpression", "value": "0 10 * * *" } ] } }, "id": "cron-trigger", "name": "Trigger Diário 10h", "type": "n8n-nodes-base.cron", "typeVersion": 1, "position": [240, 300] }, { "parameters": { "jsCode": "// Configurar parâmetros para busca de leads inativos\nconst today = new Date();\nconst threeDaysAgo = new Date(today.getTime() - (3 * 24 * 60 * 60 * 1000));\nconst sevenDaysAgo = new Date(today.getTime() - (7 * 24 * 60 * 60 * 1000));\n\nconst config = {\n three_days_ago: threeDaysAgo.toISOString().split('T')[0],\n seven_days_ago: sevenDaysAgo.toISOString().split('T')[0],\n today_date: today.toISOString().split('T')[0],\n search_statuses: ['Novo', 'Contactado', 'Qualificado', 'Em Análise'],\n timestamp: new Date().toISOString()\n};\n\nreturn config;" }, "id": "setup-search-config", "name": "Configurar Busca", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [460, 300] }, { "parameters": { "method": "GET", "url": "https://crm.memudecore.com.br/api/leads", "authentication": "predefinedCredentialType", "nodeCredentialType": "krayin-api", "sendQuery": true, "queryParameters": { "parameters": [ { "name": "limit", "value": "100" }, { "name": "sort", "value": "created_at" }, { "name": "order", "value": "desc" } ] }, "options": {} }, "id": "fetch-leads", "name": "Buscar Leads Recentes", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4, "position": [680, 300], "credentials": { "krayin-api": { "id": "krayin-crm-api", "name": "Krayin CRM API" } } }, { "parameters": { "jsCode": "// Filtrar leads que precisam de follow-up\nconst leadsData = $node[\"Buscar Leads Recentes\"].json;\nconst config = $node[\"Configurar Busca\"].json;\nconst leads = leadsData.data || [];\n\nconst today = new Date();\nconst threeDaysAgo = new Date(config.three_days_ago);\nconst sevenDaysAgo = new Date(config.seven_days_ago);\n\nconst leadsNeedingFollowup = [];\n\nfor (const lead of leads) {\n // Verificar data de criação/atualização\n const leadDate = new Date(lead.updated_at || lead.created_at);\n const daysSinceUpdate = Math.floor((today - leadDate) / (1000 * 60 * 60 * 24));\n \n // Verificar se tem telefone WhatsApp\n const contactPhone = lead.person?.contact_numbers?.[0]?.value;\n if (!contactPhone) continue;\n \n // Verificar se status permite follow-up\n const leadStatus = lead.stage?.name || 'Novo';\n const allowedStatuses = ['Novo', 'Contactado', 'Qualificado', 'Em Análise'];\n if (!allowedStatuses.includes(leadStatus)) continue;\n \n // Determinar tipo de follow-up baseado nos dias\n let followupType = null;\n let message = null;\n \n if (daysSinceUpdate >= 3 && daysSinceUpdate < 7) {\n followupType = 'FIRST_FOLLOWUP';\n message = `Olá ${lead.person?.name || 'Cliente'}! 👋 Notei que você demonstrou interesse em nossos serviços. Tem alguma dúvida que posso esclarecer? Estou aqui para ajudar! 😊`;\n } else if (daysSinceUpdate >= 7 && daysSinceUpdate < 14) {\n followupType = 'SECOND_FOLLOWUP';\n message = `Oi ${lead.person?.name || 'Cliente'}! 🌟 Ainda está interessado(a) em conhecer melhor nossos serviços? Preparei algumas informações especiais que podem te interessar. Posso compartilhar?`;\n } else if (daysSinceUpdate >= 14 && daysSinceUpdate < 30) {\n followupType = 'FINAL_FOLLOWUP';\n message = `${lead.person?.name || 'Cliente'}, espero que esteja bem! 🙏 Sei que às vezes a rotina é corrida. Se ainda tiver interesse em nossos serviços, estarei sempre aqui. Tenha uma ótima semana! ✨`;\n }\n \n if (followupType && message) {\n // Formatar telefone para WhatsApp\n let formattedPhone = contactPhone.replace(/\\D/g, '');\n if (!formattedPhone.startsWith('55') && formattedPhone.length === 11) {\n formattedPhone = '55' + formattedPhone;\n }\n formattedPhone += '@s.whatsapp.net';\n \n leadsNeedingFollowup.push({\n lead_id: lead.id,\n lead_title: lead.title,\n contact_name: lead.person?.name || 'Cliente',\n contact_phone: contactPhone,\n whatsapp_phone: formattedPhone,\n lead_status: leadStatus,\n days_since_update: daysSinceUpdate,\n followup_type: followupType,\n message: message,\n lead_value: lead.lead_value || 0,\n created_at: lead.created_at,\n updated_at: lead.updated_at\n });\n }\n}\n\nreturn {\n total_leads_checked: leads.length,\n leads_needing_followup: leadsNeedingFollowup.length,\n leads: leadsNeedingFollowup,\n timestamp: new Date().toISOString()\n};" }, "id": "filter-leads-followup", "name": "Filtrar Leads para Follow-up", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [900, 300] }, { "parameters": { "conditions": { "number": [ { "value1": "={{$node[\"Filtrar Leads para Follow-up\"].json[\"leads_needing_followup\"]}}", "operation": "equal", "value2": 0 } ] } }, "id": "has-leads-followup", "name": "Tem Leads p/ Follow-up?", "type": "n8n-nodes-base.if", "typeVersion": 1, "position": [1120, 300] }, { "parameters": { "fieldToSplitOut": "leads", "options": {} }, "id": "split-leads", "name": "Dividir Leads", "type": "n8n-nodes-base.splitOut", "typeVersion": 1, "position": [1340, 200] }, { "parameters": { "method": "POST", "url": "https://evolution.memudecore.com.br/message/sendText/default", "authentication": "predefinedCredentialType", "nodeCredentialType": "evolution-api", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "bodyParameters": { "parameters": [ { "name": "number", "value": "={{$node[\"Dividir Leads\"].json[\"whatsapp_phone\"]}}" }, { "name": "text", "value": "={{$node[\"Dividir Leads\"].json[\"message\"]}}" } ] }, "options": {} }, "id": "send-followup-message", "name": "Enviar Follow-up WhatsApp", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4, "position": [1560, 200], "credentials": { "evolution-api": { "id": "evolution-whatsapp-api", "name": "Evolution WhatsApp API" } } }, { "parameters": { "jsCode": "// Aguardar 2 segundos entre mensagens para não sobrecarregar a API\nreturn new Promise(resolve => {\n setTimeout(() => {\n resolve({ waited: true, timestamp: new Date().toISOString() });\n }, 2000);\n});" }, "id": "wait-between-messages", "name": "Aguardar 2s", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [1780, 200] }, { "parameters": { "jsCode": "// Log detalhado do follow-up enviado\nconst leadData = $node[\"Dividir Leads\"].json;\nconst sendResult = $node[\"Enviar Follow-up WhatsApp\"].json;\n\nconst logEntry = {\n timestamp: new Date().toISOString(),\n action: 'FOLLOWUP_SENT',\n lead_id: leadData.lead_id,\n contact_name: leadData.contact_name,\n contact_phone: leadData.contact_phone,\n followup_type: leadData.followup_type,\n days_since_update: leadData.days_since_update,\n message_sent: leadData.message,\n whatsapp_response: sendResult,\n success: sendResult?.status === 'pending' || sendResult?.id ? true : false,\n error: sendResult?.error || null\n};\n\nreturn logEntry;" }, "id": "log-followup", "name": "Log Follow-up", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [2000, 200] }, { "parameters": { "mode": "append", "fileName": "/tmp/whatsapp-followup-log.txt", "fileContent": "={{JSON.stringify($node[\"Log Follow-up\"].json, null, 2)}}\n---\n" }, "id": "save-followup-log", "name": "Salvar Log Follow-up", "type": "n8n-nodes-base.writeFile", "typeVersion": 1, "position": [2220, 200] }, { "parameters": { "jsCode": "// Gerar resumo da execução\nconst searchData = $node[\"Filtrar Leads para Follow-up\"].json;\n\nconst summaryLog = {\n timestamp: new Date().toISOString(),\n action: 'FOLLOWUP_EXECUTION_SUMMARY',\n total_leads_checked: searchData.total_leads_checked,\n leads_needing_followup: searchData.leads_needing_followup,\n execution_date: new Date().toLocaleDateString('pt-BR'),\n execution_time: new Date().toLocaleTimeString('pt-BR'),\n status: searchData.leads_needing_followup > 0 ? 'FOLLOWUPS_SENT' : 'NO_FOLLOWUPS_NEEDED'\n};\n\nreturn summaryLog;" }, "id": "generate-summary-no-leads", "name": "Gerar Resumo (Sem Leads)", "type": "n8n-nodes-base.code", "typeVersion": 1, "position": [1340, 400] }, { "parameters": { "mode": "append", "fileName": "/tmp/whatsapp-followup-log.txt", "fileContent": "={{JSON.stringify($node[\"Gerar Resumo (Sem Leads)\"].json, null, 2)}}\n---\n" }, "id": "save-summary-no-leads", "name": "Salvar Resumo (Sem Leads)", "type": "n8n-nodes-base.writeFile", "typeVersion": 1, "position": [1560, 400] } ], "connections": { "Trigger Diário 10h": { "main": [ [ { "node": "Configurar Busca", "type": "main", "index": 0 } ] ] }, "Configurar Busca": { "main": [ [ { "node": "Buscar Leads Recentes", "type": "main", "index": 0 } ] ] }, "Buscar Leads Recentes": { "main": [ [ { "node": "Filtrar Leads para Follow-up", "type": "main", "index": 0 } ] ] }, "Filtrar Leads para Follow-up": { "main": [ [ { "node": "Tem Leads p/ Follow-up?", "type": "main", "index": 0 } ] ] }, "Tem Leads p/ Follow-up?": { "main": [ [ { "node": "Gerar Resumo (Sem Leads)", "type": "main", "index": 0 } ], [ { "node": "Dividir Leads", "type": "main", "index": 0 } ] ] }, "Dividir Leads": { "main": [ [ { "node": "Enviar Follow-up WhatsApp", "type": "main", "index": 0 } ] ] }, "Enviar Follow-up WhatsApp": { "main": [ [ { "node": "Aguardar 2s", "type": "main", "index": 0 } ] ] }, "Aguardar 2s": { "main": [ [ { "node": "Log Follow-up", "type": "main", "index": 0 } ] ] }, "Log Follow-up": { "main": [ [ { "node": "Salvar Log Follow-up", "type": "main", "index": 0 } ] ] }, "Gerar Resumo (Sem Leads)": { "main": [ [ { "node": "Salvar Resumo (Sem Leads)", "type": "main", "index": 0 } ] ] } }, "active": false, "settings": {}, "versionId": "1", "meta": { "instanceId": "followup-automatico" }, "id": "3", "tags": [ "Follow-up", "WhatsApp", "CRM", "Automático", "Sem Slack" ] }