{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "2a2821a5-6703-4935-bbe1-04f33e9b8758",
      "name": "Decodo",
      "type": "@decodo/n8n-nodes-decodo.decodo",
      "position": [
        -320,
        528
      ],
      "parameters": {},
      "credentials": {},
      "typeVersion": 1
    },
    {
      "id": "e07f65d0-c492-4d9e-a6c2-d5ec31278c3e",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        528,
        848
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2fd41692-d12b-43aa-8de8-23774d6fc763",
      "name": "Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        928,
        608
      ],
      "parameters": {
        "jsCode": "const newItems = [];\n\nfor (const item of $input.all()) {\n  // Check common paths: item.json.output.Job OR item.json.Job OR item.json.output\n  const jobString = item.json.output?.Job || item.json.Job || item.json.output || \"\";\n\n  // 1. Skip if empty or contains the \"No open positions\" string\n  if (!jobString || typeof jobString !== 'string' || jobString.includes(\"No open positions\")) {\n    continue;\n  }\n\n  // 2. Split by new lines\n  const lines = jobString.split('\\n');\n\n  for (let line of lines) {\n    let cleanJob = line.trim();\n    \n    // 3. Remove \"Job Title:\" prefix (case-insensitive)\n    cleanJob = cleanJob.replace(/^Job Title:\\s*/i, \"\");\n\n    // 4. Remove Markdown formatting if present (like \"1. \" or \"- \")\n    cleanJob = cleanJob.replace(/^(\\d+\\.\\s*|-\\s*)/, \"\");\n\n    if (cleanJob.length > 0) {\n      newItems.push({\n        json: {\n          job: cleanJob\n        }\n      });\n    }\n  }\n}\n\nreturn newItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "35c926a5-16ad-4f91-9618-3be27c84b93a",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1360,
        512
      ],
      "parameters": {
        "text": "=Task: Filter the following list of jobs.\n\nTarget Criteria: {{ $('Job Name').item.json.Position }}\n\nJobs List: {{ $json.job }}\n\nInstructions:\n\nLook at the \"Target Criteria\" above.\n\nLook at the \"Jobs List\" extracted from the website.\n\nReturn ONLY the jobs from the list that match the Target Criteria \n\nIf a job is relevant but doesn't explicitly state the criteria name, include it if it clearly falls into that department.\n\nIf NO jobs match, return the exact phrase: \"No matching positions found\".\n\nOutput Format: Return a plain text list. No introductory text, no \"Here is your list,\" and no markdown formatting.",
        "options": {
          "systemMessage": ""
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "e7a1d3ce-2207-446a-8bae-c04bdc30084e",
      "name": "Google Gemini Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1360,
        784
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4beaa50b-115a-4738-a780-b4233195ef8f",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "disabled": true,
      "position": [
        -80,
        528
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "327931ea-cc59-452c-be0a-a6698365a6d8",
      "name": "Send a message",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1776,
        672
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "={{ $json.output }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "New job listed"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "1fdf4aff-dbff-4c7d-a478-fdcaee54430b",
      "name": "Send a message1",
      "type": "n8n-nodes-base.slack",
      "position": [
        1776,
        416
      ],
      "parameters": {
        "text": "=Here is the new listed job:\n{{ $json.output }}",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": "U09BDCAHRBN",
          "cachedResultName": "hafsa.karim"
        },
        "select": "user",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "f0a25984-5f41-4328-ba00-bc7f84a2dcb0",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1248,
        288
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 432,
        "content": "## Nodes: Schedule Trigger, Edit Fields\nControls when the workflow runs and defines the target job category (e.g., Engineering).\nChange the schedule interval or target department without touching the rest of the workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "b529e21a-8ca2-4045-a069-6a7569bce097",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -736,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 1120,
        "height": 432,
        "content": "\n## Nodes: Airtable Search Records\nFetches company career page URLs from Airtable.\nOnly records with valid links are processed, making it easy to manage multiple companies in one place.\n\n## Nodes: Decodo, Loop Over Items, Wait\nScrapes each career page and processes URLs in batches.\nThe wait node prevents rate limits and ensures stable scraping across multiple websites."
      },
      "typeVersion": 1
    },
    {
      "id": "d6ffaedd-61df-41b9-88ea-b7493ac8a741",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2000,
        288
      ],
      "parameters": {
        "width": 1120,
        "height": 592,
        "content": "### Title: Automated Job Scraping & Alerts with Decodo and Google Gemini\n\nThis workflow automatically monitors company career pages, extracts open job positions, filters them by a target department, and sends alerts when relevant roles appear. It is designed for job seekers, recruiters, and teams who want timely, noise-free job notifications without manually checking multiple websites.\n\n## How it works\n\nOn a schedule, the workflow fetches career page URLs from Airtable. Each page is scraped using Decodo, and Google Gemini extracts job titles and application links. The results are cleaned, filtered by department (for example, Engineering), and only matching jobs are sent as alerts via Slack and email.\n\n## Setup steps\n* Add career page URLs to Airtable.\n* Set the target job category in the Edit Fields node.\n* Connect Decodo, Google Gemini, Slack, and Gmail credentials.\n* Adjust the schedule trigger timing.\n* Activate the workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "a180a0f9-30ee-41a8-8b54-1ded07d60c90",
      "name": "Search records",
      "type": "n8n-nodes-base.airtable",
      "position": [
        -592,
        512
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appawawtQOODiz9zS",
          "cachedResultUrl": "https://airtable.com/appawawtQOODiz9zS",
          "cachedResultName": "Career Pages Tracker"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblFm9GBAhh9TohGu",
          "cachedResultUrl": "https://airtable.com/appawawtQOODiz9zS/tblFm9GBAhh9TohGu",
          "cachedResultName": "Table 1"
        },
        "options": {
          "fields": [
            "Link",
            "Website"
          ]
        },
        "operation": "search",
        "returnAll": "={{ true }}",
        "authentication": "airtableOAuth2Api",
        "filterByFormula": "NOT({Link} = '')"
      },
      "credentials": {
        "airtableOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "e52106e0-9fb6-4b3a-a14c-751d265f1452",
      "name": "Run Daily",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1216,
        512
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e1b1d1b8-821c-4eff-93ab-7a837902c7d8",
      "name": "Job Name",
      "type": "n8n-nodes-base.set",
      "position": [
        -960,
        512
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c43ddcfc-3fc7-4c62-a1c5-291fd8c67429",
              "name": "Position",
              "type": "string",
              "value": "Engineering"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8f0f9c15-e990-46d5-ab9d-ff7ba1c8dcdb",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        848,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 368,
        "height": 464,
        "content": "\n\n## Nodes: Code in JavaScript\nCleans AI output by removing formatting, empty results, and \u201cNo open positions.\u201d\nConverts jobs into structured items for reliable filtering."
      },
      "typeVersion": 1
    },
    {
      "id": "02b37d56-87fe-49a2-9146-26675ebbc8b6",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 368,
        "height": 448,
        "content": "\n\n\n\n## Nodes: AI Agent 1, Google Gemini Chat Model\nUses Google Gemini to extract clean job titles and application links from raw page content while ignoring navigation and non-job text."
      },
      "typeVersion": 1
    },
    {
      "id": "43133fa3-0f23-4cc3-9641-727c41a1128a",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1264,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 544,
        "height": 464,
        "content": "\n\n\n\n\n\n\n## Nodes: AI Agent, Google Gemini Chat Model 1, Slack, Gmail\nFilters jobs based on the target department and sends alerts.\nOnly relevant roles trigger Slack and email notifications."
      },
      "typeVersion": 1
    },
    {
      "id": "d3df37b6-6d8f-4412-b89a-070e0b77e681",
      "name": "Wait 5 seconds",
      "type": "n8n-nodes-base.wait",
      "position": [
        256,
        608
      ],
      "parameters": {
        "amount": 50
      },
      "typeVersion": 1.1
    },
    {
      "id": "811649b9-4e3a-4790-8d9b-137c61182947",
      "name": "Job extractor",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        528,
        608
      ],
      "parameters": {
        "text": "=Extract all job titles and their application URLs from the text below. Rules: > - Output ONLY a raw list.\n\nIgnore site navigation and company perks.\n\nIf no jobs are found, return \"No jobs\". {{ $json.results[0].content }}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 2.2
    }
  ],
  "connections": {
    "Decodo": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Send a message1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Job Name": {
      "main": [
        [
          {
            "node": "Search records",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run Daily": {
      "main": [
        [
          {
            "node": "Job Name",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Job extractor": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search records": {
      "main": [
        [
          {
            "node": "Decodo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 5 seconds": {
      "main": [
        [
          {
            "node": "Job extractor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait 5 seconds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Job extractor",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}