AutomationFlowsData & Sheets › Audit Inventory Prices Between a Website Scraper and Google Sheets

Audit Inventory Prices Between a Website Scraper and Google Sheets

ByYogyata Mantri @yogyatamantri on n8n.io

This workflow receives scraped product data via a webhook, compares it against an internal inventory list in Google Sheets, and writes an audit log (price changes, matches, and missing items) to a separate Google Sheets spreadsheet. Receives a POST webhook request containing a…

Webhook trigger★★★★☆ complexity11 nodesGoogle Sheets
Data & Sheets Trigger: Webhook Nodes: 11 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #17176 — we link there as the canonical source.

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 →

Download .json
{
  "id": "8jMYxvoRFVkAtLf9",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AUTOMATED INVENTORY AUDIT & INTEGRATION ENGINE",
  "tags": [],
  "nodes": [
    {
      "id": "29068fef-f29a-4ca1-8c8a-1ddaecb21405",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        208,
        -128
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1DNvDp6HXQeulSNx7B7r4kpIYxCTChfpBXfbJizbghbg/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1DNvDp6HXQeulSNx7B7r4kpIYxCTChfpBXfbJizbghbg",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1DNvDp6HXQeulSNx7B7r4kpIYxCTChfpBXfbJizbghbg/edit?usp=drivesdk",
          "cachedResultName": "Tuffix scraper sheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "73ca1366-40ad-400d-8b43-187dd89f3599",
      "name": "Scraper",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -640,
        -144
      ],
      "parameters": {
        "path": "b6ff236a-8807-441d-bb07-37d63258efb1",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "b2d0a076-5b3d-4645-a1b4-9f04ea781453",
      "name": "Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        656,
        32
      ],
      "parameters": {
        "jsCode": "// Safely fetch config from 'Edit Fields' node or use defaults\nlet varianceThreshold = 0.05;\ntry {\n  varianceThreshold = $('Edit Fields').first().json.variance_threshold || 0.05;\n} catch (e) {\n  varianceThreshold = 0.05;\n}\n\n// All incoming items loop\nfor (const item of $input.all()) {\n  const webSku = item.json.sku || item.json.web_sku || item.json.product_id || \"N/A\";\n  const scrapedPrice = parseFloat(item.json.scraped_price || item.json.price || 0);\n  const baselinePrice = parseFloat(item.json.baseline_price || item.json.expected_price || 0);\n\n  let priceDiff = scrapedPrice - baselinePrice;\n  let variancePercent = 0;\n  if (baselinePrice > 0) {\n    variancePercent = (priceDiff / baselinePrice) * 100;\n  }\n\n  let status = \"Matched\";\n  if (baselinePrice === 0) {\n    status = \"Not Found on Master List\";\n  } else if (Math.abs(variancePercent) > (varianceThreshold * 100)) {\n    status = `Price Variance (${variancePercent.toFixed(2)}%)`;\n  }\n\n  item.json.audit_sku = webSku;\n  item.json.audit_scraped_price = scrapedPrice;\n  item.json.audit_baseline_price = baselinePrice;\n  item.json.audit_variance = priceDiff;\n  item.json.audit_status = status;\n}\n\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "80031b43-558c-4d5e-870a-bb51f9566959",
      "name": "Append row in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1184,
        -144
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "sku",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "sku",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "product_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "product_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "sheet_price",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "sheet_price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "scraped_price",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "scraped_price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "match_found_via",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "match_found_via",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "difference",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "difference",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "category",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "image_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "image_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SKU",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "SKU",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Product Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Product Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Current Price",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Current Price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Category",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Image URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Image URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "audit_sku",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "audit_sku",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "audit_scraped_price",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "audit_scraped_price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "audit_baseline_price",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "audit_baseline_price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "audit_variance",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "audit_variance",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "audit_status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "audit_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1-dwW69mppy4Nh07VHHu_pvmqWM--OM889KFcnkpZ6rI/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1-dwW69mppy4Nh07VHHu_pvmqWM--OM889KFcnkpZ6rI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1-dwW69mppy4Nh07VHHu_pvmqWM--OM889KFcnkpZ6rI/edit?usp=drivesdk",
          "cachedResultName": "Scraper Output"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "0e77f587-0b29-4bfe-8ea0-0f4b26f99488",
      "name": "Config. Data",
      "type": "n8n-nodes-base.set",
      "position": [
        -208,
        64
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "{\n  \"target_url\": \"https://example-store.com\",\n  \"sku_column\": \"SKU\",\n  \"expected_price_column\": \"Base_Price\",\n  \"variance_threshold\": 0.05\n}",
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "185638a7-3a3b-4f55-8b94-a7f14f2eef34",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1552,
        -848
      ],
      "parameters": {
        "color": "#E4DCF1",
        "width": 704,
        "height": 1136,
        "content": "# \ud83d\ude80 AUTOMATED INVENTORY & PRICE AUDIT ENGINE\n\n### \ud83d\udccc Overview\nAn enterprise-grade, domain-agnostic automation pipeline designed to continuously ingest scraped e-commerce catalog data, perform automated price variance and stock availability audits against a master database, and output clean status logs.\n\n---\n### \ud83d\udee0\ufe0f Prerequisites & Requirements\n1. **Automation Platform:** n8n (Cloud or Self-Hosted instance).\n2. **Scraper Engine:** Any HTTP POST client / script sending JSON payload (e.g., Node.js scraper, Antigravity, Puppeteer, or cURL).\n3. **Database:** Google Sheets API credentials connected to n8n with:\n   - **Master Sheet:** Reference inventory with expected baseline prices.\n   - **Output Sheet:** Destination tab for real-time audit logging.\n\n---\n### \u2699\ufe0f How To Set Up\n1. **Configure Webhook:** Copy the Webhook production URL from the `Scraper` node into your external scraping script.\n2. **Link Spreadsheet:** Authenticate Google Sheets in the `Get row(s)` and `Append row` nodes, selecting your Master and Output sheet IDs.\n3. **Set Threshold:** Adjust the `variance_threshold` inside the `Edit Fields` node (e.g., `0.05` for a 5% allowable price tolerance).\n4. **Deploy:** Save and set the workflow status to **Active / Published**.\n\n---\n### \ud83d\udd04 How It Works (Execution Flow)\n1. **Data Ingestion:** The `Scraper` node receives a live POST payload containing scraped product SKUs and live prices.\n2. **Parameter Injection:** The `Edit Fields` node injects central configuration values dynamically.\n3. **Master Reference Fetch:** `Get row(s) in sheet` retrieves baseline SKU listings and benchmark pricing.\n4. **Audit Logic Execution:** The `Code in JavaScript` engine normalizes field names, calculates variance percentages, and assigns status tags (`Matched`, `Price Variance`, or `Not Found`).\n5. **Report Generation:** `Append row in sheet` logs the final audited records with status tags directly into Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "9f9038af-b413-446e-a506-9694e9493318",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -784,
        -576
      ],
      "parameters": {
        "color": "#DAEBFA",
        "width": 384,
        "height": 528,
        "content": "### \ud83d\udce5 NODE 1: Scraper (Webhook Trigger)\n\n**Role:**\nServes as the entry point for incoming e-commerce product data.\n\n**Key Functions:**\n* Listens for incoming HTTP `POST` requests.\n* Accepts raw JSON payloads containing scraped items (SKUs, live prices, product names).\n* Passes the live data downstream to start the execution pipeline.\n\n**Inputs & Details:**\n* **Type:** Webhook (Production / Test)\n* **HTTP Method:** POST"
      },
      "typeVersion": 1
    },
    {
      "id": "fabfbc13-dba7-4f57-94ee-8457f7ccbaa2",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        64,
        -624
      ],
      "parameters": {
        "color": "#FEF3C7",
        "width": 416,
        "height": 592,
        "content": "### \ud83d\udcd6 NODE 3: Get row(s) in sheet (Master Reference)\n\n**Role:**\nFetches baseline product records from the central inventory database.\n\n**Key Functions:**\n* Connects to the Master Google Sheet using official credentials.\n* Retrieves expected baseline pricing and master catalog SKUs.\n* Provides the reference dataset needed for price variance comparison.\n\n**Inputs & Details:**\n* **Type:** Google Sheets Node\n* **Operation:** Read / Get Rows"
      },
      "typeVersion": 1
    },
    {
      "id": "e8735019-b788-4eb5-b83f-f9f29b980f52",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        -416
      ],
      "parameters": {
        "color": "#F3E8D7",
        "width": 400,
        "height": 576,
        "content": "### \u2699\ufe0f NODE 2: Edit Fields (Config Dashboard)\n\n**Role:**\nActs as the dynamic settings layer for the workflow without modifying underlying code.\n\n**Key Functions:**\n* Injects central configuration parameters into the data stream.\n* Defines `variance_threshold` (e.g., `0.05` for a 5% allowable price tolerance).\n* Maintains domain-agnostic reusability across different store configurations.\n\n**Inputs & Details:**\n* **Type:** Set / Edit Fields Node\n* **Key Config:** `variance_threshold = 0.05`"
      },
      "typeVersion": 1
    },
    {
      "id": "7c9ba247-9a39-4d2e-a3ef-252430b919c2",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        496,
        -528
      ],
      "parameters": {
        "color": "#FFEDD5",
        "width": 464,
        "height": 656,
        "content": "### \u26a1 NODE 4: Code in JavaScript (Audit Engine)\n\n**Role:**\nExecutes the core business logic and variance calculations dynamically across incoming items.\n\n**Key Functions:**\n* **Property Normalization:** Handles dynamic key names across various scraping formats (`sku`, `web_sku`, `scraped_price`).\n* **Variance Calculation:** Calculates absolute difference and percentage variance against baseline prices.\n* **Status Tagging:** Assigns automated audit statuses:\n  - `Matched`\n  - `Price Variance (X%)`\n  - `Not Found on Master List`\n\n**Inputs & Details:**\n* **Type:** Code Node (JavaScript / All Items Loop)\n* **Error Handling:** Fallback thresholds and null checks included."
      },
      "typeVersion": 1
    },
    {
      "id": "4294daea-0dd1-4b2d-b10c-f4238989f7e4",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        992,
        -656
      ],
      "parameters": {
        "color": "#DCFCE7",
        "width": 432,
        "height": 608,
        "content": "### \ud83d\udcca NODE 5: Append row in sheet (Report Output)\n\n**Role:**\nGenerates real-time audit logs and stores processed data into the destination spreadsheet.\n\n**Key Functions:**\n* Maps audited outputs (`audit_sku`, `audit_scraped_price`, `audit_variance`, `audit_status`).\n* Appends new rows into the Output Google Sheet for reporting and tracking.\n* Completes the execution pipeline with clean, audit-ready data.\n\n**Inputs & Details:**\n* **Type:** Google Sheets Node\n* **Operation:** Append Row / Write Logs"
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "3d0c013c-3f5c-41cb-9954-2c2beeb6178f",
  "nodeGroups": [],
  "connections": {
    "Scraper": {
      "main": [
        [
          {
            "node": "Config. Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config. Data": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Append row in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow receives scraped product data via a webhook, compares it against an internal inventory list in Google Sheets, and writes an audit log (price changes, matches, and missing items) to a separate Google Sheets spreadsheet. Receives a POST webhook request containing a…

Source: https://n8n.io/workflows/17176/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

Resume Screening & Behavioral Interviews with Gemini, Elevenlabs, & Notion ATS copy. Uses googleDrive, httpRequest, notion, formTrigger. Webhook trigger; 67 nodes.

Google Drive, HTTP Request, Notion +3
Data & Sheets

[SANTOBET] FLUXO TODO - BACKUP. Uses googleSheets, httpRequest, googleSheetsTrigger. Webhook trigger; 57 nodes.

Google Sheets, HTTP Request, Google Sheets Trigger
Data & Sheets

This workflow sends post-purchase review request emails for WooCommerce orders, stores expiring form links in Google Sheets, optionally shortens links with Dub.co and delays delivery, serves a hosted

HTTP Request, Google Sheets, Email Send
Data & Sheets

FLUXO DISPARO DATA E HORA. Uses itemLists, googleSheets, httpRequest. Webhook trigger; 48 nodes.

Item Lists, Google Sheets, HTTP Request
Data & Sheets

This workflow allows you to accept online payments via YooKassa and log both orders and transactions in Google Sheets — all without writing a single line of code. It supports full payment flow: produc

Google Sheets, HTTP Request