Enrichissement de prospects LinkedIn et relance IA personnalisée

Avancé

Ceci est unContent Creation, Multimodal AIworkflow d'automatisation du domainecontenant 18 nœuds.Utilise principalement des nœuds comme If, Set, Code, Wait, SplitOut. Enrichissement de prospects LinkedIn et de prospection personnalisée froide, intégrant Hunter.io, GPT-4 et Sheets

Prérequis
  • Peut nécessiter les informations d'identification d'authentification de l'API cible
  • Informations d'identification Google Sheets API
  • Clé API OpenAI
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "id": "",
  "meta": {
    "instanceId": "your-instance-id-here",
    "templateCredsSetupCompleted": false
  },
  "name": "LinkedIn Lead Enrichment with AI Personalization for Cold Outreach",
  "tags": [
    {
      "id": "1",
      "name": "Sales",
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-01-01T00:00:00.000Z"
    },
    {
      "id": "2",
      "name": "Lead Generation",
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-01-01T00:00:00.000Z"
    },
    {
      "id": "3",
      "name": "AI",
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-01-01T00:00:00.000Z"
    }
  ],
  "nodes": [
    {
      "id": "workflow-overview-note",
      "name": "📋 Vue d'ensemble du workflow & Guide de configuration",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -420,
        240
      ],
      "parameters": {
        "color": 4,
        "width": 680,
        "height": 620,
        "content": "## 🎯 LinkedIn Lead Enrichment with AI Personalization\n\n### **Who's it for:**\nSales teams, growth marketers, and business development professionals who want to automate lead research and create personalized outreach at scale.\n\n### **What it does:**\n- Scrapes LinkedIn profiles to extract professional information\n- Enriches leads with email addresses using hunter.io\n- Generates personalized outreach messages using AI\n- Stores enriched data in Google Sheets for easy management\n\n### **How to set up:**\n1. **Configure Google Sheets:** Create a sheet with columns: Name, LinkedIn URL, Email, Company, Title, Personalized Message\n2. **Set up credentials:** Add your OpenAI API key and Hunter.io API key in n8n credentials\n3. **Customize the AI prompt:** Edit the OpenAI node to match your outreach style and value proposition\n4. **Test with sample data:** Start with 2-3 LinkedIn URLs before scaling\n\n### **Requirements:**\n- OpenAI API key (GPT-4 recommended for best personalization)\n- Hunter.io API key for email finding\n- Google Sheets access\n- LinkedIn profile URLs of your target leads\n\n### **How to customize:**\n- **Change AI tone:** Modify the system prompt in the OpenAI node\n- **Add more data sources:** Integrate company website scraping\n- **Filter leads:** Add conditional logic to qualify leads before enrichment\n- **Connect to CRM:** Replace Google Sheets with Salesforce, HubSpot, or Pipedrive\n\n💡 **Pro Tip:** Use the \"Set Fields\" node to easily update your target industry and value proposition without editing multiple nodes.\n\n📺 **Watch Setup Guide:** [Add your Loom video link here]\n\n⚠️ **Important:** This workflow uses community nodes for LinkedIn scraping. Self-hosted n8n instance required."
      },
      "typeVersion": 1
    },
    {
      "id": "step-1-note",
      "name": "Contexte de l'étape 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        140,
        240
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 180,
        "content": "## Step 1: Configure Your Campaign\n\nSet your target criteria and personalization variables here.\n\nThis makes it easy to update without touching other nodes."
      },
      "typeVersion": 1
    },
    {
      "id": "step-2-note",
      "name": "Contexte de l'étape 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        660,
        240
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 180,
        "content": "## Step 2: Extract LinkedIn Data\n\nScrape professional information from LinkedIn profiles.\n\n⚠️ Rate limit: Max 20 profiles per minute"
      },
      "typeVersion": 1
    },
    {
      "id": "step-3-note",
      "name": "Contexte de l'étape 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1180,
        240
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 180,
        "content": "## Step 3: Find Email Addresses\n\nUse Hunter.io to find verified work emails.\n\nFallback to company domain + name patterns if not found."
      },
      "typeVersion": 1
    },
    {
      "id": "step-4-note",
      "name": "Contexte de l'étape 4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1700,
        240
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 180,
        "content": "## Step 4: AI Personalization\n\nGenerate custom outreach messages based on:\n- Job title\n- Company info\n- Recent activity\n- Your value proposition"
      },
      "typeVersion": 1
    },
    {
      "id": "step-5-note",
      "name": "Contexte de l'étape 5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2220,
        240
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 180,
        "content": "## Step 5: Store Enriched Leads\n\nSave all enriched data to Google Sheets for review and outreach."
      },
      "typeVersion": 1
    },
    {
      "id": "campaign-settings-node",
      "name": "Définir les variables de campagne",
      "type": "n8n-nodes-base.set",
      "position": [
        180,
        480
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "{\n  \"target_industry\": \"SaaS\",\n  \"target_role\": \"Head of Sales\",\n  \"company_name\": \"YourCompany\",\n  \"value_proposition\": \"We help sales teams book 30% more meetings using AI-powered personalization\",\n  \"linkedin_urls\": [\n    \"https://www.linkedin.com/in/sample-profile-1\",\n    \"https://www.linkedin.com/in/sample-profile-2\"\n  ]\n}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "split-urls-node",
      "name": "Diviser les URLs LinkedIn",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        380,
        480
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "linkedin_urls"
      },
      "typeVersion": 1
    },
    {
      "id": "scrape-linkedin-node",
      "name": "Extraire le profil LinkedIn",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        700,
        480
      ],
      "parameters": {
        "url": "={{ $json.linkedin_urls }}",
        "options": {
          "timeout": 10000
        },
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "User-Agent",
              "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "parse-linkedin-data-node",
      "name": "Analyser les données LinkedIn",
      "type": "n8n-nodes-base.code",
      "position": [
        900,
        480
      ],
      "parameters": {
        "jsCode": "// Extract key information from LinkedIn HTML\nconst html = $input.item.json.data || '';\n\n// Helper function to extract text between patterns\nfunction extractText(pattern, text) {\n  const match = text.match(pattern);\n  return match ? match[1].trim() : null;\n}\n\n// Extract name\nconst name = extractText(/<title>([^|]+)/, html) || 'Unknown';\n\n// Extract current position\nconst title = extractText(/aria-label=\"Current position[^>]*>([^<]+)/, html) || 'Not specified';\n\n// Extract company\nconst company = extractText(/aria-label=\"Current company[^>]*>([^<]+)/, html) || 'Unknown';\n\n// Extract location\nconst location = extractText(/aria-label=\"Location[^>]*>([^<]+)/, html) || 'Unknown';\n\n// Clean up name\nconst cleanName = name.replace(/[\\|\\-].*$/, '').trim();\nconst nameParts = cleanName.split(' ');\nconst firstName = nameParts[0] || '';\nconst lastName = nameParts.slice(1).join(' ') || '';\n\nreturn {\n  full_name: cleanName,\n  first_name: firstName,\n  last_name: lastName,\n  title: title,\n  company: company,\n  location: location,\n  linkedin_url: $json.linkedin_urls,\n  raw_html: html.substring(0, 1000) // Keep snippet for debugging\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "find-email-node",
      "name": "Trouver l'email avec Hunter.io",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1220,
        480
      ],
      "parameters": {
        "url": "=https://api.hunter.io/v2/email-finder",
        "method": "GET",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        },
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "queryAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "domain",
              "value": "={{ $json.company.toLowerCase().replace(/[^a-z0-9]/g, '') }}.com"
            },
            {
              "name": "first_name",
              "value": "={{ $json.first_name }}"
            },
            {
              "name": "last_name",
              "value": "={{ $json.last_name }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "process-email-node",
      "name": "Traiter le résultat de l'email",
      "type": "n8n-nodes-base.code",
      "position": [
        1420,
        480
      ],
      "parameters": {
        "jsCode": "// Extract email from Hunter.io response\nconst hunterData = $input.item.json.data || {};\nconst emailData = hunterData.email || null;\n\n// Get previous node data\nconst leadData = $('Parse LinkedIn Data').item.json;\n\nreturn {\n  ...leadData,\n  email: emailData,\n  email_confidence: hunterData.score || 0,\n  email_verified: emailData ? true : false\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "check-email-exists-node",
      "name": "Email trouvé ?",
      "type": "n8n-nodes-base.if",
      "position": [
        1620,
        480
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "email-exists-condition",
              "operator": {
                "type": "string",
                "operation": "isNotEmpty"
              },
              "leftValue": "={{ $json.email }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "generate-personalization-node",
      "name": "Générer la personnalisation IA",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1900,
        400
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4-turbo-preview",
          "cachedResultName": "GPT-4 Turbo"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=You are an expert sales copywriter. Generate a highly personalized cold outreach message based on the prospect's information.\n\n**Prospect Details:**\n- Name: {{ $json.first_name }} {{ $json.last_name }}\n- Title: {{ $json.title }}\n- Company: {{ $json.company }}\n- Location: {{ $json.location }}\n\n**Our Company:** {{ $('Set Campaign Variables').item.json.company_name }}\n**Value Proposition:** {{ $('Set Campaign Variables').item.json.value_proposition }}\n\n**Instructions:**\n1. Start with a personalized opener that references their role or company\n2. Clearly state the value proposition in one sentence\n3. Include a soft call-to-action\n4. Keep it under 100 words\n5. Professional but conversational tone\n6. No hype or pushy language\n\n**Output Format:**\nProvide ONLY the message body, no subject line or greetings. Return as JSON:\n{\n  \"message\": \"your personalized message here\"\n}"
            }
          ]
        },
        "jsonOutput": true
      },
      "typeVersion": 1.8
    },
    {
      "id": "save-to-sheets-node",
      "name": "Sauvegarder dans Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2260,
        480
      ],
      "parameters": {
        "columns": {
          "value": {
            "Email": "={{ $json.email }}",
            "Title": "={{ $json.title }}",
            "Company": "={{ $json.company }}",
            "Location": "={{ $json.location }}",
            "Full Name": "={{ $json.full_name }}",
            "Last Name": "={{ $json.last_name }}",
            "First Name": "={{ $json.first_name }}",
            "LinkedIn URL": "={{ $json.linkedin_url }}",
            "Enriched Date": "={{ $now.toFormat('yyyy-MM-dd HH:mm:ss') }}",
            "Email Confidence": "={{ $json.email_confidence }}",
            "Personalized Message": "={{ $json.ai_message }}"
          },
          "schema": [],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultName": "Lead Enrichment Sheet"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "merge-ai-data-node",
      "name": "Fusionner le message IA",
      "type": "n8n-nodes-base.code",
      "position": [
        2100,
        400
      ],
      "parameters": {
        "jsCode": "// Merge AI-generated message with lead data\nconst leadData = $('Process Email Result').item.json;\nconst aiResponse = $input.item.json.message?.content || {};\nconst aiMessage = aiResponse.message || 'Personalization failed - manual review needed';\n\nreturn {\n  ...leadData,\n  ai_message: aiMessage,\n  processing_timestamp: new Date().toISOString()\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "no-email-found-node",
      "name": "Pas d'email - Ignorer",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1900,
        560
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "rate-limit-wait-node",
      "name": "Délai de limite de taux",
      "type": "n8n-nodes-base.wait",
      "position": [
        560,
        480
      ],
      "webhookId": "rate-limit-webhook-id",
      "parameters": {
        "unit": "seconds",
        "amount": 2
      },
      "typeVersion": 1.1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": "",
    "executionOrder": "v1",
    "saveManualExecutions": true
  },
  "versionId": "",
  "connections": {
    "check-email-exists-node": {
      "main": [
        [
          {
            "node": "generate-personalization-node",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "no-email-found-node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "merge-ai-data-node": {
      "main": [
        [
          {
            "node": "save-to-sheets-node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "rate-limit-wait-node": {
      "main": [
        [
          {
            "node": "scrape-linkedin-node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "parse-linkedin-data-node": {
      "main": [
        [
          {
            "node": "find-email-node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "split-urls-node": {
      "main": [
        [
          {
            "node": "rate-limit-wait-node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "process-email-node": {
      "main": [
        [
          {
            "node": "check-email-exists-node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "campaign-settings-node": {
      "main": [
        [
          {
            "node": "split-urls-node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "scrape-linkedin-node": {
      "main": [
        [
          {
            "node": "parse-linkedin-data-node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "find-email-node": {
      "main": [
        [
          {
            "node": "process-email-node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "generate-personalization-node": {
      "main": [
        [
          {
            "node": "merge-ai-data-node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Avancé - Création de contenu, IA Multimodale

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Avancé
Nombre de nœuds18
Catégorie2
Types de nœuds10
Description de la difficulté

Adapté aux utilisateurs avancés, avec des workflows complexes contenant 16+ nœuds

Auteur
Amirul Hakimi

Amirul Hakimi

@amirulhaaakimi

CS Student Specializing in Artificial Intelligence @UNITEN | Certified in CRO & Copywriting for High-Impact Digital Growth

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34