{
  "id": "vZAh4N5GaO0OqHvS",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Automate competitor campaign monitoring using BrowserAct & Openrouter",
  "tags": [],
  "nodes": [
    {
      "id": "2f9d8386-ecbd-46f5-895d-93928a833644",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -48,
        80
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "09dd7f29-b612-491d-aaa7-087ad2d240c9",
      "name": "OpenRouter Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        576,
        320
      ],
      "parameters": {
        "model": "openai/gpt-5",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c95679c3-6d6a-4105-914d-b901459edbc9",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        704,
        304
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": "{\n  \"page_context\":{\n    \"summary\": \"A concise, natural language description of the page's purpose, the product being sold, and any active offer details (e.g., 'A promotional bundle for Huel Black Edition including a free t-shirt').\" \n  },\n\"comparison_analysis\":{ \n  \"has_changes\": true,\n  \"change_severity\": \"None\" ,\n  \"price_change\": { \n    \"detected\": true, \n    \"direction\": \"Increase\", \n    \"difference_amount\": 0.00 \n  }, \"content_changes\": [ \n    \"List specific changes here (e.g., 'Price dropped by 5.00', 'Banner added Free Shipping text', 'Item 2 changed from Shaker to Pot')\" ], \n  \"verdict\": \"Short strategic summary of the shift (e.g., 'Aggressive push on the bundle by lowering price and adding free shipping keywords')\" }\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "c70bf869-dd94-481f-903a-978904d5e2e6",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        720,
        -336
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "39d44b42-2968-44c6-9ece-53d3ca60b8e6",
      "name": "OpenRouter Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        912,
        -128
      ],
      "parameters": {
        "model": "openai/gpt-5",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "39a27beb-95e1-44b0-bebf-f3884528893a",
      "name": "Structured Output Parser1",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1072,
        -128
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": "[\n  {\n    \"slack_text\": \"*\ud83d\udea8 Competitor Intelligence Report*\\nI analyzed 15 pages and found *3 significant changes* today.\\n\\n*Top Strategy Shift:* Aggressive bundling on 'Black Edition' pages.\"\n  },\n  {\n    \"slack_text\": \"*\ud83d\udd34 Update 1: Black Edition Bundle*\\n*Page:* Bundle Landing Page\\n*Change:* Price decreased by $5.00.\\n> *Verdict:* They are undercutting our Q1 offer.\\n*Details:*\\n\u2022 Added 'Free Shipping' banner\\n\u2022 Changed Item 2 to 'T-Shirt'\"\n  },\n  {\n    \"slack_text\": \"*\ud83d\udfe1 Update 2: Vanilla Powder*\\n*Page:* Standard Product\\n*Change:* Minor description update.\\n> *Verdict:* SEO keyword adjustment.\"\n  }\n]"
      },
      "typeVersion": 1.3
    },
    {
      "id": "0c2d517a-bf0a-44f3-991e-c2ded8e67725",
      "name": "Send a message",
      "type": "n8n-nodes-base.slack",
      "position": [
        1424,
        -336
      ],
      "parameters": {
        "text": "={{ $json.slack_text }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09KLV9DJSX",
          "cachedResultName": "all-browseract-workflow-test"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "7013798b-a2ee-471e-a9ac-382641f87c72",
      "name": "Extract the target URLs",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -272,
        80
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/16FHfYfVjGjpTkBdxb3l9bZtfAfwZsL5vGpkNMuy1VB0/edit#gid=0",
          "cachedResultName": "Page URLs"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "16FHfYfVjGjpTkBdxb3l9bZtfAfwZsL5vGpkNMuy1VB0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/16FHfYfVjGjpTkBdxb3l9bZtfAfwZsL5vGpkNMuy1VB0/edit?usp=drivesdk",
          "cachedResultName": "Competitor Campaign Monitoring "
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "df3df30e-53bc-4c12-a365-720ff164714d",
      "name": "Scrape the target pages",
      "type": "n8n-nodes-browseract.browserAct",
      "position": [
        368,
        96
      ],
      "parameters": {
        "type": "WORKFLOW",
        "workflowId": "77068334856978491",
        "workflowConfig": {
          "value": {
            "input-Target_Page": "={{ $json[\"Page URL\"] }}"
          },
          "schema": [
            {
              "id": "input-Target_Page",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "description": "If left blank, the default value defined in BrowserAct will be used.",
              "displayName": "Target_Page",
              "defaultMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "input-Target_Page"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "credentials": {
        "browserActApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "eea04b6a-6f65-4f9f-a2a9-a95ad5d01fea",
      "name": "Analyze the pages",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        592,
        96
      ],
      "parameters": {
        "text": "=Current Data: {{ $json.output.string }},\nPrevious Data:  {{ $('Loop Over Items').item.json[\"Page Context\"] }}",
        "options": {
          "systemMessage": "You are an expert Competitor Intelligence Analyst. Your task is to analyze data from a competitor's website to generate a context summary and compare two datasets (Current Scrape vs. Previous Scrape) to report on strategic changes.\n\nInputs\nCurrent Data: JSON object representing the page as it looks today.\n\nPrevious Data: JSON object representing the page from the last run.\n\nAnalysis Logic\nStep 1: Synthesize Page Context\nAnalyze the campaign_title, banner_description, and the list of items (item_n_name).\n\nInstead of just categorizing the page, write a concise natural language summary of what this page represents.\n\nExample: \"A promotional bundle landing page offering the 'Black Edition' starter kit, which includes two bags of powder and free accessories like a shaker and t-shirt.\"\n\nStep 2: Detect Changes (Comparison)\nCompare every field in \"Current\" against \"Previous\".\n\nPrice Check: Did campaign_price change? Calculate the difference.\n\nComposition Check: Did the specific items in the bundle change? (e.g., flavors, specific accessory types).\n\nMessaging Check: Compare banner_description. Look for added urgency (e.g., \"Limited Time,\" \"Free Shipping\").\n\nOutput Rules\nYou must output ONLY JSON. Do not include markdown fencing (```json) or conversational text.\n\nIf \"Previous Data\" is empty or null, analyze the \"Current Data\" for the context summary, but mark changes as \"New Tracking Started.\"\n\nLanguage: Ensure the page_summary is written in English, even if the source text (e.g., \"Gratis verzending\") is in another language.\n\nOutput Schema\n{ \"page_context\": { \"summary\": \"A concise, natural language description of the page's purpose, the product being sold, and any active offer details (e.g., 'A promotional bundle for Huel Black Edition including a free t-shirt').\" }, \"comparison_analysis\": { \"has_changes\": true/false, \"change_severity\": \"None\" | \"Low\" | \"High\", \"price_change\": { \"detected\": true/false, \"direction\": \"Increase\" | \"Decrease\" | \"Same\", \"difference_amount\": 0.00 }, \"content_changes\": [ \"List specific changes here (e.g., 'Price dropped by 5.00', 'Banner added Free Shipping text', 'Item 2 changed from Shaker to Pot')\" ], \"verdict\": \"Short strategic summary of the shift (e.g., 'Aggressive push on the bundle by lowering price and adding free shipping keywords')\" } }"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3
    },
    {
      "id": "f85824db-47de-4fba-84c7-42dcc7da59ba",
      "name": "Update Database",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1104,
        272
      ],
      "parameters": {
        "columns": {
          "value": {
            "Page URL": "={{ $('Loop Over Items').item.json[\"Page URL\"] }}",
            "row_number": "={{ $('Loop Over Items').item.json.row_number }}",
            "Page Context": "={{ $json.output.page_context }}",
            "Comparison Analysis": "={{ $json.output.comparison_analysis }}"
          },
          "schema": [
            {
              "id": "Page URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Page URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Page Context",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Page Context",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Comparison Analysis",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Comparison Analysis",
              "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": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/16FHfYfVjGjpTkBdxb3l9bZtfAfwZsL5vGpkNMuy1VB0/edit#gid=0",
          "cachedResultName": "Page URLs"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "16FHfYfVjGjpTkBdxb3l9bZtfAfwZsL5vGpkNMuy1VB0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/16FHfYfVjGjpTkBdxb3l9bZtfAfwZsL5vGpkNMuy1VB0/edit?usp=drivesdk",
          "cachedResultName": "Competitor Campaign Monitoring "
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "41b85a08-9ac2-4ffe-9224-65ecc17964f6",
      "name": "Retrieve database items",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        544,
        -336
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/16FHfYfVjGjpTkBdxb3l9bZtfAfwZsL5vGpkNMuy1VB0/edit#gid=0",
          "cachedResultName": "Page URLs"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "16FHfYfVjGjpTkBdxb3l9bZtfAfwZsL5vGpkNMuy1VB0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/16FHfYfVjGjpTkBdxb3l9bZtfAfwZsL5vGpkNMuy1VB0/edit?usp=drivesdk",
          "cachedResultName": "Competitor Campaign Monitoring "
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "typeVersion": 4.7
    },
    {
      "id": "0a079954-a4ce-4b26-a951-215865c72c77",
      "name": "Analyze all the items and generate a report",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        928,
        -336
      ],
      "parameters": {
        "text": "=Input : {{ JSON.stringify($json.data, null, 2) }}",
        "options": {
          "systemMessage": "You are a Senior Competitor Intelligence Reporter. Your goal is to synthesize a dataset of page analyses into a high-value, readable Slack digest.\n\nInputs\nYou will receive a JSON Array containing multiple objects. Each object represents a single page and includes:\n\npage_context (Summary of the page)\n\ncomparison_analysis (Verdict, changes, severity)\n\nProcessing Logic\nStep 1: Filter & Prioritize\nReview all inputs.\n\nIgnore pages where has_changes is false.\n\nPrioritize pages where change_severity is \"High\".\n\nStep 2: Format the Output\nYou must produce a JSON Array of message objects.\n\nMessage 1 (The Header): A summary of the total changes (e.g., \"found 3 high-priority updates\").\n\nSubsequent Messages (The Updates): One object per changed page.\n\nStep 3: Drafting the Content (Slack Style)\nFor each message, use Slack-compatible formatting:\n\nUse *Bold* for headers.\n\nUse > for the verdict or strategic summary.\n\nUse emojis to denote severity (\ud83d\udd34 High, \ud83d\udfe1 Low, \ud83d\udfe2 New).\n\nDo not use Markdown headers (# or ##) or triple backticks (```) inside the content strings.\n\nOutput Rules\nFormat: strictly a JSON Array of Objects.\n\nSchema: [ { \"slack_text\": \"string\" }, { \"slack_text\": \"string\" } ]\n\nConstraint: Ensure the text in each object is concise enough to be read easily in Slack (under 2000 chars)."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3
    },
    {
      "id": "4b71067b-112a-411c-8774-5625ba1a26a1",
      "name": "Split out Slack messages",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1232,
        -336
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "output"
      },
      "typeVersion": 1
    },
    {
      "id": "1c9a91db-488a-4225-8e6c-c3b6c860ddcb",
      "name": "Documentation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -960,
        -496
      ],
      "parameters": {
        "width": 380,
        "height": 504,
        "content": "## \u26a1 Competitor Campaign Monitoring\n\n**Summary:** This automation performs weekly surveillance on competitor landing pages, comparing current offers against historical data to detect strategy shifts (prices, bundles, copy) and reporting findings to Slack.\n\n### Requirements\n* **Credentials:** BrowserAct, OpenRouter (GPT-4/5), Google Sheets, Slack.\n* **Mandatory:** BrowserAct API (Template: **Competitor Campaign Monitoring (Huel)**)\n\n### How to Use\n1.  **Credentials:** Set up API keys for all services.\n2.  **BrowserAct Template:** Ensure the **Competitor Campaign Monitoring (Huel)** template is saved in your BrowserAct account.\n3.  **Google Sheet:** Prepare a sheet with columns for `Page URL` and historical data storage.\n4.  **Slack:** Configure the channel ID for the final report.\n\n### Need Help?\n[How to Find Your BrowserAct API Key & Workflow ID](https://docs.browseract.com)\n[How to Connect n8n to BrowserAct](https://docs.browseract.com)\n[How to Use & Customize BrowserAct Templates](https://docs.browseract.com)"
      },
      "typeVersion": 1
    },
    {
      "id": "44f8a0f7-c6a4-49e0-9e9d-ecdf3cfdf238",
      "name": "Step 1 Explanation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 584,
        "height": 124,
        "content": "### \u23f0 Step 1: Scheduling & Targets\n\nThe workflow triggers automatically on a weekly schedule. It retrieves a list of target competitor URLs from a Google Sheet to begin the monitoring cycle."
      },
      "typeVersion": 1
    },
    {
      "id": "384208bc-2606-4d6a-8f35-2f19975d74f5",
      "name": "Step 2 Explanation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        480
      ],
      "parameters": {
        "color": 7,
        "width": 1024,
        "height": 128,
        "content": "### \ud83d\udd75\ufe0f Step 2: Comparative Analysis\n\nBrowserAct scrapes the live page data. An AI agent then compares this fresh data against the *previous* week's record (fetched from the database) to identify specific changes in pricing, bundle composition, or marketing hooks. the system updates the Google Sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "43068521-6439-4717-b556-05851d24d758",
      "name": "Step 4 Explanation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        -480
      ],
      "parameters": {
        "color": 7,
        "width": 1036,
        "height": 124,
        "content": "### \ud83d\udce2 Step 4: Executive Digest\n\nOnce all pages are processed, a final AI agent aggregates the findings into a high-level intelligence report. It filters for significant changes and posts a formatted summary to Slack."
      },
      "typeVersion": 1
    },
    {
      "id": "d64a41dc-0137-4bfa-b55b-bbc9a72689a7",
      "name": "Weekly Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -496,
        80
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks"
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "58efbe2c-3a86-42eb-965e-a36d88e30e0d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        -496
      ],
      "parameters": {
        "color": 6,
        "width": 592,
        "height": 352,
        "content": "@[youtube](roIRCG3DryU)"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "16770c21-d47c-4e01-80ae-56c4f7cc5f38",
  "connections": {
    "Aggregate": {
      "main": [
        [
          {
            "node": "Analyze all the items and generate a report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekly Trigger": {
      "main": [
        [
          {
            "node": "Extract the target URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Retrieve database items",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Scrape the target pages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Database": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze the pages": {
      "main": [
        [
          {
            "node": "Update Database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze the pages",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Structured Output Parser",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze all the items and generate a report",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Structured Output Parser1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Extract the target URLs": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve database items": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape the target pages": {
      "main": [
        [
          {
            "node": "Analyze the pages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split out Slack messages": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Analyze the pages",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser1": {
      "ai_outputParser": [
        [
          {
            "node": "Analyze all the items and generate a report",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Analyze all the items and generate a report": {
      "main": [
        [
          {
            "node": "Split out Slack messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}