{ "name": "Lead automatisch mit Firmendaten anreichern und bewerten", "meta": { "beschreibung": "Nimmt einen neuen Lead per Webhook entgegen, leitet aus der E-Mail-Adresse die Firmendomain ab und trennt Geschaeftsadressen von Freemail-Adressen (gmail.com, gmx.de, web.de und Co. werden als Privatperson markiert). Fuer Firmenadressen holt der Workflow ueber eine Anreicherungs-API Stammdaten nach, laesst die KI Branche und Unternehmensgroesse einordnen und berechnet einen nachvollziehbaren Lead-Score, bevor der Datensatz ins CRM geschrieben wird. Lohnt sich fuer Vertriebsteams, die viele Leads bekommen und die guten schnell erkennen muessen. DSGVO/EU-AI-Act-Hinweis: Die Anreicherung verarbeitet personenbezogene Daten bei Dritten — AV-Vertrag nach Art. 28 DSGVO schliessen; der Score ist eine Priorisierungshilfe fuer den Vertrieb und darf keine automatisierte Einzelentscheidung nach Art. 22 DSGVO ausloesen.", "kategorie": "Vertrieb & Leads", "schwierigkeit": "fortgeschritten", "benoetigt": ["Webhook-Quelle (Formular, CRM, Newsletter)", "Anreicherungs-API fuer Firmendaten", "OpenAI-API (oder Ollama)", "CRM mit REST-API", "SMTP-Postfach"], "quelle": "https://die-ki-agentur.de/n8n-agentur/" }, "nodes": [ { "parameters": { "content": "## Lead-Anreicherung und Scoring\n\n**Ablauf:** Neuer Lead per Webhook → E-Mail-Domain extrahieren → Freemailer aussortieren → Firmendaten ueber API nachladen → KI ordnet Branche und Groesse ein → Lead-Score berechnen → CRM. A-Leads gehen zusaetzlich direkt an den Vertrieb.\n\n**Vor dem Start:**\n1. Webhook-URL aus `Neuen Lead empfangen` bei der Lead-Quelle eintragen (POST, JSON mit `email`, optional `name`, `firma`, `telefon`, `nachricht`, `quelle`)\n2. In `Firmendaten abrufen` `HIER_ANREICHERUNGS_API_URL` und `HIER_API_KEY_EINTRAGEN` ersetzen (z. B. Clearbit, Hunter.io, Companyhouse — Anbieter mit EU-Hosting bevorzugen)\n3. OpenAI-Credential waehlen oder den Node auf ein lokales Ollama-Modell umstellen\n4. In `Lead im CRM anlegen` die CRM-URL setzen; Punktlogik im Node `Lead-Score berechnen` an die eigene Zielkundschaft anpassen\n5. AV-Vertraege mit Anreicherungs- und KI-Anbieter; der Score priorisiert nur, er entscheidet nicht\n\n**Fehlertoleranz:** Antwortet die Anreicherungs-API nicht, laeuft der Lead trotzdem weiter — er bekommt dann nur den Score aus den eigenen Formularangaben.\n\n**Betreuung:** https://die-ki-agentur.de/n8n-agentur/", "height": 580, "width": 480 }, "id": "note-doku", "name": "Kurzanleitung", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [-160, 40] }, { "parameters": { "httpMethod": "POST", "path": "neuer-lead", "responseMode": "lastNode", "options": {} }, "id": "trigger-webhook", "name": "Neuen Lead empfangen", "type": "n8n-nodes-base.webhook", "typeVersion": 2, "position": [380, 320] }, { "parameters": { "jsCode": "// Die E-Mail-Domain ist der guenstigste Firmenschluessel, den ein Lead\n// mitbringt: keine Zusatzabfrage noetig, und sie ist eindeutiger als ein\n// frei getippter Firmenname (\"Mueller GmbH\" vs. \"Müller G.m.b.H.\").\nconst FREEMAILER = [\n 'gmail.com', 'googlemail.com', 'gmx.de', 'gmx.net', 'gmx.at', 'gmx.ch',\n 'web.de', 'freenet.de', 't-online.de', 'outlook.de', 'outlook.com',\n 'hotmail.de', 'hotmail.com', 'live.de', 'yahoo.de', 'yahoo.com',\n 'aol.com', 'icloud.com', 'me.com', 'mail.de', 'posteo.de', 'protonmail.com', 'proton.me'\n];\n// Wegwerfadressen sind kein Privatkunde, sondern meist gar kein Lead —\n// deshalb getrennt gefuehrt und im Score spaeter bestraft.\nconst WEGWERF = ['mailinator.com', 'trashmail.com', 'wegwerfmail.de', '10minutemail.com', 'yopmail.com'];\n\nconst raus = [];\nfor (const eintrag of $input.all()) {\n const d = eintrag.json.body ?? eintrag.json;\n const email = String(d.email ?? '').trim().toLowerCase();\n const domain = email.includes('@') ? email.split('@').pop() : '';\n // Subdomains wie mail.firma.de auf die Hauptdomain zurueckfuehren, sonst\n // findet die Anreicherungs-API den Betrieb nicht.\n const teile = domain.split('.');\n const hauptdomain = teile.length > 2 && teile[teile.length - 2].length > 3\n ? teile.slice(-2).join('.')\n : domain;\n\n raus.push({\n json: {\n name: String(d.name ?? '').trim(),\n email,\n telefon: String(d.telefon ?? d.phone ?? '').replace(/[^0-9+]/g, ''),\n firma_angegeben: String(d.firma ?? d.company ?? '').trim(),\n nachricht: String(d.nachricht ?? d.message ?? '').trim(),\n quelle: String(d.quelle ?? 'Unbekannt').trim(),\n domain,\n hauptdomain,\n ist_freemailer: FREEMAILER.includes(domain),\n ist_wegwerfadresse: WEGWERF.includes(domain),\n eingegangen_am: new Date().toLocaleDateString('de-DE')\n }\n });\n}\nreturn raus;" }, "id": "code-domain", "name": "E-Mail-Domain extrahieren", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [600, 320] }, { "parameters": { "conditions": { "options": {"caseSensitive": true, "version": 2}, "conditions": [ { "id": "kein-freemailer", "leftValue": "={{ $json.ist_freemailer }}", "rightValue": true, "operator": {"type": "boolean", "operation": "false", "singleValue": true} }, { "id": "domain-vorhanden", "leftValue": "={{ $json.hauptdomain }}", "rightValue": "", "operator": {"type": "string", "operation": "notEmpty", "singleValue": true} } ], "combinator": "and" }, "options": {} }, "id": "if-freemail", "name": "Geschaeftliche Domain?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [820, 320] }, { "parameters": { "method": "GET", "url": "https://HIER_ANREICHERUNGS_API_URL/v1/firmen", "sendQuery": true, "queryParameters": { "parameters": [ {"name": "domain", "value": "={{ $json.hauptdomain }}"} ] }, "sendHeaders": true, "headerParameters": { "parameters": [ {"name": "X-Api-Key", "value": "HIER_API_KEY_EINTRAGEN"}, {"name": "Accept", "value": "application/json"} ] }, "options": {"timeout": 20000} }, "id": "http-anreicherung", "name": "Firmendaten abrufen", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [1040, 180], "onError": "continueRegularOutput" }, { "parameters": { "modelId": {"__rl": true, "value": "gpt-4.1-mini", "mode": "list"}, "messages": { "values": [ { "role": "system", "content": "Du ordnest deutsche Firmen fuer den B2B-Vertrieb ein. Antworte AUSSCHLIESSLICH mit einem JSON-Objekt, keine Erklaerung, kein Markdown. Felder: branche (string, deutsche Bezeichnung wie 'Maschinenbau', 'Handwerk', 'Kanzlei', 'Handel', 'IT-Dienstleistung', 'Gesundheitswesen', 'Oeffentliche Hand', 'Sonstige'), unternehmensgroesse (string, genau einer von: 'Solo', 'Klein (2-9)', 'Mittel (10-49)', 'Gross (50-249)', 'Konzern (250+)'), mitarbeiter_geschaetzt (number oder null), b2b (boolean), begruendung (string, maximal 20 Woerter). Wenn die Datenlage nicht reicht, setze branche auf 'Sonstige' und unternehmensgroesse auf 'Klein (2-9)' und schreibe das in die Begruendung. Rate nichts hinzu, was nicht in den Daten steht." }, { "role": "user", "content": "=Domain: {{ $('E-Mail-Domain extrahieren').item.json.hauptdomain }}\nFirmenname laut Formular: {{ $('E-Mail-Domain extrahieren').item.json.firma_angegeben || 'nicht angegeben' }}\nNachricht des Leads: {{ $('E-Mail-Domain extrahieren').item.json.nachricht || 'keine' }}\n\nDaten der Anreicherungs-API:\n{{ JSON.stringify($json).slice(0, 3000) }}" } ] }, "jsonOutput": true, "options": {"temperature": 0} }, "id": "ki-einordnen", "name": "Branche und Groesse einordnen", "type": "@n8n/n8n-nodes-langchain.openAi", "typeVersion": 1.8, "position": [1260, 180] }, { "parameters": { "assignments": { "assignments": [ {"id": "typ", "name": "kontakttyp", "value": "Privatperson", "type": "string"}, {"id": "branche", "name": "branche", "value": "Privatkunde", "type": "string"}, {"id": "groesse", "name": "unternehmensgroesse", "value": "Solo", "type": "string"}, {"id": "b2b", "name": "b2b", "value": false, "type": "boolean"}, {"id": "grund", "name": "einordnung_begruendung", "value": "=Freemail-Adresse ({{ $json.domain }}) — keine Firmenanreicherung moeglich", "type": "string"} ] }, "includeOtherFields": true, "options": {} }, "id": "set-privatperson", "name": "Als Privatperson markieren", "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [1040, 500] }, { "parameters": { "jsCode": "// Lead-Score 0-100, bewusst additiv und einzeln begruendet: Der Vertrieb\n// sieht im CRM nicht nur die Zahl, sondern auch, welche Regel wie viele\n// Punkte gegeben hat. Nur so laesst sich die Gewichtung spaeter ehrlich\n// nachjustieren - eine Blackbox-Zahl wuerde nach zwei Wochen ignoriert.\nconst GROESSE_PUNKTE = {\n 'Solo': 5,\n 'Klein (2-9)': 10,\n 'Mittel (10-49)': 25,\n 'Gross (50-249)': 30,\n 'Konzern (250+)': 20 // absichtlich weniger: lange Einkaufsprozesse\n};\n// Wunschbranchen des eigenen Betriebs - hier anpassen, das ist der\n// wirksamste Hebel des ganzen Workflows.\nconst WUNSCHBRANCHEN = ['Maschinenbau', 'Handwerk', 'IT-Dienstleistung', 'Handel'];\n\nconst raus = [];\nfor (const eintrag of $input.all()) {\n const basis = $('E-Mail-Domain extrahieren').item.json;\n const j = eintrag.json;\n // Der KI-Node liefert je nach Version message.content oder das Objekt\n // direkt; der Freemail-Zweig liefert bereits fertige Felder.\n const ki = j.message?.content ?? j;\n\n const branche = String(ki.branche ?? j.branche ?? 'Sonstige');\n const groesse = String(ki.unternehmensgroesse ?? j.unternehmensgroesse ?? 'Klein (2-9)');\n const istB2B = Boolean(ki.b2b ?? j.b2b ?? false);\n\n let punkte = 0;\n const begruendung = [];\n const addiere = (p, text) => { punkte += p; begruendung.push((p >= 0 ? '+' : '') + p + ' ' + text); };\n\n if (istB2B) addiere(15, 'Geschaeftskunde');\n else addiere(0, 'Privatkunde oder B2B unklar');\n\n addiere(GROESSE_PUNKTE[groesse] ?? 5, 'Unternehmensgroesse: ' + groesse);\n\n if (WUNSCHBRANCHEN.includes(branche)) addiere(20, 'Wunschbranche: ' + branche);\n else addiere(5, 'Branche ausserhalb des Kernsegments: ' + branche);\n\n // Wer eine Telefonnummer hinterlaesst, rechnet mit einem Rueckruf -\n // in der Praxis das staerkste einzelne Kaufsignal im Formular.\n if (basis.telefon && basis.telefon.length >= 7) addiere(15, 'Telefonnummer hinterlassen');\n\n const laenge = (basis.nachricht || '').length;\n if (laenge >= 200) addiere(15, 'ausfuehrliche Anfrage (' + laenge + ' Zeichen)');\n else if (laenge >= 50) addiere(8, 'konkrete Anfrage (' + laenge + ' Zeichen)');\n else addiere(0, 'kaum Text in der Anfrage');\n\n // Kaufabsicht im Klartext schlaegt jede Firmenkennzahl.\n const signale = ['angebot', 'preis', 'kosten', 'anfrage', 'kaufen', 'beauftragen', 'termin', 'beratung'];\n const treffer = signale.filter(s => (basis.nachricht || '').toLowerCase().includes(s));\n if (treffer.length) addiere(Math.min(15, treffer.length * 5), 'Kaufsignal(e): ' + treffer.join(', '));\n\n if (basis.ist_wegwerfadresse) addiere(-40, 'Wegwerf-Mailadresse');\n if (!basis.name) addiere(-10, 'kein Name angegeben');\n\n punkte = Math.max(0, Math.min(100, punkte));\n const prioritaet = punkte >= 60 ? 'A' : punkte >= 35 ? 'B' : 'C';\n\n raus.push({\n json: {\n ...basis,\n kontakttyp: j.kontakttyp ?? (istB2B ? 'Firma' : 'Unklar'),\n branche,\n unternehmensgroesse: groesse,\n mitarbeiter_geschaetzt: ki.mitarbeiter_geschaetzt ?? null,\n b2b: istB2B,\n einordnung_begruendung: ki.begruendung ?? j.einordnung_begruendung ?? '',\n lead_score: punkte,\n prioritaet,\n score_begruendung: begruendung.join('; ')\n }\n });\n}\nreturn raus;" }, "id": "code-score", "name": "Lead-Score berechnen", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [1480, 320] }, { "parameters": { "method": "POST", "url": "https://HIER_CRM_API_URL/v1/leads", "sendHeaders": true, "headerParameters": { "parameters": [ {"name": "X-Api-Key", "value": "HIER_CRM_API_KEY_EINTRAGEN"}, {"name": "Content-Type", "value": "application/json"} ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({\n name: $json.name,\n email: $json.email,\n telefon: $json.telefon,\n firma: $json.firma_angegeben,\n domain: $json.hauptdomain,\n kontakttyp: $json.kontakttyp,\n branche: $json.branche,\n unternehmensgroesse: $json.unternehmensgroesse,\n lead_score: $json.lead_score,\n prioritaet: $json.prioritaet,\n score_begruendung: $json.score_begruendung,\n quelle: $json.quelle,\n nachricht: $json.nachricht,\n eingegangen_am: $json.eingegangen_am\n}) }}", "options": {"timeout": 15000} }, "id": "http-crm", "name": "Lead im CRM anlegen", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [1700, 320] }, { "parameters": { "conditions": { "options": {"caseSensitive": true, "version": 2}, "conditions": [ { "id": "prio-a", "leftValue": "={{ $('Lead-Score berechnen').item.json.prioritaet }}", "rightValue": "A", "operator": {"type": "string", "operation": "equals"} } ], "combinator": "and" }, "options": {} }, "id": "if-prioritaet", "name": "Prioritaet A?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [1920, 320] }, { "parameters": { "fromEmail": "HIER_ABSENDER_MAIL_EINTRAGEN", "toEmail": "HIER_VERTRIEB_MAIL_EINTRAGEN", "subject": "=A-Lead ({{ $('Lead-Score berechnen').item.json.lead_score }} Punkte): {{ $('Lead-Score berechnen').item.json.firma_angegeben || $('Lead-Score berechnen').item.json.hauptdomain }}", "emailFormat": "text", "text": "=Neuer Lead mit hoher Prioritaet — bitte heute noch anrufen.\n\nName: {{ $('Lead-Score berechnen').item.json.name || '-' }}\nFirma: {{ $('Lead-Score berechnen').item.json.firma_angegeben || $('Lead-Score berechnen').item.json.hauptdomain }}\nBranche: {{ $('Lead-Score berechnen').item.json.branche }}\nGroesse: {{ $('Lead-Score berechnen').item.json.unternehmensgroesse }}\nE-Mail: {{ $('Lead-Score berechnen').item.json.email }}\nTelefon: {{ $('Lead-Score berechnen').item.json.telefon || '-' }}\nQuelle: {{ $('Lead-Score berechnen').item.json.quelle }}\n\nAnfrage:\n{{ $('Lead-Score berechnen').item.json.nachricht || '-' }}\n\nScore {{ $('Lead-Score berechnen').item.json.lead_score }}/100 setzt sich zusammen aus:\n{{ $('Lead-Score berechnen').item.json.score_begruendung }}\n\nHinweis: Score und Brancheneinordnung sind KI-gestuetzt und dienen der Priorisierung — bitte vor dem Gespraech kurz gegenpruefen.", "options": {} }, "id": "mail-vertrieb", "name": "Vertrieb sofort informieren", "type": "n8n-nodes-base.emailSend", "typeVersion": 2.1, "position": [2140, 220] }, { "parameters": { "assignments": { "assignments": [ {"id": "ablage", "name": "bearbeitung", "value": "=Im Nurturing belassen (Prioritaet {{ $('Lead-Score berechnen').item.json.prioritaet }}) — Newsletter-Strecke statt Direktansprache", "type": "string"}, {"id": "wv", "name": "wiedervorlage_in_tagen", "value": "14", "type": "number"} ] }, "includeOtherFields": true, "options": {} }, "id": "set-nurturing", "name": "Im Nurturing belassen", "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [2140, 440] } ], "connections": { "Neuen Lead empfangen": {"main": [[{"node": "E-Mail-Domain extrahieren", "type": "main", "index": 0}]]}, "E-Mail-Domain extrahieren": {"main": [[{"node": "Geschaeftliche Domain?", "type": "main", "index": 0}]]}, "Geschaeftliche Domain?": {"main": [[{"node": "Firmendaten abrufen", "type": "main", "index": 0}], [{"node": "Als Privatperson markieren", "type": "main", "index": 0}]]}, "Firmendaten abrufen": {"main": [[{"node": "Branche und Groesse einordnen", "type": "main", "index": 0}]]}, "Branche und Groesse einordnen": {"main": [[{"node": "Lead-Score berechnen", "type": "main", "index": 0}]]}, "Als Privatperson markieren": {"main": [[{"node": "Lead-Score berechnen", "type": "main", "index": 0}]]}, "Lead-Score berechnen": {"main": [[{"node": "Lead im CRM anlegen", "type": "main", "index": 0}]]}, "Lead im CRM anlegen": {"main": [[{"node": "Prioritaet A?", "type": "main", "index": 0}]]}, "Prioritaet A?": {"main": [[{"node": "Vertrieb sofort informieren", "type": "main", "index": 0}], [{"node": "Im Nurturing belassen", "type": "main", "index": 0}]]} }, "settings": {"executionOrder": "v1"}, "pinData": {} }