AutomationFlowsAI & RAG › Analyze Skill Gaps for Target Jobs with Browseract, Linkedin and Gpt-4o-mini

Analyze Skill Gaps for Target Jobs with Browseract, Linkedin and Gpt-4o-mini

ByisaWOW @isawow on n8n.io

This workflow collects a student’s skills and target role via an n8n Form, scrapes top LinkedIn job postings with BrowserAct, and uses OpenAI GPT-4o-mini to generate a skill gap report with courses and a 90-day plan, saving results to Google Sheets and emailing them via Gmail.…

Event trigger★★★★☆ complexityAI-powered14 nodesForm TriggerN8N Nodes BrowseractAgentOpenAI ChatGoogle SheetsGmail
AI & RAG Trigger: Event Nodes: 14 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #16146 — we link there as the canonical source.

This workflow follows the Agent → Form Trigger recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "ld12xcUKGbUyietL",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Skill Gap Analyzer \u2014 Student vs Job Market \u2014 BrowserAct + LinkedIn + GPT-4o-mini + Sheets + Gmail",
  "tags": [],
  "nodes": [
    {
      "id": "b74f7faf-02d5-466b-a808-5d298175f961",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        384,
        -544
      ],
      "parameters": {
        "color": 4,
        "width": 556,
        "height": 1252,
        "content": "## Skill Gap Analyzer \u2014 Student Profile vs Job Market \u2014 BrowserAct + LinkedIn + GPT-4o-mini + Google Sheets + Gmail\n\nFor students, freshers, and career changers who want to know exactly which skills they are missing for their target job role \u2014 compared against real live job postings. A student fills a form with their name, email, current skills, target role, experience level, location, and weekly study hours. A Code node validates the data and builds the LinkedIn job search URL. BrowserAct opens LinkedIn with a real stealth browser, scrolls through listings, and extracts required skills from the top 20 job postings \u2014 bypassing the scraping blocks that standard HTTP requests hit. A Code node cleans the raw scraped text. GPT-4o-mini compares the student's current skills against market demand from those 20 postings, identifies every missing skill by priority, recommends 3 free courses to fill the gaps, and generates a personalised 90-day week-by-week learning plan. A Code node parses all output sections. Google Sheets saves the full report. Gmail sends a formatted HTML email with the complete analysis and plan.\n\n## How it works\n- **1. Form \u2014 Student Skill Profile** collects name, email, target role, current skills (comma-separated), experience level, preferred location, and weekly study hours\n- **2. Code \u2014 Prepare Data and Build LinkedIn URL** validates inputs, parses skills into an array, and builds the LinkedIn job search URL with encoded role and location\n- **3. BrowserAct \u2014 Scrape LinkedIn Job Postings** uses a real stealth browser to open LinkedIn and extract required skills from the top 20 job postings\n- **4. Code \u2014 Extract Job Data** normalises the BrowserAct output across possible response field names, cleans whitespace, trims to 5000 characters, and passes all student data through\n- **5. AI Agent \u2014 Skill Gap Analysis** uses GPT-4o-mini with the student profile and scraped job data to produce: market skills with frequencies, skills the student already has, missing skills with priority, gap score, top 3 free courses with URLs, and a 13-week 90-day learning plan\n- **OpenAI \u2014 GPT-4o-mini Model** language model attached to the AI Agent\n- **6. Code \u2014 Parse Gap Analysis** extracts each labeled section from the AI output using regex and counts matched and missing skills\n- **7. Google Sheets \u2014 Save Gap Report** appends the full report as one row with 17 columns\n- **8. Gmail \u2014 Send 90-Day Learning Plan** sends a formatted HTML email with the full gap analysis, courses, and learning plan\n\n## Set up steps\n1. Install the BrowserAct community node: Settings \u2192 Community Nodes \u2192 Install `n8n-nodes-browseract`\n2. Sign up at browseract.com \u2014 join their Discord for 100 free credits\n3. Create a BrowserAct workflow that opens the LinkedIn URL, scrolls, and extracts job titles and required skills from top 20 postings. Copy the workflow ID and replace `YOUR_BROWSERACT_WORKFLOW_ID` in node 3\n4. In **3. BrowserAct** \u2014 connect your BrowserAct API credential\n5. In **OpenAI \u2014 GPT-4o-mini Model** \u2014 connect your OpenAI API credential\n6. In **7. Google Sheets \u2014 Save Gap Report** \u2014 connect Google Sheets OAuth2 credential and replace `YOUR_GOOGLE_SHEET_ID`. Create a sheet tab named Reports with columns: Student Name, Email, Target Role, Experience Level, Location, Student Skills, Market Skills, Skills You Have, Skills Missing, Gap Score, Have Count, Missing Count, Top 3 Courses, 90 Day Plan, Market Insight, LinkedIn URL, Date\n7. In **8. Gmail \u2014 Send 90-Day Learning Plan** \u2014 connect Gmail OAuth2 credential"
      },
      "typeVersion": 1
    },
    {
      "id": "5372b352-5e0c-44ee-8ec7-5683a5c4c6a1",
      "name": "Section \u2014 Student Skill Profile Form",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        -224
      ],
      "parameters": {
        "color": 5,
        "width": 340,
        "height": 324,
        "content": "## Student Skill Profile Form\nCollects name, email, target job role, current skills (comma-separated), experience level, preferred location, and weekly study hours available."
      },
      "typeVersion": 1
    },
    {
      "id": "6cecb18a-526d-448c-a471-51717ad7d6b5",
      "name": "Section \u2014 Data Preparation and LinkedIn Scrape",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1440,
        -224
      ],
      "parameters": {
        "color": 6,
        "width": 532,
        "height": 324,
        "content": "## Data Preparation and LinkedIn Scrape\nCode validates inputs and builds the LinkedIn search URL. BrowserAct opens LinkedIn with a real stealth browser and extracts required skills from the top 20 job postings."
      },
      "typeVersion": 1
    },
    {
      "id": "f94391bf-1031-434e-a724-2769a8ec9d6f",
      "name": "Section \u2014 Job Data Extraction and GPT-4o-mini Gap Analysis",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2000,
        -304
      ],
      "parameters": {
        "color": 6,
        "width": 564,
        "height": 644,
        "content": "## Job Data Extraction and GPT-4o-mini Gap Analysis\nCode normalises BrowserAct output. GPT-4o-mini compares student skills vs market demand from 20 job postings \u2014 produces missing skills by priority, gap score, top 3 free courses, and a 13-week learning plan."
      },
      "typeVersion": 1
    },
    {
      "id": "7345bced-d5f9-4c62-85ce-d94068d85e75",
      "name": "Section \u2014 Parse, Save to Sheets, and Email",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2640,
        -224
      ],
      "parameters": {
        "color": 4,
        "width": 676,
        "height": 420,
        "content": "## Parse, Save to Sheets, and Email\nCode parses all labeled sections from the AI output. Sheets appends the full report. Gmail sends the formatted HTML analysis and 90-day learning plan to the student."
      },
      "typeVersion": 1
    },
    {
      "id": "a3267d71-a050-4ee1-9ff6-9dfcf0a877a4",
      "name": "1. Form \u2014 Student Skill Profile",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        1168,
        -80
      ],
      "parameters": {
        "options": {},
        "formTitle": "Skill Gap Analyzer \u2014 Find What's Missing for Your Dream Job",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Your Full Name",
              "placeholder": "e.g. Priya Sharma",
              "requiredField": true
            },
            {
              "fieldLabel": "Your Email Address",
              "placeholder": "priya@email.com",
              "requiredField": true
            },
            {
              "fieldLabel": "Target Job Role",
              "placeholder": "e.g. Data Analyst, Frontend Developer, Digital Marketing Manager, Product Manager",
              "requiredField": true
            },
            {
              "fieldLabel": "Your Current Skills",
              "placeholder": "List your skills separated by commas \u2014 e.g. Python, Excel, SQL, Communication, HTML",
              "requiredField": true
            },
            {
              "fieldLabel": "Experience Level",
              "placeholder": "e.g. Fresher (0 experience) / Junior (0-1 year) / Mid-level (1-3 years)",
              "requiredField": true
            },
            {
              "fieldLabel": "Preferred Job Location",
              "placeholder": "e.g. India, United States, Remote, Bangalore",
              "requiredField": true
            },
            {
              "fieldLabel": "How many hours per week can you learn new skills?",
              "placeholder": "e.g. 5 (enter a number)",
              "requiredField": true
            }
          ]
        },
        "formDescription": "Enter your current skills and target role. AI will analyze the job market, find your skill gaps, and send you a free personalized 90-day learning plan."
      },
      "typeVersion": 2.2
    },
    {
      "id": "5daf4062-f319-47a3-afc7-240c58477d80",
      "name": "2. Code \u2014 Prepare Data and Build LinkedIn URL",
      "type": "n8n-nodes-base.code",
      "position": [
        1568,
        -96
      ],
      "parameters": {
        "jsCode": "const row = $json;\n\nconst studentName     = (row['Your Full Name'] || '').trim();\nconst email           = (row['Your Email Address'] || '').trim();\nconst targetRole      = (row['Target Job Role'] || '').trim();\nconst currentSkills   = (row['Your Current Skills'] || '').trim();\nconst experienceLevel = (row['Experience Level'] || 'Fresher').trim();\nconst location        = (row['Preferred Job Location'] || 'India').trim();\nconst weeklyHours     = parseFloat(row['How many hours per week can you learn new skills?']) || 5;\n\nif (!studentName || !email || !targetRole || !currentSkills) {\n  throw new Error('Name, Email, Target Role, and Current Skills are required.');\n}\n\nconst skillsArray = currentSkills\n  .split(',')\n  .map(s => s.trim())\n  .filter(s => s.length > 0);\n\nconst encodedRole     = encodeURIComponent(targetRole);\nconst encodedLocation = encodeURIComponent(location);\nconst linkedinUrl = `https://www.linkedin.com/jobs/search/?keywords=${encodedRole}&location=${encodedLocation}&sortBy=R`;\n\nconst today = new Date();\nconst day30 = new Date(today); day30.setDate(today.getDate() + 30);\nconst day60 = new Date(today); day60.setDate(today.getDate() + 60);\nconst day90 = new Date(today); day90.setDate(today.getDate() + 90);\n\nconst fmt = d => d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });\n\nreturn [{\n  json: {\n    studentName,\n    email,\n    targetRole,\n    currentSkills,\n    skillsArray,\n    skillsCount: skillsArray.length,\n    experienceLevel,\n    location,\n    weeklyHours,\n    linkedinUrl,\n    today: fmt(today),\n    day30: fmt(day30),\n    day60: fmt(day60),\n    day90: fmt(day90),\n    totalWeeks: 13\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "eed37428-7ed1-4c92-b08e-76c2848fff01",
      "name": "3. BrowserAct \u2014 Scrape LinkedIn Job Postings",
      "type": "n8n-nodes-browseract.BrowserAct",
      "position": [
        1824,
        -80
      ],
      "parameters": {
        "workflowId": "YOUR_BROWSERACT_WORKFLOW_ID",
        "workflowParams": "={{ JSON.stringify({ url: $json.linkedinUrl, targetRole: $json.targetRole, maxJobs: 20 }) }}"
      },
      "credentials": {},
      "typeVersion": 1
    },
    {
      "id": "aaec08e0-6005-4322-b3bb-470d146fb88a",
      "name": "4. Code \u2014 Extract Job Data",
      "type": "n8n-nodes-base.code",
      "position": [
        2048,
        -96
      ],
      "parameters": {
        "jsCode": "const browserOutput = $json;\nconst studentData   = $('2. Code \u2014 Prepare Data and Build LinkedIn URL').item.json;\n\nlet rawJobData = '';\n\nif (typeof browserOutput.result === 'string')        rawJobData = browserOutput.result;\nelse if (typeof browserOutput.output === 'string')   rawJobData = browserOutput.output;\nelse if (typeof browserOutput.content === 'string')  rawJobData = browserOutput.content;\nelse if (browserOutput.data?.text)                   rawJobData = browserOutput.data.text;\nelse if (typeof browserOutput.data === 'string')     rawJobData = browserOutput.data;\nelse                                                 rawJobData = JSON.stringify(browserOutput);\n\nlet cleaned = rawJobData\n  .replace(/\\n{3,}/g, '\\n\\n')\n  .replace(/\\t/g, ' ')\n  .trim();\n\nif (cleaned.length > 5000) {\n  cleaned = cleaned.substring(0, 5000) + '\\n[Trimmed to fit processing limit]';\n}\n\nif (!cleaned || cleaned.length < 50) {\n  throw new Error(\n    'BrowserAct returned empty job data. ' +\n    'Check that your BrowserAct workflow scrapes LinkedIn job listings correctly. ' +\n    'LinkedIn URL used: ' + studentData.linkedinUrl\n  );\n}\n\nreturn [{\n  json: {\n    jobListingsRaw: cleaned,\n    jobDataLength: cleaned.length,\n    studentName:     studentData.studentName,\n    email:           studentData.email,\n    targetRole:      studentData.targetRole,\n    currentSkills:   studentData.currentSkills,\n    skillsArray:     studentData.skillsArray,\n    skillsCount:     studentData.skillsCount,\n    experienceLevel: studentData.experienceLevel,\n    location:        studentData.location,\n    weeklyHours:     studentData.weeklyHours,\n    linkedinUrl:     studentData.linkedinUrl,\n    today:           studentData.today,\n    day30:           studentData.day30,\n    day60:           studentData.day60,\n    day90:           studentData.day90,\n    totalWeeks:      studentData.totalWeeks\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "ff18aa3a-b255-489d-acad-9d0f117eeaca",
      "name": "5. AI Agent \u2014 Skill Gap Analysis",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2272,
        -96
      ],
      "parameters": {
        "text": "=JOB POSTINGS DATA FROM LINKEDIN (Top 20 postings for {{ $json.targetRole }}):\n\n{{ $json.jobListingsRaw }}",
        "options": {
          "systemMessage": "=You are an expert career coach and job market analyst. Analyze the scraped LinkedIn job postings and the student's current skills to generate a detailed skill gap analysis.\n\n## STUDENT PROFILE\n- Name: {{ $json.studentName }}\n- Target Role: {{ $json.targetRole }}\n- Experience Level: {{ $json.experienceLevel }}\n- Location Preference: {{ $json.location }}\n- Current Skills: {{ $json.currentSkills }}\n- Weekly Learning Hours Available: {{ $json.weeklyHours }} hours per week\n- 90-Day Timeline: {{ $json.today }} to {{ $json.day90 }}\n\n## YOUR TASK\n1. Extract ALL required skills mentioned across the 20 job postings\n2. Count how often each skill is mentioned (frequency = market demand)\n3. Compare against student's current skills\n4. Identify skill gaps (what market wants but student does not have)\n5. Recommend exactly 3 free courses or resources to fill the top gaps\n6. Create a realistic 90-day learning plan based on {{ $json.weeklyHours }} hours per week\n\n## STRICT OUTPUT FORMAT \u2014 Use EXACTLY these labels:\n\nMARKET_SKILLS_FOUND:\n- [Skill Name] \u2014 mentioned in [X] out of 20 job postings\n[List all skills found, sorted by frequency \u2014 highest first]\n\nSKILLS_YOU_HAVE:\n- [Skill] \u2014 [one line: how valuable this is for the target role]\n[List every matching skill the student already has]\n\nSKILLS_MISSING:\n- [Skill] \u2014 Priority: [High/Medium/Low] \u2014 [one line: why this skill matters for the role]\n[List skills the market wants but student does not have \u2014 sorted by priority]\n\nGAP_SCORE:\n[A score like: 6 out of 12 required skills \u2014 50 percent ready]\n\nTOP_3_COURSES:\n1. [Course Name] \u2014 [Platform like Coursera/YouTube/freeCodeCamp] \u2014 [URL] \u2014 Fills gap: [skill name] \u2014 Duration: [X hours]\n2. [Course Name] \u2014 [Platform] \u2014 [URL] \u2014 Fills gap: [skill name] \u2014 Duration: [X hours]\n3. [Course Name] \u2014 [Platform] \u2014 [URL] \u2014 Fills gap: [skill name] \u2014 Duration: [X hours]\n\nNINETY_DAY_PLAN:\nPhase 1 \u2014 Foundation ({{ $json.today }} to {{ $json.day30 }}):\n- Week 1: [Specific skill to learn] \u2014 [Course or resource to use] \u2014 [What to build or practice]\n- Week 2: [Specific skill] \u2014 [Resource] \u2014 [Practice task]\n- Week 3: [Specific skill] \u2014 [Resource] \u2014 [Practice task]\n- Week 4: [Review and Mini Project] \u2014 Build [small project using Phase 1 skills]\n\nPhase 2 \u2014 Skill Building ({{ $json.day30 }} to {{ $json.day60 }}):\n- Week 5: [Next skill] \u2014 [Resource] \u2014 [Practice task]\n- Week 6: [Next skill] \u2014 [Resource] \u2014 [Practice task]\n- Week 7: [Next skill] \u2014 [Resource] \u2014 [Practice task]\n- Week 8: [Portfolio project] \u2014 Build [project that showcases Phase 1 and 2 skills]\n\nPhase 3 \u2014 Job Ready ({{ $json.day60 }} to {{ $json.day90 }}):\n- Week 9: [Advanced skill or polish existing] \u2014 [Resource]\n- Week 10: [Resume update] \u2014 Add all new skills and projects\n- Week 11: [Apply to 5 jobs] \u2014 Use LinkedIn with new skills\n- Week 12: [Interview prep] \u2014 Practice common [target role] interview questions\n- Week 13: [Final portfolio review] \u2014 Refine and publish\n\nMARKET_INSIGHT:\n[2-3 sentences: what the current job market for this role looks like based on the scraped postings]\n\nMOTIVATION_MESSAGE:\n[One encouraging paragraph personalized to this student's situation \u2014 honest but positive]"
        },
        "promptType": "define"
      },
      "typeVersion": 1.9
    },
    {
      "id": "67b11578-8fd9-4f99-94a2-06572703862a",
      "name": "OpenAI \u2014 GPT-4o-mini Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2272,
        176
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "bf6d95e3-b716-4e12-9ebe-802976feb87a",
      "name": "6. Code \u2014 Parse Gap Analysis",
      "type": "n8n-nodes-base.code",
      "position": [
        2688,
        -96
      ],
      "parameters": {
        "jsCode": "const output      = $('5. AI Agent \u2014 Skill Gap Analysis').item.json.output || '';\nconst studentData = $('4. Code \u2014 Extract Job Data').item.json;\n\nconst extract = (label, nextLabel) => {\n  const pattern = nextLabel\n    ? new RegExp(label + ':\\\\s*([\\\\s\\\\S]*?)(?=\\\\n' + nextLabel + ':|$)')\n    : new RegExp(label + ':\\\\s*([\\\\s\\\\S]*)$');\n  const m = output.match(pattern);\n  return m ? m[1].trim() : '';\n};\n\nconst marketSkills      = extract('MARKET_SKILLS_FOUND', 'SKILLS_YOU_HAVE');\nconst skillsYouHave     = extract('SKILLS_YOU_HAVE', 'SKILLS_MISSING');\nconst skillsMissing     = extract('SKILLS_MISSING', 'GAP_SCORE');\nconst gapScore          = extract('GAP_SCORE', 'TOP_3_COURSES');\nconst top3Courses       = extract('TOP_3_COURSES', 'NINETY_DAY_PLAN');\nconst ninetyDayPlan     = extract('NINETY_DAY_PLAN', 'MARKET_INSIGHT');\nconst marketInsight     = extract('MARKET_INSIGHT', 'MOTIVATION_MESSAGE');\nconst motivationMessage = extract('MOTIVATION_MESSAGE', null);\n\nconst missingCount = (skillsMissing.match(/Priority:/g) || []).length;\nconst haveCount    = (skillsYouHave.match(/\\n-/g) || []).length;\n\nif (!skillsMissing || skillsMissing.length < 10) {\n  throw new Error(\n    'GPT did not return a valid gap analysis. Job data may be insufficient. ' +\n    'Preview: ' + output.substring(0, 200)\n  );\n}\n\nreturn [{\n  json: {\n    marketSkills,\n    skillsYouHave,\n    skillsMissing,\n    gapScore,\n    top3Courses,\n    ninetyDayPlan,\n    marketInsight,\n    motivationMessage,\n    missingCount,\n    haveCount,\n    studentName:     studentData.studentName,\n    email:           studentData.email,\n    targetRole:      studentData.targetRole,\n    currentSkills:   studentData.currentSkills,\n    experienceLevel: studentData.experienceLevel,\n    location:        studentData.location,\n    weeklyHours:     studentData.weeklyHours,\n    linkedinUrl:     studentData.linkedinUrl,\n    today:           studentData.today,\n    day30:           studentData.day30,\n    day60:           studentData.day60,\n    day90:           studentData.day90\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "e2637029-e4f5-4764-9fab-daa4209f4f25",
      "name": "7. Google Sheets \u2014 Save Gap Report",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2880,
        -96
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $now.toFormat('dd MMMM yyyy HH:mm') }}",
            "Email": "={{ $json.email }}",
            "Location": "={{ $json.location }}",
            "Gap Score": "={{ $json.gapScore }}",
            "Have Count": "={{ $json.haveCount }}",
            "90 Day Plan": "={{ $json.ninetyDayPlan }}",
            "Target Role": "={{ $json.targetRole }}",
            "LinkedIn URL": "={{ $json.linkedinUrl }}",
            "Student Name": "={{ $json.studentName }}",
            "Market Skills": "={{ $json.marketSkills }}",
            "Missing Count": "={{ $json.missingCount }}",
            "Top 3 Courses": "={{ $json.top3Courses }}",
            "Market Insight": "={{ $json.marketInsight }}",
            "Skills Missing": "={{ $json.skillsMissing }}",
            "Student Skills": "={{ $json.currentSkills }}",
            "Skills You Have": "={{ $json.skillsYouHave }}",
            "Experience Level": "={{ $json.experienceLevel }}"
          },
          "schema": [
            {
              "id": "Student Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Student Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Target Role",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Target Role",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Experience Level",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Experience Level",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Location",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Location",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Student Skills",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Student Skills",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Market Skills",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Market Skills",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Skills You Have",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Skills You Have",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Skills Missing",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Skills Missing",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Gap Score",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Gap Score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Have Count",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Have Count",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Missing Count",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Missing Count",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Top 3 Courses",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Top 3 Courses",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "90 Day Plan",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "90 Day Plan",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Market Insight",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Market Insight",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LinkedIn URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "LinkedIn URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Reports"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "24b58746-31a8-49da-aa76-b6079fc563e9",
      "name": "8. Gmail \u2014 Send 90-Day Learning Plan",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3120,
        -96
      ],
      "parameters": {
        "sendTo": "={{ $('6. Code \u2014 Parse Gap Analysis').item.json.email }}",
        "message": "=<div style=\"font-family:Arial,sans-serif;max-width:700px;margin:0 auto;background:#f4f4f4;\">\n\n  <div style=\"background:#1a1a2e;padding:28px 32px;border-radius:8px 8px 0 0;\">\n    <h1 style=\"color:#ffffff;font-size:24px;margin:0;\">Skill Gap Analysis Report</h1>\n    <p style=\"color:#aaaaaa;font-size:14px;margin:8px 0 0;\">Target Role: {{ $('6. Code \u2014 Parse Gap Analysis').item.json.targetRole }}</p>\n  </div>\n\n  <div style=\"background:#4a90e2;padding:10px 32px;\">\n    <p style=\"color:#fff;font-size:13px;margin:0;\">\n      {{ $('6. Code \u2014 Parse Gap Analysis').item.json.studentName }}\n      &nbsp;\u2022&nbsp; {{ $('6. Code \u2014 Parse Gap Analysis').item.json.location }}\n      &nbsp;\u2022&nbsp; {{ $('6. Code \u2014 Parse Gap Analysis').item.json.experienceLevel }}\n      &nbsp;\u2022&nbsp; {{ $('6. Code \u2014 Parse Gap Analysis').item.json.weeklyHours }} hrs/week available\n    </p>\n  </div>\n\n  <div style=\"background:#ffffff;padding:28px 32px;\">\n\n    <div style=\"background:#f0f4ff;border-left:4px solid #4a90e2;padding:16px;border-radius:0 8px 8px 0;margin-bottom:24px;\">\n      <h2 style=\"margin:0 0 6px;font-size:16px;color:#1a1a2e;\">Your Readiness Score</h2>\n      <p style=\"margin:0;font-size:20px;font-weight:700;color:#1a1a2e;\">{{ $('6. Code \u2014 Parse Gap Analysis').item.json.gapScore }}</p>\n      <p style=\"margin:6px 0 0;font-size:13px;color:#666;\">{{ $('6. Code \u2014 Parse Gap Analysis').item.json.haveCount }} skills matched &nbsp;|&nbsp; {{ $('6. Code \u2014 Parse Gap Analysis').item.json.missingCount }} skills to learn</p>\n    </div>\n\n    <h2 style=\"font-size:17px;color:#1a1a2e;border-bottom:2px solid #e0e0e0;padding-bottom:8px;\">Skills You Already Have</h2>\n    <pre style=\"font-family:Arial,sans-serif;font-size:13px;color:#2e7d32;line-height:1.9;white-space:pre-wrap;background:#f1f8f1;padding:16px;border-radius:8px;margin-bottom:24px;\">{{ $('6. Code \u2014 Parse Gap Analysis').item.json.skillsYouHave }}</pre>\n\n    <h2 style=\"font-size:17px;color:#1a1a2e;border-bottom:2px solid #e0e0e0;padding-bottom:8px;\">Skills You Need to Learn</h2>\n    <pre style=\"font-family:Arial,sans-serif;font-size:13px;color:#c62828;line-height:1.9;white-space:pre-wrap;background:#fff5f5;padding:16px;border-radius:8px;margin-bottom:24px;\">{{ $('6. Code \u2014 Parse Gap Analysis').item.json.skillsMissing }}</pre>\n\n    <div style=\"background:#fff8e1;border-left:4px solid #ffa000;padding:16px;border-radius:0 8px 8px 0;margin-bottom:24px;\">\n      <h2 style=\"margin:0 0 10px;font-size:16px;color:#1a1a2e;\">Top 3 Free Courses to Fill Your Gaps</h2>\n      <pre style=\"font-family:Arial,sans-serif;font-size:13px;color:#444;line-height:1.9;white-space:pre-wrap;margin:0;\">{{ $('6. Code \u2014 Parse Gap Analysis').item.json.top3Courses }}</pre>\n    </div>\n\n    <h2 style=\"font-size:17px;color:#1a1a2e;border-bottom:2px solid #e0e0e0;padding-bottom:8px;\">Your Personalized 90-Day Learning Plan</h2>\n    <pre style=\"font-family:Arial,sans-serif;font-size:13px;color:#333;line-height:1.9;white-space:pre-wrap;background:#f9f9f9;padding:16px;border-radius:8px;margin-bottom:24px;\">{{ $('6. Code \u2014 Parse Gap Analysis').item.json.ninetyDayPlan }}</pre>\n\n    <h2 style=\"font-size:17px;color:#1a1a2e;border-bottom:2px solid #e0e0e0;padding-bottom:8px;\">Market Demand \u2014 Skills from Top 20 Job Postings</h2>\n    <pre style=\"font-family:Arial,sans-serif;font-size:13px;color:#333;line-height:1.8;white-space:pre-wrap;background:#f9f9f9;padding:16px;border-radius:8px;margin-bottom:24px;\">{{ $('6. Code \u2014 Parse Gap Analysis').item.json.marketSkills }}</pre>\n\n    <div style=\"background:#e8f5e9;border-left:4px solid #43a047;padding:16px;border-radius:0 8px 8px 0;margin-bottom:24px;\">\n      <h2 style=\"margin:0 0 8px;font-size:16px;color:#1a1a2e;\">Market Insight</h2>\n      <p style=\"margin:0;font-size:14px;color:#333;line-height:1.7;\">{{ $('6. Code \u2014 Parse Gap Analysis').item.json.marketInsight }}</p>\n    </div>\n\n    <div style=\"background:#fce4ec;border-left:4px solid #e91e63;padding:16px;border-radius:0 8px 8px 0;\">\n      <h2 style=\"margin:0 0 8px;font-size:16px;color:#1a1a2e;\">A Note for You</h2>\n      <p style=\"margin:0;font-size:14px;color:#333;line-height:1.7;\">{{ $('6. Code \u2014 Parse Gap Analysis').item.json.motivationMessage }}</p>\n    </div>\n\n  </div>\n\n  <div style=\"background:#1a1a2e;padding:14px 32px;text-align:center;border-radius:0 0 8px 8px;\">\n    <p style=\"color:#888;font-size:11px;margin:0;\">Powered by n8n + BrowserAct + GPT-4o-mini</p>\n    <p style=\"color:#888;font-size:11px;margin:4px 0 0;\">Job data scraped from LinkedIn for: {{ $('6. Code \u2014 Parse Gap Analysis').item.json.targetRole }}</p>\n  </div>\n\n</div>",
        "options": {
          "senderName": "Skill Gap Analyzer"
        },
        "subject": "=Your Skill Gap Report \u2014 {{ $('6. Code \u2014 Parse Gap Analysis').item.json.targetRole }} | {{ $('6. Code \u2014 Parse Gap Analysis').item.json.gapScore }}"
      },
      "typeVersion": 2.1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "05137988-f49d-4725-b6dc-9eb6b550fc95",
  "connections": {
    "4. Code \u2014 Extract Job Data": {
      "main": [
        [
          {
            "node": "5. AI Agent \u2014 Skill Gap Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI \u2014 GPT-4o-mini Model": {
      "ai_languageModel": [
        [
          {
            "node": "5. AI Agent \u2014 Skill Gap Analysis",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "6. Code \u2014 Parse Gap Analysis": {
      "main": [
        [
          {
            "node": "7. Google Sheets \u2014 Save Gap Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1. Form \u2014 Student Skill Profile": {
      "main": [
        [
          {
            "node": "2. Code \u2014 Prepare Data and Build LinkedIn URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5. AI Agent \u2014 Skill Gap Analysis": {
      "main": [
        [
          {
            "node": "6. Code \u2014 Parse Gap Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7. Google Sheets \u2014 Save Gap Report": {
      "main": [
        [
          {
            "node": "8. Gmail \u2014 Send 90-Day Learning Plan",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3. BrowserAct \u2014 Scrape LinkedIn Job Postings": {
      "main": [
        [
          {
            "node": "4. Code \u2014 Extract Job Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2. Code \u2014 Prepare Data and Build LinkedIn URL": {
      "main": [
        [
          {
            "node": "3. BrowserAct \u2014 Scrape LinkedIn Job Postings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow collects a student’s skills and target role via an n8n Form, scrapes top LinkedIn job postings with BrowserAct, and uses OpenAI GPT-4o-mini to generate a skill gap report with courses and a 90-day plan, saving results to Google Sheets and emailing them via Gmail.…

Source: https://n8n.io/workflows/16146/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This workflow collects a student’s profile via an n8n form, scrapes relevant LinkedIn job postings with BrowserAct, uses OpenAI GPT-4o-mini to generate a skill gap report and 90-day learning plan, the

Form Trigger, N8N Nodes Browseract, Agent +3
AI & RAG

This n8n workflow template automates your lead generation and follow-up process using AI. It captures leads through a form, enriches them with company data, classifies them into different categories,

Gmail, Output Parser Structured, Form Trigger +5
AI & RAG

The workflow runs every hour with a randomized delay of 5–20 minutes to help distribute load. It records the exact date and time a lead is emailed so you can track outreach. Follow-ups are automatical

Google Sheets, Agent, OpenAI Chat +5
AI & RAG

This n8n workflow automates turning short user ideas into production-ready real-estate marketing assets (photorealistic images and optional 360° videos). A form submission seeds a prompt board → an LL

Form Trigger, Google Sheets, Agent +6
AI & RAG

Transform your manual hiring process into an intelligent evaluation system that saves 15-20 minutes per candidate! This workflow automates the entire candidate assessment pipeline - from CSV/XLSX uplo

Form Trigger, Google Sheets, Google Drive +8