AutomationFlowsData & Sheets › Multi-Platform Price Monitor & Dynamic Pricing

Multi-Platform Price Monitor & Dynamic Pricing

Multi-Platform Price Monitor & Dynamic Pricing. Uses httpRequest, postgres. Scheduled trigger; 13 nodes.

Cron / scheduled trigger★★★★☆ complexity13 nodesHTTP RequestPostgres
Data & Sheets Trigger: Cron / scheduled Nodes: 13 Complexity: ★★★★☆ Added:
Multi-Platform Price Monitor & Dynamic Pricing — n8n workflow card showing HTTP Request, Postgres integration

This workflow follows the HTTP Request → Postgres 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 →

Download .json
{
  "name": "Multi-Platform Price Monitor & Dynamic Pricing",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 15
            }
          ]
        }
      },
      "id": "cron-trigger",
      "name": "Scheduled Price Check",
      "type": "n8n-nodes-base.cron",
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $vars.SHOPIFY_STORE_URL }}/admin/api/2023-10/products.json",
        "authentication": "headerAuth",
        "headerAuth": {
          "name": "X-Shopify-Access-Token",
          "value": "={{ $vars.SHOPIFY_ACCESS_TOKEN }}"
        },
        "options": {
          "queryParameters": {
            "parameters": [
              {
                "name": "limit",
                "value": "50"
              },
              {
                "name": "fields",
                "value": "id,title,variants,vendor,product_type,tags"
              }
            ]
          }
        }
      },
      "id": "shopify-products",
      "name": "Get Shopify Products",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        460,
        300
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "product-data",
              "name": "product_id",
              "value": "={{ $json.id }}",
              "type": "string"
            },
            {
              "id": "product-title",
              "name": "title",
              "value": "={{ $json.title }}",
              "type": "string"
            },
            {
              "id": "current-price",
              "name": "current_price",
              "value": "={{ $json.variants[0].price }}",
              "type": "number"
            },
            {
              "id": "sku",
              "name": "sku",
              "value": "={{ $json.variants[0].sku }}",
              "type": "string"
            },
            {
              "id": "inventory",
              "name": "inventory_quantity",
              "value": "={{ $json.variants[0].inventory_quantity }}",
              "type": "number"
            }
          ]
        },
        "options": {}
      },
      "id": "extract-product-data",
      "name": "Extract Product Data",
      "type": "n8n-nodes-base.set",
      "position": [
        680,
        300
      ]
    },
    {
      "parameters": {
        "url": "https://api.amazon.com/products/search",
        "authentication": "headerAuth",
        "headerAuth": {
          "name": "Authorization",
          "value": "Bearer {{ $vars.AMAZON_ACCESS_TOKEN }}"
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "query",
              "value": "={{ $json.title }}"
            },
            {
              "name": "category",
              "value": "all"
            }
          ]
        }
      },
      "id": "amazon-price-check",
      "name": "Check Amazon Prices",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        900,
        200
      ]
    },
    {
      "parameters": {
        "url": "https://api.ebay.com/buy/browse/v1/item_summary/search",
        "authentication": "headerAuth",
        "headerAuth": {
          "name": "Authorization",
          "value": "Bearer {{ $vars.EBAY_ACCESS_TOKEN }}"
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "={{ $json.title }}"
            },
            {
              "name": "limit",
              "value": "10"
            }
          ]
        }
      },
      "id": "ebay-price-check",
      "name": "Check eBay Prices",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        900,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "// Price analysis and optimization logic\nconst productData = $input.first().json;\nconst amazonPrices = $('Check Amazon Prices').first().json.products || [];\nconst ebayPrices = $('Check eBay Prices').first().json.itemSummaries || [];\n\n// Extract competitor prices\nconst competitorPrices = [\n  ...amazonPrices.map(p => parseFloat(p.price?.value || 0)),\n  ...ebayPrices.map(p => parseFloat(p.price?.value || 0))\n].filter(price => price > 0);\n\n// Calculate market statistics\nconst marketStats = {\n  min: Math.min(...competitorPrices),\n  max: Math.max(...competitorPrices),\n  avg: competitorPrices.reduce((a, b) => a + b, 0) / competitorPrices.length,\n  median: competitorPrices.sort()[Math.floor(competitorPrices.length / 2)]\n};\n\n// Current product price\nconst currentPrice = parseFloat(productData.current_price);\nconst inventoryLevel = productData.inventory_quantity;\n\n// Dynamic pricing rules\nlet recommendedPrice = currentPrice;\nlet priceAction = 'no_change';\nlet reason = 'Price is optimal';\n\n// Rule 1: Competitive pricing\nif (marketStats.min > 0 && currentPrice > marketStats.avg * 1.15) {\n  recommendedPrice = Math.max(marketStats.avg * 1.05, currentPrice * 0.9);\n  priceAction = 'decrease';\n  reason = 'Price too high compared to market average';\n}\n\n// Rule 2: Inventory-based pricing\nif (inventoryLevel < 10) {\n  recommendedPrice = Math.max(recommendedPrice, currentPrice * 1.1);\n  priceAction = 'increase';\n  reason = 'Low inventory - premium pricing';\n} else if (inventoryLevel > 100) {\n  recommendedPrice = Math.min(recommendedPrice, currentPrice * 0.95);\n  priceAction = 'decrease';\n  reason = 'High inventory - clearance pricing';\n}\n\n// Rule 3: Margin protection (assume 30% cost ratio)\nconst minPrice = currentPrice * 0.7 / 0.7; // Maintain minimum margin\nrecommendedPrice = Math.max(recommendedPrice, minPrice);\n\n// Price change threshold (minimum 2% change)\nconst priceChangePercent = Math.abs(recommendedPrice - currentPrice) / currentPrice;\nif (priceChangePercent < 0.02) {\n  recommendedPrice = currentPrice;\n  priceAction = 'no_change';\n  reason = 'Price change too small to implement';\n}\n\nreturn {\n  json: {\n    product_id: productData.product_id,\n    title: productData.title,\n    sku: productData.sku,\n    current_price: currentPrice,\n    recommended_price: Math.round(recommendedPrice * 100) / 100,\n    price_action: priceAction,\n    reason: reason,\n    inventory_level: inventoryLevel,\n    market_stats: marketStats,\n    competitor_count: competitorPrices.length,\n    price_change_percent: Math.round(priceChangePercent * 10000) / 100,\n    analysis_timestamp: new Date().toISOString()\n  }\n};"
      },
      "id": "price-analysis",
      "name": "Price Analysis Engine",
      "type": "n8n-nodes-base.code",
      "position": [
        1120,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "price-change-needed",
              "leftValue": "={{ $json.price_action }}",
              "rightValue": "no_change",
              "operator": {
                "type": "string",
                "operation": "notEqual"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "price-update-check",
      "name": "Should Update Price?",
      "type": "n8n-nodes-base.if",
      "position": [
        1340,
        300
      ]
    },
    {
      "parameters": {
        "method": "PUT",
        "url": "={{ $vars.SHOPIFY_STORE_URL }}/admin/api/2023-10/variants/{{ $json.variant_id }}.json",
        "authentication": "headerAuth",
        "headerAuth": {
          "name": "X-Shopify-Access-Token",
          "value": "={{ $vars.SHOPIFY_ACCESS_TOKEN }}"
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "variant.price",
              "value": "={{ $json.recommended_price }}"
            }
          ]
        }
      },
      "id": "update-shopify-price",
      "name": "Update Shopify Price",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1560,
        200
      ]
    },
    {
      "parameters": {
        "operation": "create",
        "table": "price_history",
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "product_id": "={{ $json.product_id }}",
            "sku": "={{ $json.sku }}",
            "old_price": "={{ $json.current_price }}",
            "new_price": "={{ $json.recommended_price }}",
            "price_action": "={{ $json.price_action }}",
            "reason": "={{ $json.reason }}",
            "competitor_count": "={{ $json.competitor_count }}",
            "market_avg": "={{ $json.market_stats.avg }}",
            "inventory_level": "={{ $json.inventory_level }}",
            "timestamp": "={{ $json.analysis_timestamp }}"
          }
        },
        "options": {}
      },
      "id": "log-price-change",
      "name": "Log Price Change",
      "type": "n8n-nodes-base.postgres",
      "position": [
        1560,
        400
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "url": "={{ $vars.SLACK_WEBHOOK_URL }}",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "text",
              "value": "\ud83d\udcb0 Price Update: {{ $json.title }}\n\ud83d\udcca {{ $json.current_price }} \u2192 {{ $json.recommended_price }} ({{ $json.price_change_percent }}%)\n\ud83d\udcc8 Action: {{ $json.price_action }}\n\ud83d\udca1 Reason: {{ $json.reason }}\n\ud83d\udce6 Inventory: {{ $json.inventory_level }} units\n\ud83c\udfc6 Competitors: {{ $json.competitor_count }} tracked"
            }
          ]
        }
      },
      "id": "slack-notification",
      "name": "Send Price Alert",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1780,
        300
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "monitoring-summary",
              "name": "summary",
              "value": "Price monitoring completed for {{ $json.title }}",
              "type": "string"
            },
            {
              "id": "no-change-reason",
              "name": "reason",
              "value": "{{ $json.reason }}",
              "type": "string"
            }
          ]
        }
      },
      "id": "no-change-log",
      "name": "Log No Change",
      "type": "n8n-nodes-base.set",
      "position": [
        1560,
        600
      ]
    },
    {
      "parameters": {
        "jsCode": "// Error handling and retry logic\nconst error = $input.first().json;\n\nreturn {\n  json: {\n    error_type: error.name || 'Unknown Error',\n    error_message: error.message || 'An error occurred',\n    product_id: $('Extract Product Data').first()?.json?.product_id || 'unknown',\n    timestamp: new Date().toISOString(),\n    retry_count: $executionData.workflowData?.retryCount || 0\n  }\n};"
      },
      "id": "error-handler",
      "name": "Error Handler",
      "type": "n8n-nodes-base.code",
      "position": [
        1340,
        700
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "url": "={{ $vars.SLACK_WEBHOOK_URL }}",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "text",
              "value": "\ud83d\udea8 Price Monitor Error!\n\u274c Type: {{ $json.error_type }}\n\ud83d\udcdd Message: {{ $json.error_message }}\n\ud83c\udd94 Product: {{ $json.product_id }}\n\ud83d\udd04 Retry: {{ $json.retry_count }}/3"
            }
          ]
        }
      },
      "id": "error-notification",
      "name": "Send Error Alert",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1560,
        700
      ]
    }
  ],
  "connections": {
    "Scheduled Price Check": {
      "main": [
        [
          {
            "node": "Get Shopify Products",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Shopify Products": {
      "main": [
        [
          {
            "node": "Extract Product Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Product Data": {
      "main": [
        [
          {
            "node": "Check Amazon Prices",
            "type": "main",
            "index": 0
          },
          {
            "node": "Check eBay Prices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Amazon Prices": {
      "main": [
        [
          {
            "node": "Price Analysis Engine",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check eBay Prices": {
      "main": [
        [
          {
            "node": "Price Analysis Engine",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Price Analysis Engine": {
      "main": [
        [
          {
            "node": "Should Update Price?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Should Update Price?": {
      "main": [
        [
          {
            "node": "Update Shopify Price",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log Price Change",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log No Change",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Shopify Price": {
      "main": [
        [
          {
            "node": "Send Price Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Price Change": {
      "main": [
        [
          {
            "node": "Send Price Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Error Handler": {
      "main": [
        [
          {
            "node": "Send Error Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": "error-handler"
  },
  "versionId": "1.0.0",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "id": "price-monitor",
  "tags": [
    {
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z",
      "id": "e-commerce",
      "name": "E-commerce"
    },
    {
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z",
      "id": "pricing",
      "name": "Pricing"
    },
    {
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z",
      "id": "automation",
      "name": "Automation"
    }
  ]
}

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

How this works

Keep your online store's prices competitive across platforms by automatically monitoring competitors on Amazon and eBay, then dynamically adjusting your Shopify listings to stay ahead without constant manual effort. This saves time for e-commerce owners juggling multiple marketplaces, ensuring you never undersell or overprice. The key step involves a scheduled price check that fetches your Shopify products, pulls competitor data via HTTP requests, analyses the figures in a custom code node, and updates prices only if needed.

Use this workflow for small to medium e-commerce operations selling on Shopify with direct rivals on Amazon and eBay, especially when prices fluctuate daily. Avoid it for high-volume stores needing real-time monitoring, as the cron trigger runs on a fixed schedule rather than instantly. Common variations include adding more competitor sites like Etsy or integrating with a different database instead of Postgres for storing historical price data.

About this workflow

Multi-Platform Price Monitor & Dynamic Pricing. Uses httpRequest, postgres. Scheduled trigger; 13 nodes.

Source: https://github.com/MustafaKemal0146/Yapay-Zeka-Otomasyon-1/blob/46e56683900ff2af1a0007b7141a1f8cb0a32541/automations/e-commerce/price-monitor/workflow.json — 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

Disparador 1.8. Uses itemLists, postgres, emailSend, httpRequest. Scheduled trigger; 85 nodes.

Item Lists, Postgres, Email Send +1
Data & Sheets

공유회_알림톡_크론. Uses postgres, httpRequest, n8n-nodes-solapi. Scheduled trigger; 39 nodes.

Postgres, HTTP Request, N8N Nodes Solapi
Data & Sheets

QuepasaAutomatic. Uses postgres, postgresTrigger, httpRequest. Scheduled trigger; 39 nodes.

Postgres, Postgres Trigger, HTTP Request
Data & Sheets

QuepasaAutomatic. Uses postgres, postgresTrigger, httpRequest. Scheduled trigger; 39 nodes.

Postgres, Postgres Trigger, HTTP Request
Data & Sheets

QuepasaAutomatic. Uses postgres, postgresTrigger, httpRequest. Scheduled trigger; 39 nodes.

Postgres, Postgres Trigger, HTTP Request