{
  "id": "jSHygjNuZdSzA83e",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Automated E-commerce Store Monitoring for New Products Using BrowserAct",
  "tags": [],
  "nodes": [
    {
      "id": "4a57ae79-3420-41de-8712-3bfb0638ee44",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -544,
        -128
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ae8004bb-cbc4-463d-bfa1-f4e0025f89a3",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -416,
        -128
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4/edit#gid=0",
          "cachedResultName": "Competitor Store List"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4/edit?usp=drivesdk",
          "cachedResultName": "Shopify New Product Monitor"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "a4c4d616-994b-47f7-a480-d7b25df1678e",
      "name": "Create sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        0,
        -112
      ],
      "parameters": {
        "title": "={{ $json.Name }}",
        "options": {},
        "operation": "create",
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4/edit?usp=drivesdk",
          "cachedResultName": "Shopify New Product Monitor"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "96c17b4b-81fc-4367-a1f5-48f6df2012e8",
      "name": "Send a message",
      "type": "n8n-nodes-base.slack",
      "position": [
        1280,
        -112
      ],
      "parameters": {
        "text": "=New Product Added to {{ $('Loop Over Items').first().json.Name }}\nWebsite Please Check it out\n------------------------------------------------------\n{{ $('Schedule Trigger').first().json['Readable date']}}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09LWT82KHN",
          "cachedResultName": "new_product_added"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "09378204-fcb5-4ab3-bc55-d152ced637ff",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        832,
        -128
      ],
      "parameters": {
        "mode": "chooseBranch",
        "useDataOfInput": 2
      },
      "typeVersion": 3.2
    },
    {
      "id": "e02d1d99-71f7-4f28-b32c-cf87350b6f6c",
      "name": "Sticky Note - Intro",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1104,
        -512
      ],
      "parameters": {
        "width": 544,
        "height": 460,
        "content": "## Try It Out!\n### This template is an advanced competitive intelligence tool that automatically monitors competitor Shopify stores and alerts you the moment they launch a new product.\n\n### How it works\n* The workflow runs on a **schedule** to check for new products automatically.\n* It reads your list of competitor stores from a central **Google Sheet**.\n* It **loops** through each competitor one by one.\n* For each competitor, it creates a dedicated tracking sheet and then uses **BrowserAct** to scrape their current product list.\n* The workflow then compares this *new* product list against the *previous* list stored in the tracking sheet.\n* A **Code** node performs a difference check to see if any new products have been added.\n* If a new product is detected, it sends an instant **Slack** alert to your team.\n\n### Requirements\n* **BrowserAct** API account for web scraping.\n* **BrowserAct** n8n Community Node -> ([n8n Nodes BrowserAct](https://www.npmjs.com/package/n8n-nodes-browseract-workflows))\n* **Google Sheets** credentials for storing data.\n* **Slack** credentials for sending alerts.\n* A BrowserAct template named **\u201cCompetitors Shopify Website New Product Monitor\n\u201d**.\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/UpnCKd7GaU) or Visit Our [Blog](https://www.browseract.com/blog)!\n"
      },
      "typeVersion": 1
    },
    {
      "id": "84f37a3b-9084-42c1-9a7c-10cf3dcbce2f",
      "name": "Sticky Note - How to Use",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1104,
        -32
      ],
      "parameters": {
        "width": 544,
        "height": 212,
        "content": "## How to use\n\n1.  **Set up Credentials:** Add your credentials for **BrowserAct**, **Google Sheets**, and **Slack**.\n2.  **Set up BrowserAct Template:** Ensure you Use the **\u201cCompetitors Shopify Website New Product Monitor\n\u201d** template in your BrowserAct account.\n3.  **Prepare Your Google Sheet:** In the main spreadsheet, create a sheet named `Competitor Store List` with columns for competitor `Name`, `Link`, and `Pagination Type`.\n4.  **Set Slack Channel:** Update the **Channel ID** in the **Slack** node to your desired alerts channel.\n5.  **Activate Workflow:** Activate the workflow to begin scheduled monitoring. The workflow will automatically create and manage the individual tracking sheets for each competitor."
      },
      "typeVersion": 1
    },
    {
      "id": "26e56a85-706b-47cf-8c4f-744ff76ba4ec",
      "name": "Sticky Note - Need Help",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1104,
        192
      ],
      "parameters": {
        "width": 544,
        "height": 152,
        "content": "\n### Need Help?\n* #### [How to Find Your BrowseAct API Key & Workflow ID](https://www.youtube.com/watch?v=pDjoZWEsZlE)\n* #### [How to Connect n8n to Browseract](https://www.youtube.com/watch?v=RoYMdJaRdcQ)\n* #### [How to Use & Customize BrowserAct Templates](https://www.youtube.com/watch?v=CPZHFUASncY)\n* #### [How to Use the BrowserAct N8N Community Node](https://youtu.be/j0Nlba2pRLU)\n* #### [Automatically Track Competitor Products | n8n & Google Sheets Template](https://youtu.be/Gsj6IlyxdY0)"
      },
      "typeVersion": 1
    },
    {
      "id": "4f57eeca-65ca-4d2d-85f9-c3ac2a121caa",
      "name": "Sticky Note - Input & Loop",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -432,
        -368
      ],
      "parameters": {
        "color": 6,
        "width": 368,
        "height": 216,
        "content": "### \ud83d\udccb 1. Setup & Loop\n\n* **Schedule Trigger:** Kicks off the entire process automatically.\n\n* **Google Sheets:** This node fetches your master list of competitor stores to be monitored.\n\n* **Loop Over Items:** This node is essential. It ensures the workflow processes each competitor from your sheet individually and in an organized fashion."
      },
      "typeVersion": 1
    },
    {
      "id": "ba28c483-2847-4942-919b-2fda4f7ca43e",
      "name": "Sticky Note - Scrape & Store",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        -368
      ],
      "parameters": {
        "color": 5,
        "width": 560,
        "height": 208,
        "content": "### \ud83e\udd16 2. Scrape & Store Data\n\nThis section is the data engine for each competitor in the loop.\n\n* **Create sheet:** Creates a dedicated sheet for the competitor if it doesn't exist, keeping your data organized.\n* **BrowserAct Nodes:** These nodes run the scraper to get a fresh list of products from the competitor's live website.\n* **Code Node:** Parses the scraper's output.\n* **Append or update row...:** This node saves the newly scraped product list to the competitor's dedicated sheet, creating a historical record for comparison."
      },
      "typeVersion": 1
    },
    {
      "id": "4eee11df-f0aa-48e3-8b32-0612749612b4",
      "name": "Sticky Note - Compare & Alert",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        816,
        -368
      ],
      "parameters": {
        "color": 3,
        "width": 624,
        "height": 208,
        "content": "### \ud83e\udde0 3. Compare & Alert\n\nThis is the intelligence core of the workflow.\n\n* **Get Row Nodes & Merge:** These nodes fetch both the *newly scraped* product list and the *previously saved* list.\n\n* **Code in JavaScript1:** This is the key logic. It compares the two lists and detects if any product names exist in the new list that weren't in the old one.\n\n* **If & Slack:** If the code finds a new product, the `If` node directs the workflow to send an immediate Slack alert, giving you real-time competitive insight."
      },
      "typeVersion": 1
    },
    {
      "id": "8e99c2b5-ef85-491b-ab56-9888208054f6",
      "name": "Get row(s) for Compare",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        608,
        -256
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1605316777,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4/edit#gid=1605316777",
          "cachedResultName": "hiutdenim - Men"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4/edit?usp=drivesdk",
          "cachedResultName": "Shopify New Product Monitor"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "b520b61b-025e-4c40-9495-f719c5978d87",
      "name": "Compare Datas",
      "type": "n8n-nodes-base.code",
      "position": [
        960,
        -128
      ],
      "parameters": {
        "jsCode": "// The 'items' variable is an array of objects, where each object\n// corresponds to an input item and has a 'json' property containing its data.\n// In the Function node, items[0] will be the first input (e.g., from Google Sheets Get Row 1)\n// and items[1] will be the second input (e.g., from Google Sheets Get Row 2) if you connect two nodes.\n\nconst list1 = $input.all(); // Assuming your first input is a list of maps/items under a 'data' key\nconst list2 = $('Get row(s) for Compare').all(); // Assuming your second input is a list of maps/items under a 'data' key\n\n// ----------------------------------------------------------------------\n// 1. Create a Set of all 'Name' values from the second list for quick lookup\n// ----------------------------------------------------------------------\nconst namesInList2 = new Set(list2.map(item => item.json.Name).filter(name => name != null));\n\n// ----------------------------------------------------------------------\n// 2. Check if ANY name from list1 is missing in list2\n//    The .some() method will stop and return true the moment the condition is met.\n// ----------------------------------------------------------------------\nconst isMissingName = list1.some(item1 => {\n    const nameToCheck = item1.json.Name;\n    \n    // Condition: Is the name NOT null AND is it NOT present in the namesInList2 Set?\n    return nameToCheck != null && !namesInList2.has(nameToCheck);\n});\n\n// ----------------------------------------------------------------------\n// 3. Output a SINGLE item with the Alert status\n// ----------------------------------------------------------------------\nif (isMissingName) {\n    return [{\n        json: {\n            \"Alert\": true,\n            \"Message\": \"One or more names from the first list are missing in the second list.\"\n        }\n    }];\n} else {\n    return [{\n        json: {\n            \"Alert\": false,\n            \"Message\": \"All names from the first list are present in the second list.\"\n        }\n    }];\n}"
      },
      "typeVersion": 2
    },
    {
      "id": "ed459d93-efe4-4b7f-a66c-5a3d8e8cb721",
      "name": "Parse Json",
      "type": "n8n-nodes-base.code",
      "position": [
        336,
        -112
      ],
      "parameters": {
        "jsCode": "// Get the JSON string using the exact path provided by the user.\nconst jsonString = $input.first().json.output.string;\n\nlet parsedData;\n\n// Check if the string exists before attempting to parse\nif (!jsonString) {\n    // Return an empty array or throw an error if no string is found\n    // Throwing an error is usually better to stop the workflow if data is missing.\n    throw new Error(\"Input string is empty or missing at the specified path: $input.first().json.output.string\");\n}\n\ntry {\n    // 1. Parse the JSON string into a JavaScript array of objects\n    parsedData = JSON.parse(jsonString);\n} catch (error) {\n    // Handle JSON parsing errors (e.g., if the string is malformed)\n    throw new Error(`Failed to parse JSON string: ${error.message}`);\n}\n\n// 2. Ensure the parsed data is an array\nif (!Array.isArray(parsedData)) {\n    throw new Error('Parsed data is not an array. It cannot be split into multiple items.');\n}\n\n// 3. Map the array of objects into the n8n item format { json: object }\n// Each element in this array will be treated as a new item by n8n, achieving the split.\nconst outputItems = parsedData.map(item => ({\n    json: item,\n}));\n\n// 4. Return the new array of items\nreturn outputItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "530fc448-8f83-4c49-8c29-60b3bac8eb05",
      "name": "Get workflow Data",
      "type": "n8n-nodes-browseract-workflows.browserAct",
      "position": [
        224,
        -112
      ],
      "parameters": {
        "taskId": "={{ $json.id }}",
        "operation": "getTask",
        "waitForFinish": true
      },
      "credentials": {
        "browserActApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e3833253-d698-4144-8999-a638c6999977",
      "name": "Run a workflow",
      "type": "n8n-nodes-browseract-workflows.browserAct",
      "position": [
        112,
        -112
      ],
      "parameters": {
        "workflowId": "57142458383023994",
        "inputParameters": {
          "parameters": [
            {
              "name": "Competitor_Store_Link",
              "value": "={{ $('Loop Over Items').item.json.Link }}"
            },
            {
              "name": "Pagination_Type",
              "value": "={{ $('Loop Over Items').item.json[\"Pagination Type\"] }}"
            },
            {
              "name": "Total_Product",
              "value": "10"
            }
          ]
        },
        "additionalFields": {}
      },
      "credentials": {
        "browserActApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "127198eb-8387-45e9-b4f1-ce70c01fbb7c",
      "name": "Store Data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        544,
        -112
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Price",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [
            "Name"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1605316777,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4/edit#gid=1605316777",
          "cachedResultName": "hiutdenim - Men"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4/edit?usp=drivesdk",
          "cachedResultName": "Shopify New Product Monitor"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "b637be2d-8c78-4517-a9bc-68fb12eb2019",
      "name": "Get Data For Compare",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        672,
        -112
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1605316777,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4/edit#gid=1605316777",
          "cachedResultName": "hiutdenim - Men"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1A_SG0aNjbRs9Sdc2uowXyNCI0-h3W4uEpPogD_B3ZM4/edit?usp=drivesdk",
          "cachedResultName": "Shopify New Product Monitor"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "db5e7117-f9bf-4cad-8d22-eb2ca4a9e07c",
      "name": "Check New Product",
      "type": "n8n-nodes-base.if",
      "position": [
        1088,
        -128
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "db0940fb-0954-4792-8065-eb7147e8068e",
              "operator": {
                "type": "boolean",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.Alert }}",
              "rightValue": ""
            },
            {
              "id": "03a29ec0-3f86-4d9b-8834-c08b3ddf8953",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Alert }}",
              "rightValue": "=true"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "a7712d64-c968-4131-b6d6-eea600699e86",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -240,
        -128
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "d3e295c7-249c-4c09-bb66-828b1335c23e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -432,
        -144
      ],
      "parameters": {
        "color": 6,
        "width": 368,
        "height": 240,
        "content": ""
      },
      "typeVersion": 1
    },
    {
      "id": "d34cb56d-dabe-4f4e-ae84-605893f7fafb",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        -144
      ],
      "parameters": {
        "color": 5,
        "width": 560,
        "height": 240,
        "content": ""
      },
      "typeVersion": 1
    },
    {
      "id": "17fdf64a-8c47-4661-9a32-43be26c24938",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        528,
        -368
      ],
      "parameters": {
        "color": 5,
        "width": 272,
        "height": 464,
        "content": ""
      },
      "typeVersion": 1
    },
    {
      "id": "9e96b86b-3615-4c14-be2f-555c7ba386de",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        816,
        -144
      ],
      "parameters": {
        "color": 3,
        "width": 624,
        "height": 240,
        "content": ""
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "8b998d65-770d-4218-a6cb-11815c365e72",
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Compare Datas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Json": {
      "main": [
        [
          {
            "node": "Get row(s) for Compare",
            "type": "main",
            "index": 0
          },
          {
            "node": "Store Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store Data": {
      "main": [
        [
          {
            "node": "Get Data For Compare",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create sheet": {
      "main": [
        [
          {
            "node": "Run a workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compare Datas": {
      "main": [
        [
          {
            "node": "Check New Product",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run a workflow": {
      "main": [
        [
          {
            "node": "Get workflow Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send a message": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Create sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check New Product": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get workflow Data": {
      "main": [
        [
          {
            "node": "Parse Json",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Data For Compare": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Get row(s) for Compare": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}