{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "a686b9b4-09c6-4f5e-9917-6d590648e4f9",
      "name": "post Apify data scrap",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        304,
        0
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/peakydev~leads-scraper-ppe/runs?token=YOUR_TOKEN_HERE",
        "method": "POST",
        "options": {
          "redirect": {
            "redirect": {
              "maxRedirects": 5
            }
          }
        },
        "jsonBody": "{\n    \"includeEmails\": true,\n    \"industry\": [\n        \"Primary and Secondary Education\"\n    ],\n    \"totalResults\": 10000\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "Application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "0f495a64-b00e-46cf-b3f9-69beb2a32dbf",
      "name": "Get Apify recent run data",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        592,
        0
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/peakydev~leads-scraper-ppe/runs/last/dataset/items?token=YOUR_TOKEN_HERE",
        "options": {
          "redirect": {
            "redirect": {
              "maxRedirects": 5
            }
          }
        },
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "Application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "bde68ef5-7b9f-48c8-b3e3-5215c50290ba",
      "name": "generate Ai email",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2224,
        0
      ],
      "parameters": {
        "text": "=User Input:  {{ $item(\"0\").$node[\"JSON Stringifier\"].json[\"userInput\"] }}",
        "options": {
          "systemMessage": "=You are an expert Automation Engineer & B2B Outreach Specialist.\n\nYou will receive USER INPUT as a JSON array of lead objects.\nEach object represents one lead with personal and company details.\n\nYour task:\n- Read the USER INPUT carefully\n- Generate ONE personalized, professional cold email per lead\n- Use the lead\u2019s:\n  - fullName\n  - position\n  - organizationName\n  - organizationIndustry\n  - organizationDescription\n  - organizationWebsite (if helpful)\n- The email must feel human, relevant, and non-salesy\n- Focus on how automation can save time, reduce manual work, and improve efficiency\n- Tailor the value proposition based on the company\u2019s industry (e.g. Travel, SaaS, E-commerce, Agency)\n\nEmail requirements:\n- Friendly and professional tone\n- Short, clear paragraphs\n- No hype, no buzzwords\n- One clear CTA (call to action)\n- Do NOT mention scraping, APIs, or data sources\n- Do NOT say \u201cI found you on LinkedIn\u201d\n- Do NOT invent facts beyond the provided data\n\nEmail structure:\n1. Subject line (short & relevant)\n2. Personalized greeting using fullName\n3. One sentence showing you understand their business\n4. How automation can help their specific type of company\n5. What you do as an automation engineer (brief)\n6. Soft CTA (call, reply, or quick chat)\n7. Professional sign-off\n\nOutput format (VERY IMPORTANT):\nReturn ONLY the email content in plain text like this:\n\nSubject: <subject line>\n\nHi <Full Name>,\n\n<email body>\n\nBest regards,  \n<Your Name>  \nAutomation Engineer\n\nIf multiple users are provided, generate a separate email for EACH user.\n"
        },
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "0b0623d0-f30e-48db-ab9f-29d1ac069b69",
      "name": "make separate json of each keyword",
      "type": "n8n-nodes-base.code",
      "position": [
        -304,
        -16
      ],
      "parameters": {
        "jsCode": "// Input from previous node\nconst input = $input.item.json;\n\n// Step 1: Get the keyword string\nconst keywordString = input.Keyword || \"\";\n\n// Step 2: Split string into individual keywords\nconst keywordsArray = keywordString\n  .split(/\\s{2,}/)       // split by 2 or more spaces\n  .map(k => k.trim())    // remove extra spaces\n  .filter(k => k !== ''); // remove empty strings\n\n// Step 3: Convert into n8n items format\nreturn keywordsArray.map(k => ({\n  json: { keyword: k }\n}));\n"
      },
      "typeVersion": 2
    },
    {
      "id": "45214227-bb86-476d-9cfc-bcc68c5e426f",
      "name": "If email exist",
      "type": "n8n-nodes-base.if",
      "position": [
        1168,
        16
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8060c190-0a72-4c9b-a5c7-451ec8fe6a9c",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.email }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f02a9fd2-897d-4c60-a34a-9582a47b4556",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        448
      ],
      "parameters": {
        "color": 4,
        "width": 1184,
        "height": 384,
        "content": "# Approved Leads Email Workflow"
      },
      "typeVersion": 1
    },
    {
      "id": "9de6efad-ecb0-4c4f-a29c-40b0eba54055",
      "name": "\ud83d\udce5 Approved Leads Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -464,
        576
      ],
      "parameters": {
        "path": "webhook/approved",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "70ae0f09-b164-44fa-8ae1-c4f7c518a767",
      "name": "\ud83d\udd27 Normalize Lead Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -176,
        576
      ],
      "parameters": {
        "jsCode": "const webhookData = $input.item.json;\n\n// Extract body data\nconst data = webhookData.body;\n\n// Normalize data according to your sheet columns\nconst normalizedData = {\n  // Your sheet columns in exact order:\n  \n  // 1. organizationIndustry\n  organizationIndustry: data.organizationIndustry || \"\",\n  \n  // 2. email\n  email: data.email || \"\",\n  \n  // 3. city\n  city: data.city || \"\",\n  \n  // 4. state\n  state: data.state || \"\",\n  \n  // 5. country\n  country: data.country || \"\",\n  \n  // 6. organizationSize\n  organizationSize: data.organizationSize || \"\",\n  \n  // 7. organizationLinkedinUrl\n  organizationLinkedinUrl: data.organizationLinkedinUrl || \"\",\n  \n  // 8. organizationWebsiteUrl\n  organizationWebsiteUrl: data.organizationWebsiteUrl || \"\",\n  \n  // 9. organizationFoundedYear\n  organizationFoundedYear: data.organizationFoundedYear || \"\",\n  \n  // 10. organizationDescription\n  organizationDescription: data.organizationDescription || \"\",\n  \n  // 11. emailContent\n  emailContent: data.emailContent || \"\",\n  \n  // 12. Status (from webhook)\n  Status: data.status || \"\",\n  \n  // Additional useful data for email sending:\n  fullName: data.fullName || \"\",\n  position: data.position || \"\",\n  organizationName: data.organizationName || \"\",\n  \n  // Tracking\n  sheetRow: data.sheetRow,\n  eventId: data.eventId,\n  timestamp: data.timestamp\n};\n\n// Log for debugging\nconsole.log(\"Normalized Data:\", JSON.stringify(normalizedData, null, 2));\n\nreturn [{ json: normalizedData }];"
      },
      "typeVersion": 2
    },
    {
      "id": "b1dbaf04-48d2-437e-9966-ef4d6b08b8d7",
      "name": "\u2702\ufe0f Split Email Content",
      "type": "n8n-nodes-base.code",
      "position": [
        64,
        576
      ],
      "parameters": {
        "jsCode": "// Get the input data safely\nlet emailContent = \"\";\n\ntry {\n  // Method 1: Try to get data from common structures\n  const inputData = $input.item.json;\n  \n  if (inputData.body && inputData.body.emailContent) {\n    emailContent = inputData.body.emailContent;\n  } else if (inputData.emailContent) {\n    emailContent = inputData.emailContent;\n  } else if (inputData[0] && inputData[0].json && inputData[0].json.body && inputData[0].json.body.emailContent) {\n    emailContent = inputData[0].json.body.emailContent;\n  } else {\n    // Try to find email content in any format\n    const jsonStr = JSON.stringify(inputData);\n    const match = jsonStr.match(/\"emailContent\":\"([^\"]+)\"/);\n    if (match) {\n      emailContent = match[1].replace(/\\\\n/g, '\\n');\n    }\n  }\n} catch (error) {\n  console.log(\"Error getting data:\", error);\n  emailContent = \"\";\n}\n\nconsole.log(\"Email content length:\", emailContent.length);\n\n// Extract subject and body\nlet subject = \"Automation Proposal\";\nlet body = \"\";\n\nif (emailContent && emailContent.trim() !== \"\") {\n  // Find subject\n  const subjectMatch = emailContent.match(/Subject:\\s*(.+?)(?:\\n\\n|\\r\\n\\r\\n|$)/im);\n  if (subjectMatch) {\n    subject = subjectMatch[1].trim();\n    // Remove subject line\n    body = emailContent.replace(/Subject:\\s*.+?(\\n\\n|\\r\\n\\r\\n|$)/im, '').trim();\n  } else {\n    body = emailContent.trim();\n  }\n}\n\nconsole.log(\"Subject:\", subject);\nconsole.log(\"Body length:\", body.length);\n\n// Return the result\nreturn [{\n  json: {\n    subject: subject,\n    body: body\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "98c5b879-f320-4256-a412-36469668e49f",
      "name": "\ud83d\udce4 Send Approved Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        304,
        576
      ],
      "parameters": {
        "sendTo": "=muhammadmoosa.abc1@gmail.com",
        "message": "={{ $json.body }}",
        "options": {},
        "subject": "={{ $json.subject }}",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6b865333-8ab3-46fd-a2d5-2f0b92d9ae7e",
      "name": "Data Batcher",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        0,
        -16
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "0dbaa915-0aeb-4b29-92db-29f3ca5aef4d",
      "name": "Lead Data Batcher",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        880,
        0
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "17642f70-ca69-49ac-a08d-683b788b2e09",
      "name": "JSON Stringifier",
      "type": "n8n-nodes-base.code",
      "position": [
        1456,
        0
      ],
      "parameters": {
        "jsCode": "// Get all incoming items (n8n compatible)\nconst items = $input.all();\n\n// Convert incoming JSON to string\nconst userInput = JSON.stringify(\n  items.map(item => item.json)\n);\n\n// Return as output\nreturn [\n  {\n    json: {\n      userInput\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "a1677126-07b7-4eed-8ddd-1accef15be52",
      "name": "HubSpot Company Creator",
      "type": "n8n-nodes-base.hubspot",
      "position": [
        1744,
        0
      ],
      "parameters": {
        "name": "={{ $item(\"0\").$node[\"If email exist\"].json[\"organizationName\"] }}",
        "resource": "company",
        "authentication": "appToken",
        "additionalFields": {
          "websiteUrl": "={{ $item(\"0\").$node[\"If email exist\"].json[\"organizationWebsite\"] }}",
          "description": "={{ $item(\"0\").$node[\"If email exist\"].json[\"organizationDescription\"] }}",
          "yearFounded": "={{ $item(\"0\").$node[\"If email exist\"].json[\"organizationFoundedYear\"] }}",
          "linkedInCompanyPage": "={{ $item(\"0\").$node[\"If email exist\"].json[\"organizationLinkedinUrl\"] }}"
        }
      },
      "credentials": {
        "hubspotAppToken": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e83d869f-c9be-41c4-ac56-e4f082afd13c",
      "name": "HubSpot Contact Sync",
      "type": "n8n-nodes-base.hubspot",
      "position": [
        1968,
        0
      ],
      "parameters": {
        "email": "={{ $item(\"0\").$node[\"If email exist\"].json[\"email\"] }}",
        "options": {},
        "authentication": "appToken",
        "additionalFields": {
          "city": "={{ $item(\"0\").$node[\"If email exist\"].json[\"city\"] }}",
          "country": "={{ $item(\"0\").$node[\"If email exist\"].json[\"country\"] }}",
          "jobTitle": "={{ $item(\"0\").$node[\"If email exist\"].json[\"position\"] }}",
          "lastName": "={{ $item(\"0\").$node[\"If email exist\"].json[\"lastName\"] }}",
          "firstName": "={{ $item(\"0\").$node[\"If email exist\"].json[\"firstName\"] }}",
          "companySize": "={{ $item(\"0\").$node[\"If email exist\"].json[\"organizationSize\"] }}",
          "linkedinUrl": "={{ $item(\"0\").$node[\"If email exist\"].json[\"linkedinUrl\"] }}",
          "stateRegion": "={{ $item(\"0\").$node[\"If email exist\"].json[\"state\"] }}",
          "associatedCompanyId": "={{ $json.companyId }}"
        }
      },
      "credentials": {
        "hubspotAppToken": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5a61af7b-a3ee-464f-a579-7212564b3018",
      "name": "Leads Log",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2608,
        0
      ],
      "parameters": {
        "columns": {
          "value": {
            "city": "={{ $item(\"0\").$node[\"If email exist\"].json[\"city\"] }}",
            "email": "={{ $item(\"0\").$node[\"If email exist\"].json[\"email\"] }}",
            "state": "={{ $item(\"0\").$node[\"If email exist\"].json[\"state\"] }}",
            "Status": "Pending",
            "country": "={{ $item(\"0\").$node[\"If email exist\"].json[\"country\"] }}",
            "emailContent": "={{ $json.output }}",
            "organizationSize": "={{ $item(\"0\").$node[\"If email exist\"].json[\"organizationSize\"] }}",
            "organizationIndustry": "={{ $('If email exist').item.json.organizationIndustry }}",
            "organizationWebsiteUrl": "={{ $item(\"0\").$node[\"If email exist\"].json[\"organizationWebsite\"] }}",
            "organizationDescription": "={{ $item(\"0\").$node[\"If email exist\"].json[\"organizationDescription\"] }}",
            "organizationFoundedYear": "={{ $item(\"0\").$node[\"If email exist\"].json[\"organizationFoundedYear\"] }}",
            "organizationLinkedinUrl": "={{ $item(\"0\").$node[\"If email exist\"].json[\"organizationLinkedinUrl\"] }}"
          },
          "schema": [
            {
              "id": "organizationIndustry",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "organizationIndustry",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "city",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "city",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "state",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "state",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "country",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "country",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organizationSize",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "organizationSize",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organizationLinkedinUrl",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "organizationLinkedinUrl",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organizationWebsiteUrl",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "organizationWebsiteUrl",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organizationFoundedYear",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "organizationFoundedYear",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organizationDescription",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "organizationDescription",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "emailContent",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "emailContent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1B5gPF93zBySVC9h2JzbCZXbVZvf5tEcLaoc6Xuyt3aQ/edit#gid=0",
          "cachedResultName": "Leads"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1B5gPF93zBySVC9h2JzbCZXbVZvf5tEcLaoc6Xuyt3aQ",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1B5gPF93zBySVC9h2JzbCZXbVZvf5tEcLaoc6Xuyt3aQ/edit?usp=drivesdk",
          "cachedResultName": "Linkdin Leads Scrapping"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "93a3faf9-d003-441b-901d-1bc3d8f1011b",
      "name": "Lead Campaign Setup",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -544,
        -16
      ],
      "parameters": {
        "options": {},
        "formTitle": "LinkedIn Leads Scraping Setup",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Keyword",
              "placeholder": "Keyword",
              "requiredField": true
            }
          ]
        },
        "formDescription": "This form configures automated LinkedIn lead extraction for targeted B2B marketing campaigns. By providing specific criteria below, our system will scrape high-quality leads from LinkedIn based on your business needs."
      },
      "typeVersion": 2.3
    },
    {
      "id": "1ca64694-06c4-471b-aadb-0ed0bdb20be7",
      "name": "Rejection Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -560,
        1088
      ],
      "parameters": {
        "path": "webhook/rejected",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "a1e44d3a-983d-4f24-9cb4-be151ded07d3",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -624,
        944
      ],
      "parameters": {
        "color": 2,
        "width": 1280,
        "height": 464,
        "content": "# Rejection Follow-up Workflow\n"
      },
      "typeVersion": 1
    },
    {
      "id": "800b3f0f-1531-417d-b9ad-9a6ff4f3b7a5",
      "name": "Webhook Data Normalizer",
      "type": "n8n-nodes-base.code",
      "position": [
        -320,
        1088
      ],
      "parameters": {
        "jsCode": "const webhookData = $input.item.json;\n\n// Extract body data\nconst data = webhookData.body;\n\n// Normalize data according to your sheet columns\nconst normalizedData = {\n  // Your sheet columns in exact order:\n  \n  // 1. organizationIndustry\n  organizationIndustry: data.organizationIndustry || \"\",\n  \n  // 2. email\n  email: data.email || \"\",\n  \n  // 3. city\n  city: data.city || \"\",\n  \n  // 4. state\n  state: data.state || \"\",\n  \n  // 5. country\n  country: data.country || \"\",\n  \n  // 6. organizationSize\n  organizationSize: data.organizationSize || \"\",\n  \n  // 7. organizationLinkedinUrl\n  organizationLinkedinUrl: data.organizationLinkedinUrl || \"\",\n  \n  // 8. organizationWebsiteUrl\n  organizationWebsiteUrl: data.organizationWebsiteUrl || \"\",\n  \n  // 9. organizationFoundedYear\n  organizationFoundedYear: data.organizationFoundedYear || \"\",\n  \n  // 10. organizationDescription\n  organizationDescription: data.organizationDescription || \"\",\n  \n  // 11. emailContent\n  emailContent: data.emailContent || \"\",\n  \n  // 12. Status (from webhook)\n  Status: data.status || \"\",\n  \n  // Additional useful data for email sending:\n  fullName: data.fullName || \"\",\n  position: data.position || \"\",\n  organizationName: data.organizationName || \"\",\n  \n  // Tracking\n  sheetRow: data.sheetRow,\n  eventId: data.eventId,\n  timestamp: data.timestamp\n};\n\n// Log for debugging\nconsole.log(\"Normalized Data:\", JSON.stringify(normalizedData, null, 2));\n\nreturn [{ json: normalizedData }];"
      },
      "typeVersion": 2
    },
    {
      "id": "d19b6e66-09b6-4df1-ae4d-d9909cedcfe0",
      "name": "Rejection Data Stringifier",
      "type": "n8n-nodes-base.code",
      "position": [
        -80,
        1088
      ],
      "parameters": {
        "jsCode": "// Get all incoming items (n8n compatible)\nconst items = $input.all();\n\n// Convert incoming JSON to string\nconst userInput = JSON.stringify(\n  items.map(item => item.json)\n);\n\n// Return as output\nreturn [\n  {\n    json: {\n      userInput\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "d3ba5d1e-d1c7-4291-8c40-1abc4baa299b",
      "name": "Rejection Email Rewriter",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        112,
        1088
      ],
      "parameters": {
        "text": "=User input:  {{ $json.userInput }}",
        "options": {
          "systemMessage": "You are an expert Automation Engineer and B2B Outreach Copywriter.\n\nYou will receive USER INPUT as a JSON string.\nThe JSON may include:\n- previous lead data\n- current lead data\n- an emailContent field\n- a Status field that can be \"Rejected\"\n\nIMPORTANT CONTEXT:\nThe existing email was REJECTED.\nYour task is to REWRITE and IMPROVE the email with a different angle.\nDo NOT repeat the same phrasing, structure, or opening.\n\nYour goals:\n- Generate a NEW outreach email that feels more:\n  - Helpful\n  - Softer\n  - More value-focused\n  - Less salesy\n- Adapt tone to the lead\u2019s industry (Education, SaaS, Agency, etc.)\n- Emphasize assistance, clarity, and practical benefits\n- Avoid pressure, avoid aggressive CTAs\n\nRules:\n- Use ONLY data present in the USER INPUT\n- Do NOT mention rejection or status\n- Do NOT mention LinkedIn, scraping, or data sources\n- Do NOT invent personal details\n- Keep it short, polite, and respectful\n- One clear but low-friction CTA\n\nPersonalization:\n- If name is available, use it\n- Reference the organization\u2019s industry and context\n- Frame automation as support, not disruption\n\nEmail structure:\n1. New subject line (different from previous)\n2. Polite greeting\n3. Acknowledge their work context subtly\n4. Practical automation examples relevant to their industry\n5. Brief intro of yourself as an automation engineer\n6. Soft CTA (reply, short chat, or simple question)\n7. Professional sign-off\n\nOutput format (STRICT):\nReturn ONLY the updated email in plain text:\n\nSubject: <new subject>\n\nHi <Name>,\n\n<email body>\n\nBest regards,  \n<Your Name>  \nAutomation Engineer\n\nIf multiple users exist in the input, generate ONE updated email PER user.\nDo not include explanations, JSON, or commentary \u2014 only the email text.\n"
        },
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "ea6196c1-c0e2-48ac-b8fa-f33458a4e479",
      "name": "Update: Improved Email",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        464,
        1088
      ],
      "parameters": {
        "columns": {
          "value": {
            "email": "={{ $item(\"0\").$node[\"Webhook Data Normalizer\"].json[\"email\"] }}",
            "emailContent": "={{ $json.output }}"
          },
          "schema": [
            {
              "id": "organizationIndustry",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "organizationIndustry",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "city",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "city",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "state",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "state",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "country",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "country",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organizationSize",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "organizationSize",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organizationLinkedinUrl",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "organizationLinkedinUrl",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organizationWebsiteUrl",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "organizationWebsiteUrl",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organizationFoundedYear",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "organizationFoundedYear",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organizationDescription",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "organizationDescription",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "emailContent",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "emailContent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1B5gPF93zBySVC9h2JzbCZXbVZvf5tEcLaoc6Xuyt3aQ/edit#gid=0",
          "cachedResultName": "Leads"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1B5gPF93zBySVC9h2JzbCZXbVZvf5tEcLaoc6Xuyt3aQ",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1B5gPF93zBySVC9h2JzbCZXbVZvf5tEcLaoc6Xuyt3aQ/edit?usp=drivesdk",
          "cachedResultName": "Linkdin Leads Scrapping"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "f48b7143-491e-43c8-81d6-f9afd69bf6ed",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -624,
        -144
      ],
      "parameters": {
        "width": 3520,
        "height": 464,
        "content": "# LinkedIn Lead Generation Pipeline"
      },
      "typeVersion": 1
    },
    {
      "id": "fe109bb7-1ff3-4435-95ad-e1a26d5d56a9",
      "name": "LLM",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2224,
        192
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5-mini",
          "cachedResultName": "gpt-5-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "b54d2535-c0c1-4df1-b784-c670dd2f4b91",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        112,
        1280
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5-mini",
          "cachedResultName": "gpt-5-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "c8f60827-fe7d-426b-b101-00cb5c392fc4",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        80
      ],
      "parameters": {
        "width": 400,
        "height": 1024,
        "content": "\n## How it works\n\n1. You submit lead keywords (industry, role, location) using the form trigger or by adding rows in Google Sheets.\n2. The workflow scrapes targeted LinkedIn leads via Apify and processes them in batches.\n3. Leads are filtered to keep only contacts with valid email addresses.\n4. Company and contact records are automatically created in HubSpot CRM.\n5. AI generates a personalized, non-salesy cold email for each lead, tailored to the company\u2019s industry.\n6. All leads and email drafts are logged in Google Sheets with a **Pending** status.\n7. You review leads directly inside Google Sheets:\n\n   * **Approve** \u2192 the email is sent automatically via Gmail.\n   * **Reject** \u2192 the email is rewritten with a softer, value-focused angle and updated in the same sheet row.\n8. This creates a full human-in-the-loop outreach system with traceable decisions and clean CRM data.\n\n---\n\n## Setup steps\n\n1. Import the workflow into n8n.\n2. Connect required credentials:\n\n   * Apify API token\n   * HubSpot App Token\n   * Google Sheets OAuth2\n   * Gmail OAuth2\n   * OpenAI API key\n3. Update placeholders:\n\n   * Google Sheet ID in the \u201cLeads Log\u201d node\n   * Your name and signature inside the AI prompts\n4. Activate the **Lead Campaign Setup** form trigger to start collecting leads.\n5. Review leads in Google Sheets and use approval or rejection actions to control email sending and rewriting.\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "LLM": {
      "ai_languageModel": [
        [
          {
            "node": "generate Ai email",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Leads Log": {
      "main": [
        [
          {
            "node": "Lead Data Batcher",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Data Batcher": {
      "main": [
        [],
        [
          {
            "node": "post Apify data scrap",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If email exist": {
      "main": [
        [
          {
            "node": "JSON Stringifier",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Lead Data Batcher",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "JSON Stringifier": {
      "main": [
        [
          {
            "node": "HubSpot Company Creator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lead Data Batcher": {
      "main": [
        [
          {
            "node": "Data Batcher",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "If email exist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Rejection Email Rewriter",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Rejection Webhook": {
      "main": [
        [
          {
            "node": "Webhook Data Normalizer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "generate Ai email": {
      "main": [
        [
          {
            "node": "Leads Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lead Campaign Setup": {
      "main": [
        [
          {
            "node": "make separate json of each keyword",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HubSpot Contact Sync": {
      "main": [
        [
          {
            "node": "generate Ai email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "post Apify data scrap": {
      "main": [
        [
          {
            "node": "Get Apify recent run data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HubSpot Company Creator": {
      "main": [
        [
          {
            "node": "HubSpot Contact Sync",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Data Normalizer": {
      "main": [
        [
          {
            "node": "Rejection Data Stringifier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rejection Email Rewriter": {
      "main": [
        [
          {
            "node": "Update: Improved Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udce4 Send Approved Email": {
      "main": [
        []
      ]
    },
    "\ud83d\udd27 Normalize Lead Data": {
      "main": [
        [
          {
            "node": "\u2702\ufe0f Split Email Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Apify recent run data": {
      "main": [
        [
          {
            "node": "Lead Data Batcher",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rejection Data Stringifier": {
      "main": [
        [
          {
            "node": "Rejection Email Rewriter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u2702\ufe0f Split Email Content": {
      "main": [
        [
          {
            "node": "\ud83d\udce4 Send Approved Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udce5 Approved Leads Webhook": {
      "main": [
        [
          {
            "node": "\ud83d\udd27 Normalize Lead Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "make separate json of each keyword": {
      "main": [
        [
          {
            "node": "Data Batcher",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}