{
  "nodes": [
    {
      "id": "5d647c78-50ae-4c73-84d8-2a75c895154b",
      "name": "Run Workflow Manually",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "c24a19f6-a041-4d24-b169-907f45e762ef",
      "name": "Read PBN Sites from Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        208,
        0
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 879625869,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1N9xfOX8V6JFATJFaoc-_0xUnYWt-gWD9FmvHKQ0hNfc/edit#gid=879625869",
          "cachedResultName": "PBNs"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1N9xfOX8V6JFATJFaoc-_0xUnYWt-gWD9FmvHKQ0hNfc/edit?gid=879625869#gid=879625869"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "2c18d612-aa4f-4cae-81f6-5b3744eba319",
      "name": "Filter Unprocessed PBN Rows",
      "type": "n8n-nodes-base.code",
      "position": [
        416,
        0
      ],
      "parameters": {
        "jsCode": "// Input: All rows from Google Sheet\n// Output: Rows starting from the first row where \"Offboarded Links\" is blank\n\nlet rows = items.map(item => item.json);\n\n// Find the index of the first row where \"Offboarded Links\" is blank or empty\nlet startIndex = rows.findIndex(row => \n    row[\"Offboarded Links\"] === \"\" || row[\"Offboarded Links\"] === null || row[\"Offboarded Links\"] === undefined\n);\n\n// \u0905\u0917\u0930 \u0915\u094b\u0908 match \u0928\u0939\u0940\u0902 \u092e\u093f\u0932\u093e \u0924\u094b \u0916\u093e\u0932\u0940 array return \u0915\u0930\u094b\nif (startIndex === -1) {\n    return [];\n}\n\n// \u0909\u0938 row \u0938\u0947 \u0932\u0947\u0915\u0930 \u092c\u093e\u0915\u0940 \u0938\u092d\u0940 rows return \u0915\u0930\u094b\nlet filteredRows = rows.slice(startIndex);\n\n// Output \u0915\u094b n8n \u0915\u0947 \u0932\u093f\u090f format \u0915\u0930\u094b\nreturn filteredRows.map(row => ({ json: row }));\n"
      },
      "typeVersion": 2
    },
    {
      "id": "a66eb36b-46ef-4cc0-89be-2e53c32d5d24",
      "name": "Loop Through Each PBN",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        624,
        0
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "f48e6d1c-5ff6-45c3-9ca0-780b01ce4640",
      "name": "Fetch PBN Site HTML",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        864,
        16
      ],
      "parameters": {
        "url": "=https://{{ $json['Site URL'] }}",
        "options": {}
      },
      "retryOnFail": true,
      "typeVersion": 4.2,
      "waitBetweenTries": 3000
    },
    {
      "id": "404d6187-7fd6-4811-8844-fc4e3712b6fe",
      "name": "Read Offboarded Project Domains",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1072,
        16
      ],
      "parameters": {
        "options": {
          "dataLocationOnSheet": {
            "values": {
              "range": "A1:A",
              "rangeDefinition": "specifyRangeA1"
            }
          }
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1N9xfOX8V6JFATJFaoc-_0xUnYWt-gWD9FmvHKQ0hNfc/edit#gid=0",
          "cachedResultName": "offboard projects"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1N9xfOX8V6JFATJFaoc-_0xUnYWt-gWD9FmvHKQ0hNfc/edit?gid=879625869#gid=879625869"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "05c73580-d4c0-4da1-973b-e5e5e2a10f7b",
      "name": "Match Domains in HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        1280,
        16
      ],
      "parameters": {
        "jsCode": "// Get input domains\nconst inputItems = $input.all();\nconst domains = inputItems.map(item => {\n  try {\n    const url = new URL(item.json[\"Website URLs\"]);\n    return url.hostname.replace(/^www\\./, \"\"); // Remove www.\n  } catch (e) {\n    return null;\n  }\n}).filter(Boolean);\n\n// Get HTML Data\nconst htmlData = $('Fetch PBN Site HTML').first().json.data;\n\n// Check matches\nlet matched = [];\nfor (const domain of domains) {\n  if (htmlData.includes(domain)) {\n    matched.push(domain);\n  }\n}\n\n// Return result\nif (matched.length > 0) {\n  return matched.map(d => ({ json: { matched_domain: d } }));\n} else {\n  return [{ json: { matched_domain: 0 } }];\n}\n"
      },
      "typeVersion": 2
    },
    {
      "id": "30df9e6e-4ca4-4f50-8021-6d76ee8ebdab",
      "name": "Prepare Row Update Payload",
      "type": "n8n-nodes-base.set",
      "position": [
        1488,
        16
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "3efc5b75-e346-45df-8cb9-e9efd6aa8bcd",
              "name": "url",
              "type": "string",
              "value": "={{ $('Loop Through Each PBN').first().json[\"row_number\"] }}\n"
            },
            {
              "id": "fca4ac9b-3ee6-4aba-b0a4-ef0782caa373",
              "name": "mach",
              "type": "string",
              "value": "={{ $json.matched_domain }}"
            },
            {
              "id": "035b2872-896c-4c52-9216-c7f5bc5a4963",
              "name": "HTML",
              "type": "string",
              "value": "={{ $('Fetch PBN Site HTML').first().json[\"data\"] }}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "db8377d6-1fe3-4ec6-916f-1794aef3b426",
      "name": "Write Matched Domain to PBNs Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1680,
        16
      ],
      "parameters": {
        "columns": {
          "value": {
            "row_number": "={{ $json.url }}",
            "Offboarded Links": "={{ $json.mach }}"
          },
          "schema": [
            {
              "id": "Site URL",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Site URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Offboarded Links",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Offboarded Links",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "HTML",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "HTML",
              "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": 879625869,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1N9xfOX8V6JFATJFaoc-_0xUnYWt-gWD9FmvHKQ0hNfc/edit#gid=879625869",
          "cachedResultName": "PBNs"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1N9xfOX8V6JFATJFaoc-_0xUnYWt-gWD9FmvHKQ0hNfc/edit?gid=0#gid=0"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "17a1feff-ba0f-4323-b817-83b7f34b9ed5",
      "name": "Pause Before Next Iteration",
      "type": "n8n-nodes-base.wait",
      "position": [
        1856,
        16
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "bdbdc364-db6a-4cfe-aee2-2c8dc244bbbf",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -480,
        -240
      ],
      "parameters": {
        "width": 432,
        "height": 656,
        "content": "## PBN Offboarded Link Checker\n\nThis workflow automatically checks all PBN sites to detect\nif any offboarded client domain is still linked on them.\nIt runs row by row, fetches live HTML of each PBN, and\ncompares it against your offboard project list. If a match\nis found, it writes the matched domain directly into the\n\"Offboarded Links\" column in your PBNs sheet \u2014 so you\nalways know which PBN still carries a dead link.\n\n## How it works\n1. Reads all PBN sites from the \"PBNs\" Google Sheet.\n2. Skips rows already processed (where \"Offboarded Links\" is filled).\n3. Loops one by one \u2014 fetches live HTML of each PBN site.\n4. Pulls the offboarded project domain list from a separate sheet.\n5. Checks if any offboarded domain exists inside that HTML.\n6. Writes the matched domain into the PBNs sheet & moves to next.\n\n## Setup steps\n1. Connect your Google account in credentials.\n2. Set the correct Google Sheet URL & sheet names.\n3. Make sure \"offboard projects\" sheet has domains in Column A.\n4. Run manually using the trigger node."
      },
      "typeVersion": 1
    },
    {
      "id": "742384c7-ca32-484b-845c-30c6ccfddd79",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        208,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 192,
        "content": "## Data Fetching\n\nReads all PBN rows from Google Sheets,\nthen filters out already-processed rows\nso only new/unchecked PBNs move forward."
      },
      "typeVersion": 1
    },
    {
      "id": "10e0cfbe-8107-4e4d-9ec4-9c4d65783514",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        624,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 752,
        "height": 208,
        "content": "## HTML Fetch & Domain Matching\n\nLoops through each PBN one by one, fetches\nits live HTML, then checks if any offboarded\nclient domain is present inside that HTML."
      },
      "typeVersion": 1
    },
    {
      "id": "eac0c950-5152-44e3-b124-2845a12826d0",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1488,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 464,
        "height": 208,
        "content": "## Update & Loop Back\n\nStructures the matched result, writes it\ninto the PBNs sheet, then pauses briefly\nbefore moving to the next PBN in the loop."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Fetch PBN Site HTML": {
      "main": [
        [
          {
            "node": "Read Offboarded Project Domains",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Through Each PBN": {
      "main": [
        [],
        [
          {
            "node": "Fetch PBN Site HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Match Domains in HTML": {
      "main": [
        [
          {
            "node": "Prepare Row Update Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run Workflow Manually": {
      "main": [
        [
          {
            "node": "Read PBN Sites from Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read PBN Sites from Sheet": {
      "main": [
        [
          {
            "node": "Filter Unprocessed PBN Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Row Update Payload": {
      "main": [
        [
          {
            "node": "Write Matched Domain to PBNs Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Unprocessed PBN Rows": {
      "main": [
        [
          {
            "node": "Loop Through Each PBN",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pause Before Next Iteration": {
      "main": [
        [
          {
            "node": "Loop Through Each PBN",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Offboarded Project Domains": {
      "main": [
        [
          {
            "node": "Match Domains in HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Matched Domain to PBNs Sheet": {
      "main": [
        [
          {
            "node": "Pause Before Next Iteration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}