{
  "id": "euU1g72FGuPI0jZB",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Get Enriched Lead Profiles from LinkedIn URLs with Apify and Google Sheets",
  "tags": [
    {
      "id": "Tx5TGVSKbShwuivF",
      "name": "Web Scraping",
      "createdAt": "2025-11-06T11:24:12.990Z",
      "updatedAt": "2025-11-06T11:24:12.990Z"
    },
    {
      "id": "W01fUigEbpzoMJlg",
      "name": "Lead Capture",
      "createdAt": "2025-11-05T11:27:38.370Z",
      "updatedAt": "2025-11-05T11:27:38.370Z"
    },
    {
      "id": "eEKVQFjuDWUBjiw7",
      "name": "LinkedIn",
      "createdAt": "2026-01-29T07:56:28.257Z",
      "updatedAt": "2026-01-29T07:56:28.257Z"
    }
  ],
  "nodes": [
    {
      "id": "7f4c62ad-aa24-41f5-a28c-228d505d222e",
      "name": "When clicking 'Execute Workflow'",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -5584,
        416
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "4daa223f-38f3-450e-b8f8-39fe456b88de",
      "name": "Process One Row at a Time",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -5072,
        304
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "55b937aa-77fd-42f0-bb5d-01843f4ed5fa",
      "name": "Start Apify Scrape",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -4720,
        512
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/dev_fusion~linkedin-profile-scraper/runs?token=YOUR_TOKEN_HERE",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"profileUrls\": [\n    \"{{ $json['LinkedIn'] }}\"\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "ec4c7c07-b02e-4f97-83a5-4e2f46501267",
      "name": "Store Run Info",
      "type": "n8n-nodes-base.code",
      "position": [
        -4512,
        512
      ],
      "parameters": {
        "jsCode": "// Store important data for later use\nconst apifyResponse = $input.first().json;\nconst originalRow = $('Process One Row at a Time').item.json;\n\nreturn [{\n  json: {\n    apifyRunId: apifyResponse.data.id,\n    apifyActId: apifyResponse.data.actId,\n    rowNumber: originalRow.row_number,\n    linkedInUrl: originalRow['LinkedIn'],\n    loopCount: 0\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "196a2f7b-d93c-46e5-a3cf-692bea44f6f0",
      "name": "Wait 15 Seconds",
      "type": "n8n-nodes-base.wait",
      "position": [
        -4272,
        352
      ],
      "parameters": {
        "amount": 15
      },
      "typeVersion": 1.1
    },
    {
      "id": "7a1a58b1-f278-435b-9be8-2186707d42ce",
      "name": "Check Status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -4080,
        352
      ],
      "parameters": {
        "url": "=https://api.apify.com/v2/acts/{{ $json.apifyActId }}/runs/{{ $json.apifyRunId }}?token=YOUR_APIFY_API_KEY",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "df1282c2-b773-44ba-9a8e-b6976195d1c4",
      "name": "Update Loop Counter",
      "type": "n8n-nodes-base.code",
      "position": [
        -3856,
        352
      ],
      "parameters": {
        "jsCode": "// Preserve original data and update status\nconst statusResponse = $input.first().json;\nconst previousData = $('Wait 15 Seconds').item.json;\n\nreturn [{\n  json: {\n    apifyRunId: previousData.apifyRunId,\n    apifyActId: previousData.apifyActId,\n    rowNumber: previousData.rowNumber,\n    linkedInUrl: previousData.linkedInUrl,\n    loopCount: previousData.loopCount + 1,\n    status: statusResponse.data.status\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "f389d47f-57a0-43bd-8e12-0b90faed9922",
      "name": "Check if Ready",
      "type": "n8n-nodes-base.if",
      "position": [
        -3664,
        352
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "condition1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "SUCCEEDED"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "bda5be84-5090-493a-b7f2-0ff6d2638965",
      "name": "Check Max Retries",
      "type": "n8n-nodes-base.if",
      "position": [
        -3904,
        608
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition2",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "leftValue": "={{ $json.loopCount }}",
              "rightValue": 20
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0a8e0730-7c81-41ef-95b7-b78dd5070bcf",
      "name": "Fetch LinkedIn Data",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -3088,
        448
      ],
      "parameters": {
        "url": "=https://api.apify.com/v2/datasets/{{ $('Check Status').item.json.data.defaultDatasetId }}/items?token=YOUR_APIFY_API_KEY",
        "options": {}
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "a856ba43-567a-45cc-aa77-5498c7d7f2e9",
      "name": "Prepare Error Message",
      "type": "n8n-nodes-base.code",
      "position": [
        -3664,
        624
      ],
      "parameters": {
        "jsCode": "// Prepare error message\nconst runInfo = $input.first().json;\n\nreturn [{\n  json: {\n    rowNumber: runInfo.rowNumber,\n    linkedInData: `Error: Failed after ${runInfo.loopCount} attempts`\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "2cbb12b4-8e84-4583-a58d-d1bfa56f4c06",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        -2496,
        432
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition",
        "numberInputs": 3
      },
      "typeVersion": 3.2
    },
    {
      "id": "9af0e302-ea01-4d9c-90d4-4c626a823643",
      "name": "Get Other Current Jobs",
      "type": "n8n-nodes-base.code",
      "position": [
        -2752,
        272
      ],
      "parameters": {
        "jsCode": "// Get the experiences array safely\nconst experiences = Array.isArray($json.experiences) ? $json.experiences : [];\n\n// Helper: clean strings (prevents random \\n, \\r issues)\nconst clean = (v) => String(v ?? '').replace(/[\\r\\n]+/g, ' ').trim();\n\n// Helper: treat blanks/nulls as N/A\nconst valOrNA = (v) => {\n  const s = clean(v);\n  return s ? s : 'N/A';\n};\n\n// Current date in MM-YYYY (force Asia/Tokyo)\nconst currentMMYYYY = (() => {\n  const parts = new Intl.DateTimeFormat('en-US', {\n    timeZone: 'Asia/Tokyo',\n    year: 'numeric',\n    month: '2-digit',\n  }).formatToParts(new Date());\n\n  const year = parts.find((p) => p.type === 'year')?.value || String(new Date().getFullYear());\n  const month =\n    parts.find((p) => p.type === 'month')?.value || String(new Date().getMonth() + 1).padStart(2, '0');\n\n  return `${month}-${year}`;\n})();\n\n// Helper: determine if a role is current\nconst isCurrentRole = (exp) => {\n  if (!exp || typeof exp !== 'object') return false;\n\n  // Prefer explicit boolean when present\n  if (typeof exp.jobStillWorking === 'boolean') return exp.jobStillWorking;\n\n  // Fallback: infer from missing/empty end date\n  const ended = exp.jobEndedOn;\n  return ended === null || ended === undefined || String(ended).trim() === '';\n};\n\n// All current roles (in the original order)\nconst currentRoles = experiences.filter(isCurrentRole);\n\n// Treat the first current role as the \"primary\" one, others are \"additional\"\nconst additionalCurrentRoles = currentRoles.slice(1);\n\n// Format additional current roles (include industry + size if present)\nconst formattedJobs = additionalCurrentRoles\n  .map((exp, i) => {\n    const title = valOrNA(exp.title);\n    const company = valOrNA(exp.companyName);\n    const started = valOrNA(exp.jobStartedOn);\n    const employmentType = valOrNA(exp.employmentType);\n    const companyIndustry = valOrNA(exp.companyIndustry);\n    const companySize = valOrNA(exp.companySize);\n\n    // Prefer explicit jobLocation; fall back to jobLocationCountry if present\n    const location = clean(exp.jobLocation) || clean(exp.jobLocationCountry) || 'N/A';\n\n    const desc = clean(exp.jobDescription) ? clean(exp.jobDescription) : 'No description';\n\n    return [\n      `additional_current_role_${i + 1}:`,\n      `- job_title: ${title}`,\n      `- job_description: ${desc}`,\n      `- company: ${company}`,\n      `- company_industry: ${companyIndustry}`,\n      `- company_size: ${companySize}`,\n      `- employment_type: ${employmentType}`,\n      `- location: ${location}`,\n      `- started: ${started} (current as of ${currentMMYYYY})`,\n    ].join('\\n');\n  })\n  .join('\\n\\n');\n\nreturn [\n  {\n    json: {\n      additionalCurrentJobs: formattedJobs || 'No additional current jobs',\n      count: additionalCurrentRoles.length,\n      currentRolesCount: currentRoles.length,\n    },\n  },\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "22635c73-d866-4ddd-a979-2e8f780b24dc",
      "name": "Set Other Key LinkedIn Data",
      "type": "n8n-nodes-base.set",
      "position": [
        -2752,
        608
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "15dcd484-86af-4cad-93ff-a3dfd1e9afc6",
              "name": "firstName",
              "type": "string",
              "value": "={{ $json.firstName }}"
            },
            {
              "id": "0b491156-4aa5-4308-9439-097c1686b5c8",
              "name": "lastName",
              "type": "string",
              "value": "={{ $json.lastName }}"
            },
            {
              "id": "c39d635f-5bdc-44d6-85cf-cf46279de143",
              "name": "linkedinUrl",
              "type": "string",
              "value": "={{ $json.linkedinUrl }}"
            },
            {
              "id": "713e4ea0-ae85-477a-93e3-8f59f049d79a",
              "name": "linkedInHeadline",
              "type": "string",
              "value": "={{ $json.headline }}"
            },
            {
              "id": "3cfd2667-eb7a-4204-a383-5d9fd22c7b08",
              "name": "currentJobDuration",
              "type": "string",
              "value": "={{ $json.currentJobDuration }}"
            },
            {
              "id": "598e015d-13d2-4297-9d05-fc395e8f0f6b",
              "name": "aboutPersonLead",
              "type": "string",
              "value": "={{ $json.about }}"
            },
            {
              "id": "4b5a5f3e-03de-4634-bc9f-2ff708c7d18f",
              "name": "latestCompanyName",
              "type": "string",
              "value": "={{   (() => {     const exps = Array.isArray($json.experiences) ? $json.experiences                : Array.isArray($json.experience) ? $json.experience                : [];      const clean = (v) => String(v ?? '').replace(/[\\r\\n]+/g, ' ').trim();      const isCurrent = (exp) => {       if (!exp || typeof exp !== 'object') return false;       if (typeof exp.jobStillWorking === 'boolean') return exp.jobStillWorking;       const ended = exp.jobEndedOn;       return ended === null || ended === undefined || String(ended).trim() === '';     };      const primary = exps.find(isCurrent) || exps[0];     return primary ? (clean(primary.companyName) || 'N/A') : 'N/A';   })() }}"
            },
            {
              "id": "b2c7c4ed-f2d9-4e7f-98a9-bd5e619438ce",
              "name": "latestJobTitle",
              "type": "string",
              "value": "={{\n  (() => {\n    const exps = Array.isArray($json.experiences) ? $json.experiences\n               : Array.isArray($json.experience) ? $json.experience\n               : [];\n\n    const clean = (v) => String(v ?? '').replace(/[\\r\\n]+/g, ' ').trim();\n\n    const isCurrent = (exp) => {\n      if (!exp || typeof exp !== 'object') return false;\n      if (typeof exp.jobStillWorking === 'boolean') return exp.jobStillWorking;\n      const ended = exp.jobEndedOn;\n      return ended === null || ended === undefined || String(ended).trim() === '';\n    };\n\n    const primary = exps.find(isCurrent) || exps[0];\n    return primary ? (clean(primary.title) || 'N/A') : 'N/A';\n  })()\n}}"
            },
            {
              "id": "4bc0b8c4-8955-41aa-aa01-66b19559fbdf",
              "name": "latestJobDescription",
              "type": "string",
              "value": "={{\n  (() => {\n    const exps = Array.isArray($json.experiences) ? $json.experiences\n               : Array.isArray($json.experience) ? $json.experience\n               : [];\n\n    const isCurrent = (exp) => {\n      if (!exp || typeof exp !== 'object') return false;\n      if (typeof exp.jobStillWorking === 'boolean') return exp.jobStillWorking;\n      const ended = exp.jobEndedOn;\n      return ended === null || ended === undefined || String(ended).trim() === '';\n    };\n\n    const primary = exps.find(isCurrent) || exps[0];\n    return primary ? (primary.jobDescription ?? null) : null;\n  })()\n}}"
            },
            {
              "id": "7d0f901e-eed7-4a1c-baba-646be2094966",
              "name": "oldPreviousCompanyName",
              "type": "string",
              "value": "={{\n  (() => {\n    const exps = Array.isArray($json.experiences) ? $json.experiences : [];\n    if (!exps.length) return '';\n\n    const clean = (v) => String(v ?? '').replace(/[\\r\\n]+/g, '').trim();\n\n    const isCurrent = (exp) => {\n      if (!exp) return false;\n      if (typeof exp.jobStillWorking === 'boolean') return exp.jobStillWorking;\n      const ended = exp.jobEndedOn;\n      return ended === null || ended === undefined || String(ended).trim() === '';\n    };\n\n    // Find the first current role (the \"main\" current role)\n    const currentIdx = exps.findIndex(isCurrent);\n\n    // Previous role = the first non-current role after the current one\n    const prev = exps.slice(Math.max(currentIdx + 1, 0)).find(exp => exp && !isCurrent(exp));\n\n    // If we can't find a previous role, fall back to experiences[1] if present\n    const target = prev || exps[1];\n    if (!target) return '';\n\n    const name = clean(target.companyName) || 'N/A';\n    const endedStr = clean(target.jobEndedOn);\n\n    return endedStr\n      ? `${name} - ended on ${endedStr}`\n      : `${name} - but no end date listed`;\n  })()\n}}"
            },
            {
              "id": "b21cf744-ede9-4416-9320-3d21bcaa3604",
              "name": "latestCompanyIndustry",
              "type": "string",
              "value": "={{\n  (() => {\n    const exps = Array.isArray($json.experiences) ? $json.experiences : [];\n    const isCurrent = (e) =>\n      e && (e.jobStillWorking === true || e.jobEndedOn == null || String(e.jobEndedOn).trim() === '');\n\n    const primary = exps.find(isCurrent) || exps[0] || null;\n\n    // Pull from the SAME experience object (absolute match)\n    return primary?.companyIndustry ?? $json.companyIndustry ?? null;\n  })()\n}}"
            },
            {
              "id": "cb834ca0-b98e-4046-816c-f65b7bffecb2",
              "name": "=latestCompanySize",
              "type": "string",
              "value": "={{\n  (() => {\n    const exps = Array.isArray($json.experiences) ? $json.experiences : [];\n    const isCurrent = (e) =>\n      e && (e.jobStillWorking === true || e.jobEndedOn == null || String(e.jobEndedOn).trim() === '');\n\n    const primary = exps.find(isCurrent) || exps[0] || null;\n\n    // Pull from the SAME experience object (absolute match)\n    return primary?.companySize ?? $json.companySize ?? null;\n  })()\n}}"
            },
            {
              "id": "44b30fd5-4a9a-49b1-9799-6e7a30275a6e",
              "name": "leadLocation",
              "type": "string",
              "value": "={{ $json.addressCountryOnly }}"
            },
            {
              "id": "8c966908-e1a8-4752-abc2-db0cf511789d",
              "name": "apifyLinkedInDatasetID",
              "type": "string",
              "value": "={{ $('Check Status').item.json.data.defaultDatasetId }}"
            },
            {
              "id": "90212539-1236-4c06-974e-794b9091cb82",
              "name": "emailAddress",
              "type": "string",
              "value": "={{ $json.email }}"
            },
            {
              "id": "961d16ec-e225-492b-8009-453bccdac1bf",
              "name": "companyName",
              "type": "string",
              "value": "={{ $json.companyName }}"
            },
            {
              "id": "8f63d6d7-39fc-45b9-b156-7d2077b70d84",
              "name": "companyWebsite",
              "type": "string",
              "value": "={{ $json.companyWebsite }}"
            },
            {
              "id": "6e9e6fe8-5c90-4130-9405-0d3499177de8",
              "name": "companySize",
              "type": "string",
              "value": "={{ $json.companySize }}"
            },
            {
              "id": "1f2ed940-36d6-4fb3-86df-b5cd4adb1129",
              "name": "companyIndustry",
              "type": "string",
              "value": "={{ $json.companyIndustry }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "612e67e2-6c08-42ff-a14c-923c5bdc38fd",
      "name": "Get 2 Most Recent Posts",
      "type": "n8n-nodes-base.code",
      "position": [
        -2752,
        448
      ],
      "parameters": {
        "jsCode": " // Get only first 2 posts\n  const firstTwoPosts = ($json.updates || []).slice(0, 2);\n\n  // Format as human-readable text\n  const formattedPosts = firstTwoPosts.map((post, index) => {\n    return `Post ${index + 1}:\n  ${post.postText || 'No text'}\n\n  Link: ${post.postLink || 'N/A'}`;\n  }).join('\\n\\n---\\n\\n');\n\n  return [{\n    json: {\n      linkedInUpdatesPostsActivity: formattedPosts || 'No posts available'\n    }\n  }];"
      },
      "typeVersion": 2
    },
    {
      "id": "5ff5b6cb-7b40-4a38-869b-0b042de50d4b",
      "name": "Get Rows - Not Enriched Yet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -5360,
        416
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "First Name"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kLOvqW5__U62IinkTCB6R8zVXHdlMayTz4werxnxXtU/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1kLOvqW5__U62IinkTCB6R8zVXHdlMayTz4werxnxXtU",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kLOvqW5__U62IinkTCB6R8zVXHdlMayTz4werxnxXtU/edit?usp=drivesdk",
          "cachedResultName": "Lead Enrichment with LinkedIn Profile URLs"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "916799c8-2973-442e-b685-6eca4e9af084",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -6560,
        -400
      ],
      "parameters": {
        "width": 864,
        "height": 1072,
        "content": "# **Get Enriched Lead Profiles from LinkedIn URLs with Apify and Google Sheets**\n\nTransform LinkedIn profile URLs into comprehensive lead profiles automatically. Add URLs to your sheet, run the workflow, and get fully enriched contact data: names, job titles, company details, career history, and recent activity\u2014all written back to your spreadsheet.\n\n## What it does\n- Reads unenriched rows from Google Sheets (detects empty \"First Name\" field)\n- Scrapes LinkedIn profiles via Apify (dev_fusion~linkedin-profile-scraper actor)\n- Polls for completion with smart retry logic (15-second intervals, max 20 attempts)\n- Extracts comprehensive profile data:\n  - Personal info (name, location, headline, bio)\n  - Current role (title, description, company, industry, size, website)\n  - Additional concurrent positions (for people with multiple roles)\n  - Most recent previous employer\n  - Last 2 LinkedIn posts with links\n- Writes enriched data back to the same Google Sheet row\n- Handles errors gracefully with status updates\n\n## Requirements\n- Apify account + API token\n- Google Sheets OAuth2 credentials\n- A Google Sheet with columns: LinkedIn, First Name, Last Name, Job Position, Location, Industry, Company Name, Company URL, Company Size, LI Other Profile Information, Status, Apify ID, Add date, row_number\n\n## Setup\n1. Create your Google Sheet with the required columns (or duplicate the template structure)\n2. Replace `YOUR_APIFY_API_KEY` in three HTTP Request nodes: \"Start Apify Scrape\", \"Check Status\", and \"Fetch LinkedIn Data\"\n3. Connect your Google Sheets OAuth2 credentials to the two Google Sheets nodes\n4. Update the document ID if using your own sheet (currently points to a specific sheet)\n5. Add LinkedIn profile URLs to the \"LinkedIn\" column, leaving \"First Name\" blank\n6. Run manually\u2014workflow processes all unenriched rows sequentially\n\n## Next steps\nUse the enriched data for sales outreach, recruiting pipelines, or lead scoring. The \"LI Other Profile Information\" column contains a rich text summary ideal for AI-powered lead qualification or personalized messaging.\n\n**Tip:** Process small batches (5-10 profiles) first to verify Apify results and check for rate limiting. The Apify dataset ID is stored in each row, so you can retrieve raw JSON data later if needed for deeper analysis.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "65cec22e-438e-45b7-a105-fb681fd83cc3",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5664,
        -400
      ],
      "parameters": {
        "color": 7,
        "width": 1344,
        "height": 512,
        "content": "## Sample Output\n\n**Google Sheet row output - from one successfully enriched lead profile via LinkedIn URL**:\n[Link to Google Sheets sample file](https://docs.google.com/spreadsheets/d/1kLOvqW5__U62IinkTCB6R8zVXHdlMayTz4werxnxXtU/edit?usp=sharing)\n\n![](https://i.postimg.cc/PxmX6FJw/sample-linkedin-url-lead-profile-enrichment.png)"
      },
      "typeVersion": 1
    },
    {
      "id": "5e1ee124-d91a-4428-85fb-6f02dd335a54",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5664,
        144
      ],
      "parameters": {
        "color": 5,
        "width": 784,
        "height": 900,
        "content": "## 1. Input & Batch Processing\nFetches unenriched rows from Google Sheets and processes one LinkedIn URL at a time."
      },
      "typeVersion": 1
    },
    {
      "id": "8af06cf7-5b87-4086-83e5-dc3e747da308",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4848,
        144
      ],
      "parameters": {
        "color": 3,
        "width": 1632,
        "height": 896,
        "content": "## 2. Apify Scraping & Polling\nTriggers LinkedIn profile scrape and polls for completion every 15 seconds for 20x attempts, logs an error if no successful response."
      },
      "typeVersion": 1
    },
    {
      "id": "56ff5899-7ad2-46e5-874c-9d599eca3b38",
      "name": "Update Row in Google Sheet (2)",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -2288,
        736
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "Done",
            "Add date": "={{ new Date().toISOString() }}",
            "Apify ID": "={{ $json.apifyLinkedInDatasetID }}",
            "Industry": "={{ $json.latestCompanyIndustry }}",
            "LinkedIn": "={{ $json.linkedinUrl }}",
            "Location": "={{ $json.leadLocation }}",
            "Last Name": "={{ $json.lastName }}",
            "First Name": "={{ $json.firstName }}",
            "row_number": "={{ $('Get Rows - Not Enriched Yet').item.json.row_number }}",
            "Company URL": "={{ $json.companyWebsite }}",
            "Company Name": "={{ $json.companyName }}",
            "Company SIze": "={{ $json.companySize }}",
            "Job Position": "={{ $json.latestJobTitle }}",
            "LI Other Profile Information": "=Headline: {{ $json.linkedInHeadline || 'Nothing added' }}\n\nSummary: {{ $json.aboutPersonLead || 'Nothing added' }}\n\nJob_description: {{ $json.latestJobDescription || 'Unknown' }}\n\nOther Current Roles:\n{{ $json.additionalCurrentJobs || 'None' }}\n\n\nprevious_employer_most_recent (may match current company, e.g. change of role in same company):\n- company_and_end_date: {{ $json.oldPreviousCompanyName || 'None provided' }}\n\nrecent_post_activity:\n{{ $json.linkedInUpdatesPostsActivity || 'No Posts' }}"
          },
          "schema": [
            {
              "id": "LinkedIn",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "LinkedIn",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "First Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "First Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Last Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Last Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Job Position",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Job Position",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Location",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Location",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Industry",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Industry",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Add date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Add date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Company Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Company Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Company URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Company URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Company SIze",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Company SIze",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LI Other Profile Information",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "LI Other Profile Information",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Apify ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Apify ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kLOvqW5__U62IinkTCB6R8zVXHdlMayTz4werxnxXtU/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1kLOvqW5__U62IinkTCB6R8zVXHdlMayTz4werxnxXtU",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kLOvqW5__U62IinkTCB6R8zVXHdlMayTz4werxnxXtU/edit?usp=drivesdk",
          "cachedResultName": "Lead Enrichment with LinkedIn Profile URLs"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "0395efb3-9c91-406a-82b1-b7abec5db05d",
      "name": "Update Row in Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -3424,
        624
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "={{ $json.linkedInData }}",
            "Apify ID": "={{ $('Check Status').item.json.data.id }}",
            "row_number": "={{ $json.rowNumber }}"
          },
          "schema": [
            {
              "id": "LinkedIn",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "LinkedIn",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "First Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "First Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Last Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Last Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Job Position",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Job Position",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Country",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Country",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Location",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Location",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Industry",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Industry",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Add date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Add date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Company Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Company Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Company URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Company URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Company SIze",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Company SIze",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LI Key Profile Information",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "LI Key Profile Information",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Apify ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Apify ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kLOvqW5__U62IinkTCB6R8zVXHdlMayTz4werxnxXtU/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1kLOvqW5__U62IinkTCB6R8zVXHdlMayTz4werxnxXtU",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kLOvqW5__U62IinkTCB6R8zVXHdlMayTz4werxnxXtU/edit?usp=drivesdk",
          "cachedResultName": "Lead Enrichment with LinkedIn Profile URLs"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "b9d873b8-f6e8-4110-b2b9-68b7ee1779e1",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3184,
        144
      ],
      "parameters": {
        "color": 4,
        "width": 1120,
        "height": 896,
        "content": "## 3. Data Extraction & Output\nExtracts detailed profile outputs (name, job position, company, other roles, recent posts etc), and writes enriched data back to Google Sheets."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "d3e33a6b-1f8c-441c-bb5c-1353920fd83b",
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Update Row in Google Sheet (2)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Status": {
      "main": [
        [
          {
            "node": "Update Loop Counter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Ready": {
      "main": [
        [
          {
            "node": "Fetch LinkedIn Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check Max Retries",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store Run Info": {
      "main": [
        [
          {
            "node": "Wait 15 Seconds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 15 Seconds": {
      "main": [
        [
          {
            "node": "Check Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Max Retries": {
      "main": [
        [
          {
            "node": "Wait 15 Seconds",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare Error Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start Apify Scrape": {
      "main": [
        [
          {
            "node": "Store Run Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch LinkedIn Data": {
      "main": [
        [
          {
            "node": "Get 2 Most Recent Posts",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Other Current Jobs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Set Other Key LinkedIn Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Loop Counter": {
      "main": [
        [
          {
            "node": "Check if Ready",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Error Message": {
      "main": [
        [
          {
            "node": "Update Row in Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Other Current Jobs": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get 2 Most Recent Posts": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Process One Row at a Time": {
      "main": [
        [],
        [
          {
            "node": "Start Apify Scrape",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Row in Google Sheet": {
      "main": [
        [
          {
            "node": "Process One Row at a Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Rows - Not Enriched Yet": {
      "main": [
        [
          {
            "node": "Process One Row at a Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Other Key LinkedIn Data": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Update Row in Google Sheet (2)": {
      "main": [
        [
          {
            "node": "Process One Row at a Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking 'Execute Workflow'": {
      "main": [
        [
          {
            "node": "Get Rows - Not Enriched Yet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}