{
  "id": "44Vh3I9HIJgB6Ghz",
  "meta": {
    "builderVariant": "mcp",
    "aiBuilderAssisted": true
  },
  "name": "Watch any web page for changes and get an AI summary of what changed with Gemini",
  "tags": [],
  "nodes": [
    {
      "id": "395aa903-d197-4ae9-b98c-f1808a405dc8",
      "name": "Schedule Every 6 Hours",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        48,
        48
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 6
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "390145e7-de1f-467c-a076-46eac05e79b4",
      "name": "Set Page to Watch",
      "type": "n8n-nodes-base.set",
      "position": [
        272,
        48
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "label",
              "name": "label",
              "type": "string",
              "value": "Competitor pricing"
            },
            {
              "id": "url",
              "name": "url",
              "type": "string",
              "value": "https://example.com/pricing"
            },
            {
              "id": "sel",
              "name": "selector",
              "type": "string",
              "value": "main"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "9f56cec2-3d7f-4e12-81ff-1a71d9479ee8",
      "name": "Fetch Page",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        480,
        48
      ],
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "abf2270d-6883-4ed9-b9cd-49f0f1dcb6b5",
      "name": "Clean Page Text",
      "type": "n8n-nodes-base.code",
      "position": [
        944,
        32
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "let html = String($json.data || $json.body || '');\nconst sel = $('Set Page to Watch').item.json.selector;\nlet text = html.replace(/<script[\\s\\S]*?<\\/script>/gi, ' ').replace(/<style[\\s\\S]*?<\\/style>/gi, ' ').replace(/<[^>]+>/g, ' ').replace(/&nbsp;/g, ' ').replace(/\\s+/g, ' ').trim();\ntext = text.slice(0, 6000);\nreturn { label: $('Set Page to Watch').item.json.label, url: $('Set Page to Watch').item.json.url, currentText: text };"
      },
      "typeVersion": 2
    },
    {
      "id": "e5b9ccc5-87e5-4e74-8eda-e442b04b76c9",
      "name": "Get Last Snapshot",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1168,
        32
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Snapshots"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Select your spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "8ca8a77d-4f5f-43b2-a67f-a85f1a454b9b",
      "name": "Detect Change",
      "type": "n8n-nodes-base.code",
      "position": [
        1360,
        32
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const cur = $('Clean Page Text').item.json;\nconst prev = ($json && $json.Text != null) ? String($json.Text) : '';\nconst current = String(cur.currentText || '');\nconst isFirstRun = prev.length === 0;\nconst changed = !isFirstRun && prev !== current;\nreturn { label: cur.label, url: cur.url, previousText: prev, currentText: current, changed: changed, isFirstRun: isFirstRun };"
      },
      "typeVersion": 2
    },
    {
      "id": "61e0a4e8-7427-42c9-a941-3c5fc7f08f39",
      "name": "Changed?",
      "type": "n8n-nodes-base.if",
      "position": [
        1552,
        32
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.changed }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "1e66c817-7ce1-436f-a6d2-ce296572c7bf",
      "name": "Summarise Change with Gemini",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1808,
        16
      ],
      "parameters": {
        "text": "=You are a monitoring assistant. Below are the previous and current text of a web page we watch called \"{{ $json.label }}\". In two or three sentences, describe what actually changed in plain language (new prices, new features, removed items, wording changes). If the differences are trivial or cosmetic, say \"No meaningful change.\" Do not list the whole page.\n\nPREVIOUS:\n{{ $json.previousText }}\n\nCURRENT:\n{{ $json.currentText }}",
        "batching": {},
        "promptType": "define"
      },
      "typeVersion": 1.9
    },
    {
      "id": "260b8e60-37aa-4bb9-b28a-0cd80af69576",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1744,
        176
      ],
      "parameters": {
        "options": {
          "temperature": 0.2
        },
        "modelName": "models/gemini-3.1-flash-lite"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "a398b3ad-71ce-42d6-866e-92dc8a2a7fb8",
      "name": "Notify Change",
      "type": "n8n-nodes-base.slack",
      "position": [
        2096,
        16
      ],
      "parameters": {
        "text": "=*:eyes: Change detected: {{ $(\"Detect Change\").item.json.label }}*\n{{ $json.text }}\n{{ $(\"Detect Change\").item.json.url }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "#monitoring"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "1af7fb81-0327-4637-921f-a0eee21d8cf0",
      "name": "Update Snapshot (Changed)",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2272,
        16
      ],
      "parameters": {
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Snapshots"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Select your spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "09b1f4fe-9a26-419c-8283-c38ff534f368",
      "name": "Update Snapshot (Baseline)",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1808,
        336
      ],
      "parameters": {
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Snapshots"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "Select your spreadsheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "c8a66d61-e446-4732-9652-51f02774f78b",
      "name": "Report Fetch Failure",
      "type": "n8n-nodes-base.slack",
      "position": [
        720,
        144
      ],
      "parameters": {
        "text": "=*:x: Could not fetch {{ $(\"Set Page to Watch\").item.json.label }}*\nThe page did not respond. It will be retried on the next run.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": "#monitoring"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "690f8f9e-cdef-43d8-af8b-c2d9cf41415c",
      "name": "Overview Sticky",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -592,
        -144
      ],
      "parameters": {
        "width": 568,
        "height": 660,
        "content": "## Watch any web page for changes and get an AI summary of what changed\n\n### How it works\nInstead of re-reading a competitor page or a policy page yourself, this template watches it for you. On a schedule it fetches the page, strips it down to clean text, and compares it against the last snapshot stored in Google Sheets. On the very first run it just saves a baseline. When the text later changes, a Basic LLM Chain with Google Gemini reads the old and new versions and explains in two or three sentences what actually changed - a new price, a new feature, removed wording - rather than dumping the whole page, and calls out trivial edits as no meaningful change. Real changes are posted to Slack and the snapshot is updated so each change is reported once. Fetch failures are reported and retried next run.\n\n### Setup\n1. Connect Google Gemini (PaLM) API, Google Sheets and Slack.\n2. In Set Page to Watch, enter the label and URL to monitor.\n3. Point the Snapshots sheet at your spreadsheet and pick a Slack channel.\n\n### Customization tips\nWatch several pages by turning the config into sheet rows and looping."
      },
      "typeVersion": 1
    },
    {
      "id": "756eb461-ee41-47c2-a526-065a47955418",
      "name": "S1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 860,
        "height": 664,
        "content": "## 1. Fetch & clean\nRun on a schedule, fetch the page and strip it to clean text. Fetch failures go to Slack."
      },
      "typeVersion": 1
    },
    {
      "id": "26179022-e2ef-4f0a-88e9-8a5e69db21e7",
      "name": "S2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        880,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 620,
        "height": 664,
        "content": "## 2. Compare to last snapshot\nRead the previous snapshot from Sheets and diff it. First run saves a baseline silently."
      },
      "typeVersion": 1
    },
    {
      "id": "0ae55fcc-25c5-4804-b8d7-55e269847ce5",
      "name": "S3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1520,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 948,
        "height": 676,
        "content": "## 3. Summarise & notify (Basic LLM Chain)\nOn a real change, Gemini explains what changed, Slack is notified, and the snapshot is updated so each change is reported once."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "versionId": "d42d94aa-06f0-45ef-b46e-0378ff1b3226",
  "nodeGroups": [],
  "connections": {
    "Changed?": {
      "main": [
        [
          {
            "node": "Summarise Change with Gemini",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update Snapshot (Baseline)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Page": {
      "main": [
        [
          {
            "node": "Clean Page Text",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Report Fetch Failure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Detect Change": {
      "main": [
        [
          {
            "node": "Changed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Change": {
      "main": [
        [
          {
            "node": "Update Snapshot (Changed)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean Page Text": {
      "main": [
        [
          {
            "node": "Get Last Snapshot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Last Snapshot": {
      "main": [
        [
          {
            "node": "Detect Change",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Page to Watch": {
      "main": [
        [
          {
            "node": "Fetch Page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Every 6 Hours": {
      "main": [
        [
          {
            "node": "Set Page to Watch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Summarise Change with Gemini",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Summarise Change with Gemini": {
      "main": [
        [
          {
            "node": "Notify Change",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}