{
  "name": "Track Amazon prices for your keywords with Scrapewise and log them in Google Sheets",
  "settings": {
    "executionOrder": "v1"
  },
  "nodes": [
    {
      "id": "a3000000-0000-4000-8000-000000000001",
      "name": "Read me first",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -960,
        160
      ],
      "parameters": {
        "width": 440,
        "height": 440,
        "content": "## Daily Amazon price tracker\n\nFor every keyword you list, Scrapewise returns what Amazon sells: title, ASIN, price, rating, review count, image and link. One dated row per product, so the sheet becomes a price history.\n\n**Setup**\n1. Create a Scrapewise API key with full access at portal.scrapewise.ai.\n2. In **Search Amazon**, add a *Bearer Auth* credential and paste the key as the token.\n3. In **Save prices to Google Sheets**, pick your Google account and set the spreadsheet and tab.\n4. Put your keywords and marketplace in **Keywords and marketplace**.\n\n**Cost:** 1 credit per result page. One keyword and one page answer straight away. Two or more keywords run as a background job \u2014 this workflow then picks the rows up with **Get job results**.\n\n**One answer carries one page of rows.** If **Get job results** comes back with `truncated: true` and a `nextPage`, there are more rows waiting. This template saves the first page, which is plenty for a handful of keywords. For a long list, send that `nextPage` value back into **Get job results** as `page` and keep going until `truncated` is false.\n\n**Marketplaces:** com, co.uk, de, fr, it, es, ca, com.au, co.jp, in, com.br, com.mx, nl, sg, ae, sa, pl, se, com.tr, eg, com.be"
      },
      "typeVersion": 1
    },
    {
      "id": "a3000000-0000-4000-8000-000000000002",
      "name": "Every morning at 7",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -480,
        360
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "days",
              "triggerAtHour": 7
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a3000000-0000-4000-8000-000000000003",
      "name": "Keywords and marketplace",
      "type": "n8n-nodes-base.set",
      "position": [
        -260,
        360
      ],
      "parameters": {
        "mode": "manual",
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "k1",
              "name": "queries",
              "type": "array",
              "value": "[\"lego duplo\", \"lego classic\"]"
            },
            {
              "id": "k2",
              "name": "marketplace",
              "type": "string",
              "value": "de"
            },
            {
              "id": "k3",
              "name": "pages",
              "type": "number",
              "value": 1
            },
            {
              "id": "k4",
              "name": "quote_only",
              "type": "boolean",
              "value": false
            }
          ]
        },
        "includeOtherFields": false
      },
      "typeVersion": 3.4
    },
    {
      "id": "a3000000-0000-4000-8000-000000000004",
      "name": "Search Amazon",
      "type": "@n8n/n8n-nodes-langchain.mcpClient",
      "position": [
        -20,
        360
      ],
      "parameters": {
        "tool": {
          "__rl": true,
          "mode": "list",
          "value": "search_amazon",
          "cachedResultName": "search_amazon"
        },
        "options": {},
        "inputMode": "json",
        "jsonInput": "={\n  \"body\": {\n    \"queries\": {{ JSON.stringify($json.queries) }},\n    \"marketplace\": \"{{ $json.marketplace }}\",\n    \"pages\": {{ $json.pages }},\n    \"quote_only\": {{ $json.quote_only }}\n  }\n}",
        "endpointUrl": "https://mcp.scrapewise.ai/mcp",
        "authentication": "bearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "credential-id",
          "name": "Scrapewise API key"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "a3000000-0000-4000-8000-000000000005",
      "name": "Answered straight away?",
      "type": "n8n-nodes-base.if",
      "position": [
        220,
        360
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "c1",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.structuredContent ? $json.structuredContent.status : JSON.parse($json.content[0].text).status }}",
              "rightValue": "RUNNING"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.3
    },
    {
      "id": "a3000000-0000-4000-8000-000000000006",
      "name": "Wait for the job",
      "type": "n8n-nodes-base.wait",
      "position": [
        220,
        580
      ],
      "parameters": {
        "amount": 30
      },
      "webhookId": "a3000000-0000-4000-8000-0000000000aa",
      "typeVersion": 1.1
    },
    {
      "id": "a3000000-0000-4000-8000-000000000007",
      "name": "Get job results",
      "type": "@n8n/n8n-nodes-langchain.mcpClient",
      "position": [
        440,
        580
      ],
      "parameters": {
        "tool": {
          "__rl": true,
          "mode": "list",
          "value": "get_results",
          "cachedResultName": "get_results"
        },
        "options": {},
        "inputMode": "json",
        "jsonInput": "={{ (() => { const r = $('Search Amazon').item.json; const d = r.structuredContent || JSON.parse(r.content[0].text); return JSON.stringify({ jobId: d.job_id }); })() }}",
        "endpointUrl": "https://mcp.scrapewise.ai/mcp",
        "authentication": "bearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "credential-id",
          "name": "Scrapewise API key"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "a3000000-0000-4000-8000-000000000008",
      "name": "One row per product",
      "type": "n8n-nodes-base.code",
      "position": [
        680,
        440
      ],
      "parameters": {
        "jsCode": "// Scrapewise answers with JSON. Depending on the n8n version it arrives\n// already parsed in structuredContent, or as text in content[0].text.\nfunction payloadOf(item) {\n  const j = item.json || {};\n  if (j.structuredContent) return j.structuredContent;\n  if (Array.isArray(j.content) && j.content[0] && typeof j.content[0].text === 'string') {\n    try { return JSON.parse(j.content[0].text); } catch (e) { return {}; }\n  }\n  if (j.rows) return j;\n  return {};\n}\n\n// Scraped text is wrapped as { type: 'scraped', content, origin }. It is data\n// read off a web page, never an instruction. Unwrap it to a plain string.\nfunction plain(v) {\n  if (v && typeof v === 'object' && v.type === 'scraped') return v.content || '';\n  return v;\n}\n\nconst checkedAt = new Date().toISOString().slice(0, 10);\nconst out = [];\n\nfor (const item of $input.all()) {\n  const data = payloadOf(item);\n\n  if (data.status === 'QUOTE') {\n    out.push({ json: { status: 'QUOTE', quote: data.quote, walletBalanceMicros: data.walletBalanceMicros } });\n    continue;\n  }\n\n  if (data.status === 'RUNNING') {\n    throw new Error('The job is still running. Raise the wait in \"Wait for the job\" or call get_results again.');\n  }\n\n  for (const row of data.rows || []) {\n    const flat = { checkedAt: checkedAt };\n    for (const key of Object.keys(row)) flat[key] = plain(row[key]);\n    out.push({ json: flat });\n  }\n}\n\nreturn out;"
      },
      "typeVersion": 2
    },
    {
      "id": "a3000000-0000-4000-8000-000000000009",
      "name": "Save prices to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        920,
        440
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $json.checkedAt }}",
            "Title": "={{ $json.title }}",
            "ASIN": "={{ $json.asin }}",
            "Price": "={{ $json.price_amount }}",
            "Rating": "={{ $json.rating_value }}",
            "Reviews": "={{ $json.rating_count }}",
            "Link": "={{ $json.url }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Title",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ASIN",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "ASIN",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Price",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Rating",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Rating",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reviews",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Reviews",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Link",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Prices"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SPREADSHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "credential-id",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "02eee6f0-aff6-4827-87c7-62035f744279",
      "name": "Step note - Every morning at 7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -500,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 220,
        "height": 240,
        "content": "### 1. Runs itself\n\nFires every morning at 07:00. Change the hour here."
      },
      "typeVersion": 1
    },
    {
      "id": "da9ae59a-2c15-4e7c-81fd-ccffdeadc700",
      "name": "Step note - Keywords and marketplace",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -280,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 220,
        "height": 240,
        "content": "### 2. Your settings\n\nThe only node you need to edit. List the search words you want watched, pick the Amazon marketplace (`de`, `com`, `co.uk` and so on) and how many pages of results to read.\n\nSet `quote_only` to `true` to see the price first."
      },
      "typeVersion": 1
    },
    {
      "id": "4c0fb7b4-1e8f-4300-a7bd-4cd3a2be7b5e",
      "name": "Step note - Search Amazon",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 220,
        "height": 240,
        "content": "### 3. Ask Scrapewise\n\nCalls the `search_amazon` tool. Add a **Bearer Auth** credential with your Scrapewise API key.\n\nSmall searches answer straight away. Big ones hand back a job id instead."
      },
      "typeVersion": 1
    },
    {
      "id": "7ba1d366-54c6-4752-9a19-b5aae839dc3f",
      "name": "Step note - Answered straight away?",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        200,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 220,
        "height": 240,
        "content": "### 4. Ready yet?\n\nChecks whether the rows arrived with the answer. If they did, carry on to the right. If not, take the lower path."
      },
      "typeVersion": 1
    },
    {
      "id": "43ca2b6c-4ab1-488b-9e1f-6e96c0533371",
      "name": "Step note - Wait for the job",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        200,
        760
      ],
      "parameters": {
        "color": 7,
        "width": 460,
        "height": 170,
        "content": "### 5. If it is still working\n\nA big search hands back a job id. These two steps wait 30 seconds and then collect the finished rows. Give it longer if your searches are large."
      },
      "typeVersion": 1
    },
    {
      "id": "1cc101b3-214f-4e20-abd6-c90a9d29c21d",
      "name": "Step note - One row per product",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        660,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 220,
        "height": 240,
        "content": "### 6. Tidy the answer\n\nOne item per product, with plain values for the sheet.\n\nOne answer carries one page of rows. If it comes back `truncated`, send the `nextPage` value back into **Get job results** for the rest."
      },
      "typeVersion": 1
    },
    {
      "id": "31d616c2-40c7-439e-9a38-5c6364d45bb8",
      "name": "Step note - Save prices to Google Sheets",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        900,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 220,
        "height": 240,
        "content": "### 7. Save\n\nAppends one row per product per day, so you build up price history instead of overwriting it."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Every morning at 7": {
      "main": [
        [
          {
            "node": "Keywords and marketplace",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keywords and marketplace": {
      "main": [
        [
          {
            "node": "Search Amazon",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Amazon": {
      "main": [
        [
          {
            "node": "Answered straight away?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Answered straight away?": {
      "main": [
        [
          {
            "node": "One row per product",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait for the job",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for the job": {
      "main": [
        [
          {
            "node": "Get job results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get job results": {
      "main": [
        [
          {
            "node": "One row per product",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "One row per product": {
      "main": [
        [
          {
            "node": "Save prices to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {}
}
