This workflow corresponds to n8n.io template #15429 — we link there as the canonical source.
This workflow follows the Gmail → HTTP Request 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 →
{
"id": "cQmkcbksmFo4quKl",
"name": "Creator Template - Competitor Change Monitor",
"tags": [],
"nodes": [
{
"id": "35e2288f-23e2-4ce0-8930-42c61efcf093",
"name": "Setup Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-144,
-496
],
"parameters": {
"color": 5,
"width": 902,
"height": 1448,
"content": "## \ud83d\udd75\ufe0f Competitor Change Monitor\n\nAutomatically tracks your competitors' websites on a weekly schedule, detects what changed, and delivers an AI-written intelligence digest as a Gmail draft \u2014 ready to share with your team.\n\n---\n\n## \u2699\ufe0f How It Works\n\n**1. Weekly Schedule**\nTriggers automatically once a week. You can adjust the frequency directly in the Schedule Trigger node.\n\n**2. Define Competitors**\nA Code node where you list the competitors you want to monitor. Each entry includes a `name`, `url`, and `watch_for` description (e.g. \"pricing changes\", \"new features\").\n\n**3. HTTP - Fetch Competitor Page**\nFetches the raw HTML of each competitor URL via an HTTP GET request. Runs once per competitor in the list.\n\n**4. Track Snapshot Changes**\nStrips all HTML tags, scripts, and styles down to clean readable text (up to 12,000 characters per page). Compares the current text against the last stored snapshot using n8n's built-in static data \u2014 no external database needed. Flags whether the page has `changed: true` or `false`.\n\n**5. Build Digest Prompt**\nCollects all changed pages and assembles a structured prompt for the AI. If nothing changed, it instructs the AI to produce a short no-change digest instead.\n\n**6. OpenAI - Summarize Competitor Changes**\nSends the prompt to GPT-4.1-mini which returns a plain-text competitive intelligence report covering:\n- Executive summary\n- Material changes by competitor\n- Suggested response actions\n- Watch items for the next run\n\n**7. Format Digest Email**\nFormats the AI output into an HTML email body and adds a date-stamped subject line like `Competitor change digest - 2026-05-01`.\n\n**8. Gmail - Draft Digest**\nSaves the formatted digest as a Gmail draft addressed to your recipient. Nothing is auto-sent \u2014 always review before sending.\n\n---\n\n## \ud83d\udd27 Setup Checklist\n\n- [ ] Open **Define Competitors** and add your competitor `name`, `url`, and `watch_for` values\n- [ ] Open **Build Digest Prompt** and replace `replace-me@example.com` with your recipient email\n- [x] Connect your **OpenAI** credential to the OpenAI node\n- [ ] Connect your **Gmail OAuth2** credential to the Gmail node\n- [ ] Run the workflow **once manually** to store the first baseline snapshots\n- [ ] **Activate** the workflow \u2014 weekly monitoring begins automatically\n\n---\n\n## \u26a0\ufe0f Things to Know\n\n- The **first run stores baselines only** \u2014 no digest is generated until the second run detects a diff\n- Snapshots are stored in **n8n workflow static data** \u2014 clearing static data resets all baselines\n- Page text is capped at `12,000` characters per competitor to stay within token limits\n- Sites with heavy JavaScript rendering may return incomplete snapshots via HTTP \u2014 consider a headless browser node for those\n- Adjust the schedule in the **Weekly Schedule** node to run daily or bi-weekly as needed"
},
"typeVersion": 1
},
{
"id": "f9e987b2-ca04-4561-88ca-7099f89e0ff3",
"name": "Weekly Schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
848,
96
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.3
},
{
"id": "0243b60b-bb28-4756-88de-4c6bab7b2c54",
"name": "Define Competitors",
"type": "n8n-nodes-base.code",
"position": [
1088,
96
],
"parameters": {
"jsCode": "// Replace this array with your competitors, pricing pages, changelog URLs, or product pages.\nconst competitors = [\n { name: \"Competitor A\", url: \"https://example.com/pricing\", watch_for: \"pricing, plans, positioning\" },\n { name: \"Competitor B\", url: \"https://example.org/features\", watch_for: \"features, integrations, headline changes\" }\n];\n\nreturn competitors.map((competitor) => ({ json: competitor }));"
},
"typeVersion": 2
},
{
"id": "db802d84-744c-427f-a060-0c98dd417f61",
"name": "HTTP - Fetch Competitor Page",
"type": "n8n-nodes-base.httpRequest",
"position": [
1360,
96
],
"parameters": {
"url": "={{ .url }}",
"options": {
"timeout": 20000,
"redirect": {}
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "9d3166d3-c737-4957-a4a0-c463ec2abdc3",
"name": "Track Snapshot Changes",
"type": "n8n-nodes-base.code",
"position": [
1616,
96
],
"parameters": {
"jsCode": "const page = $json.body || $json.data || $json.html || JSON.stringify($json);\nconst text = String(page)\n .replace(/<script[\\s\\S]*?<\\/script>/gi, \" \")\n .replace(/<style[\\s\\S]*?<\\/style>/gi, \" \")\n .replace(/<[^>]+>/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 12000);\n\nconst staticData = $getWorkflowStaticData(\"global\");\nstaticData.snapshots = staticData.snapshots || {};\n\nconst key = $json.url;\nconst previous = staticData.snapshots[key];\nstaticData.snapshots[key] = {\n captured_at: new Date().toISOString(),\n text\n};\n\nconst changed = !previous || previous.text !== text;\n\nreturn [{\n json: {\n name: $json.name,\n url: $json.url,\n watch_for: $json.watch_for,\n changed,\n previous_text: previous?.text || \"\",\n current_text: text,\n captured_at: staticData.snapshots[key].captured_at\n }\n}];"
},
"typeVersion": 2
},
{
"id": "4c6b1a0c-8a50-442d-9846-935bdf7c82e5",
"name": "Build Digest Prompt",
"type": "n8n-nodes-base.code",
"position": [
1872,
96
],
"parameters": {
"jsCode": "const items = $input.all().map((item) => item.json);\nconst changed = items.filter((item) => item.changed);\n\nconst prompt = changed.length\n ? changed.map((item) => [\n `COMPETITOR: ${item.name}`,\n `URL: ${item.url}`,\n `WATCH FOR: ${item.watch_for}`,\n `PREVIOUS SNAPSHOT:\\n${item.previous_text || \"(first run - no previous snapshot)\"}`,\n `CURRENT SNAPSHOT:\\n${item.current_text}`\n ].join(\"\\n\")).join(\"\\n\\n---\\n\\n\")\n : \"No competitors changed since the last run. Create a short no-change digest.\";\n\nreturn [{\n json: {\n changed_count: changed.length,\n total_checked: items.length,\n prompt,\n recipient_email: \"user@example.com\"\n }\n}];"
},
"typeVersion": 2
},
{
"id": "b795e60b-4cd5-467c-9e7e-838c85333012",
"name": "OpenAI - Summarize Competitor Changes",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
2080,
96
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "gpt-4.1-mini"
},
"options": {
"temperature": 0.2
},
"messages": {
"values": [
{
"role": "system",
"content": "You are a concise competitive intelligence analyst. Return a practical email digest in plain text. No markdown tables."
},
{
"content": "=Checked {{ $json.total_checked }} competitors. Changed pages: {{ $json.changed_count }}.\n\nAnalyze the snapshots below. Focus on pricing, positioning, offers, product launches, feature changes, and possible sales/marketing implications.\n\n{{ $json.prompt }}\n\nWrite:\n1. Executive summary\n2. Material changes by competitor\n3. Suggested response actions\n4. Watch items for next run"
}
]
}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.4
},
{
"id": "f4bfb978-9066-4746-82f4-46b34daa4d61",
"name": "Format Digest Email",
"type": "n8n-nodes-base.code",
"position": [
2400,
96
],
"parameters": {
"jsCode": "const raw = $json.message?.content || $json.text || \"\";\nconst now = new Date().toISOString().slice(0, 10);\nreturn [{\n json: {\n subject: `Competitor change digest - ${now}`,\n digest_html: raw.replace(/\\n/g, \"<br>\"),\n recipient_email: $(\"Build Digest Prompt\").first().json.recipient_email,\n changed_count: $(\"Build Digest Prompt\").first().json.changed_count,\n total_checked: $(\"Build Digest Prompt\").first().json.total_checked\n }\n}];"
},
"typeVersion": 2
},
{
"id": "1e0f679f-b47f-4446-bbe7-d36e6bc9b815",
"name": "Gmail - Draft Digest",
"type": "n8n-nodes-base.gmail",
"position": [
2656,
96
],
"parameters": {
"message": "={{ .digest_html }}",
"options": {
"sendTo": "={{ .recipient_email }}"
},
"subject": "={{ .subject }}",
"resource": "draft",
"emailType": "html"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "6a3ed7a9-3b32-4225-bedd-c71b3c9a40b5",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
832,
32
],
"parameters": {
"color": 5,
"width": 688,
"height": 256,
"content": "## Fetch competitor "
},
"typeVersion": 1
},
{
"id": "ee25ad0d-0e4b-44d8-88ef-29a86ad7831d",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1568,
0
],
"parameters": {
"color": 5,
"width": 464,
"height": 272,
"content": "## Track the changes and build digest accordingly"
},
"typeVersion": 1
},
{
"id": "4d477952-891e-4513-859d-bf18810e5eac",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
2048,
0
],
"parameters": {
"color": 5,
"width": 800,
"height": 272,
"content": "## Build and send the digest through Email"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "b5dde8e2-42d1-4e70-8967-877eeb8d76cf",
"connections": {
"Weekly Schedule": {
"main": [
[
{
"node": "Define Competitors",
"type": "main",
"index": 0
}
]
]
},
"Define Competitors": {
"main": [
[
{
"node": "HTTP - Fetch Competitor Page",
"type": "main",
"index": 0
}
]
]
},
"Build Digest Prompt": {
"main": [
[
{
"node": "OpenAI - Summarize Competitor Changes",
"type": "main",
"index": 0
}
]
]
},
"Format Digest Email": {
"main": [
[
{
"node": "Gmail - Draft Digest",
"type": "main",
"index": 0
}
]
]
},
"Track Snapshot Changes": {
"main": [
[
{
"node": "Build Digest Prompt",
"type": "main",
"index": 0
}
]
]
},
"HTTP - Fetch Competitor Page": {
"main": [
[
{
"node": "Track Snapshot Changes",
"type": "main",
"index": 0
}
]
]
},
"OpenAI - Summarize Competitor Changes": {
"main": [
[
{
"node": "Format Digest Email",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2openAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
How it works Runs automatically on a weekly schedule and fetches the live HTML of every competitor page you define Strips all HTML tags and captures a clean text snapshot of each page Compares the current snapshot against the previously stored version using workflow static data…
Source: https://n8n.io/workflows/15429/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
A scheduled process aggregates content from eight distinct data sources and standardizes all inputs into a unified format. AI models perform sentiment scoring, detect conspiracy or misinformation sign
This workflow monitors filesystem sync and backup jobs by validating their execution logs, not by running or inspecting the jobs themselves.
Stop wasting billable hours on manual time-tracking. AutoTimesheet Pro uses AI to collect emails, meetings, and GitHub work, then writes a clean timesheet straight into Google Sheets. Perfect for deve
Imagine a dedicated financial expert tirelessly working behind the scenes, sifting through every transaction, every investment move, and every accounting entry. That's exactly what this automated syst
Who is this for? AI creators, marketers, agencies, and researchers tracking YouTube trends who need weekly high-signal insights without 4+ hours manual research.