{
  "name": "Captador de leads con clasificación por IA — AI Automation Élite Academy",
  "nodes": [
    {
      "parameters": {
        "content": "## Captador de leads con clasificación por IA\n\nCortesía de masterdeagentesia.com\n\n**Cómo usarlo**\n1. Importa este archivo en n8n (menú superior derecho → Import from File).\n2. Abre el nodo *Clasificar con IA* y conecta tu credencial de OpenAI.\n3. Pulsa *Test workflow* y envía un POST al webhook con: `{ \"nombre\": \"Ana\", \"email\": \"ana@empresa.com\", \"mensaje\": \"Necesito automatizar los presupuestos\" }`\n4. Conecta la salida a donde guardes tus leads (Sheets, Airtable, tu CRM o una base de datos).\n\n**Qué hace**\nRecibe el lead, valida el email, lo clasifica por intención de compra con IA y lo separa en caliente o frío para que cada uno reciba un trato distinto.",
        "height": 420,
        "width": 460,
        "color": 4
      },
      "id": "sticky-intro",
      "name": "Léeme primero",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [-380, -40]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "captador-leads",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "wh-entrada",
      "name": "Entrada del lead",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [140, 180],
      "webhookId": "captador-leads-demo"
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Normaliza y valida antes de gastar una llamada a la IA.\nconst d = $json.body || $json;\n\nconst email = String(d.email || '').trim().toLowerCase();\nconst nombre = String(d.nombre || d.name || '').trim();\nconst mensaje = String(d.mensaje || d.message || '').trim();\n\nconst emailValido = /^[^@\\s]+@[^@\\s]+\\.[^@\\s]{2,}$/.test(email);\n\n// Los dominios gratuitos no descalifican a nadie, pero son una señal útil.\nconst dominio = email.split('@')[1] || '';\nconst esDominioGratuito = ['gmail.com','hotmail.com','outlook.com','yahoo.com','icloud.com'].includes(dominio);\n\nreturn {\n  json: {\n    nombre,\n    email,\n    mensaje,\n    dominio,\n    esDominioGratuito,\n    emailValido,\n    recibidoEn: new Date().toISOString()\n  }\n};"
      },
      "id": "code-validar",
      "name": "Validar y normalizar",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [360, 180]
    },
    {
      "parameters": {
        "conditions": {
          "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 },
          "conditions": [
            {
              "id": "cond-email",
              "leftValue": "={{ $json.emailValido }}",
              "rightValue": "",
              "operator": { "type": "boolean", "operation": "true", "singleValue": true }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "if-valido",
      "name": "¿Email válido?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [580, 180]
    },
    {
      "parameters": {
        "modelId": { "__rl": true, "value": "gpt-4o-mini", "mode": "list", "cachedResultName": "gpt-4o-mini" },
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "Clasificas leads de una empresa que vende automatizaciones con IA.\n\nDevuelve SOLO un objeto JSON, sin texto alrededor:\n{\"intencion\":\"alta|media|baja\",\"motivo\":\"una frase corta\",\"resumen\":\"el problema del lead en 12 palabras\"}\n\nCriterio:\n- alta: describe un problema concreto, menciona urgencia, presupuesto, volumen o un proceso identificable.\n- media: interés real pero vago, sin problema concreto.\n- baja: mensaje vacío, genérico, spam o una petición de trabajo."
            },
            {
              "role": "user",
              "content": "=Nombre: {{ $json.nombre }}\nEmail: {{ $json.email }}\nDominio gratuito: {{ $json.esDominioGratuito }}\nMensaje: {{ $json.mensaje }}"
            }
          ]
        },
        "jsonOutput": true,
        "options": { "temperature": 0 }
      },
      "id": "ai-clasificar",
      "name": "Clasificar con IA",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [820, 80]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// La IA puede devolver el JSON dentro de message.content o ya parseado.\n// Nunca confíes en que venga limpio: si falla, el lead no se pierde.\nconst lead = $('Validar y normalizar').item.json;\nlet salida = $json.message?.content ?? $json;\n\nif (typeof salida === 'string') {\n  try {\n    salida = JSON.parse(salida.replace(/```json|```/g, '').trim());\n  } catch (e) {\n    salida = { intencion: 'media', motivo: 'No se pudo interpretar la respuesta de la IA', resumen: '' };\n  }\n}\n\nconst intencion = ['alta','media','baja'].includes(salida.intencion) ? salida.intencion : 'media';\n\nreturn {\n  json: {\n    ...lead,\n    intencion,\n    motivo: salida.motivo || '',\n    resumen: salida.resumen || ''\n  }\n};"
      },
      "id": "code-parsear",
      "name": "Interpretar la respuesta",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [1040, 80]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "caliente",
              "conditions": {
                "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 },
                "conditions": [
                  {
                    "id": "cond-alta",
                    "leftValue": "={{ $json.intencion }}",
                    "rightValue": "alta",
                    "operator": { "type": "string", "operation": "equals" }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "options": { "fallbackOutput": "extra", "renameFallbackOutput": "resto" }
      },
      "id": "switch-intencion",
      "name": "Separar por intención",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [1260, 80]
    },
    {
      "parameters": {},
      "id": "noop-caliente",
      "name": "Lead caliente → avísate ya",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [1500, -20]
    },
    {
      "parameters": {},
      "id": "noop-resto",
      "name": "Resto → secuencia de nurturing",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [1500, 160]
    },
    {
      "parameters": {},
      "id": "noop-descartado",
      "name": "Email inválido → descartar",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [820, 320]
    },
    {
      "parameters": {
        "content": "### Conecta aquí tu destino\n\nSustituye estos dos nodos vacíos por lo que uses:\n\n- **Caliente**: Telegram, Slack o email a ti mismo. Un lead con intención alta que espera 24 h ya no está caliente.\n- **Resto**: Google Sheets, Airtable, Supabase o tu CRM, y una secuencia de emails.\n\nEl coste de clasificar con gpt-4o-mini es de céntimos por cada mil leads.",
        "height": 280,
        "width": 380,
        "color": 7
      },
      "id": "sticky-destino",
      "name": "Siguiente paso",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [1460, -220]
    },
    {
      "parameters": {
        "content": "### Rompe esto a propósito\n\nQuita el try/catch del nodo *Interpretar la respuesta* y manda un mensaje raro. Verás cómo el workflow entero se cae por una comilla.\n\nEso es exactamente lo que separa un workflow de demo de uno que aguanta en producción.\n\nEn el máster, cada módulo termina así: explícalo, pruébalo, diagnostica el fallo.",
        "height": 260,
        "width": 380,
        "color": 3
      },
      "id": "sticky-romper",
      "name": "Ejercicio",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [1000, 380]
    }
  ],
  "connections": {
    "Entrada del lead": { "main": [[{ "node": "Validar y normalizar", "type": "main", "index": 0 }]] },
    "Validar y normalizar": { "main": [[{ "node": "¿Email válido?", "type": "main", "index": 0 }]] },
    "¿Email válido?": {
      "main": [
        [{ "node": "Clasificar con IA", "type": "main", "index": 0 }],
        [{ "node": "Email inválido → descartar", "type": "main", "index": 0 }]
      ]
    },
    "Clasificar con IA": { "main": [[{ "node": "Interpretar la respuesta", "type": "main", "index": 0 }]] },
    "Interpretar la respuesta": { "main": [[{ "node": "Separar por intención", "type": "main", "index": 0 }]] },
    "Separar por intención": {
      "main": [
        [{ "node": "Lead caliente → avísate ya", "type": "main", "index": 0 }],
        [{ "node": "Resto → secuencia de nurturing", "type": "main", "index": 0 }]
      ]
    }
  },
  "settings": { "executionOrder": "v1" },
  "pinData": {},
  "meta": { "instanceId": "masterdeagentesia-lead-magnet" }
}
