logo
Build a Price Monitoring Dashboard with an Ecommerce API

Build a Price Monitoring Dashboard with an Ecommerce API

MultiCartAPI
Author
Published At
#price-monitoring, #dashboard, #api, #ecommerce, #python
Blog Tags

Price is the single biggest lever in ecommerce. A 1% price advantage can mean the difference between winning and losing the buy box on Amazon, or converting a customer on your own store. Yet most businesses still check competitor prices manually — if they check at all.

In this guide, we'll build a price monitoring dashboard that automatically tracks product prices across ecommerce sites and alerts you when competitors change their pricing.

What We're Building

By the end of this tutorial, you'll have:

  • A Python script that pulls product prices from Amazon, eBay, and other retailers via MultiCartAPI
  • A SQLite database that stores price history over time
  • A simple dashboard that visualises price trends
  • Email alerts when prices drop below your thresholds

Architecture Overview

MultiCartAPI ──→ Price Collector (Python) ──→ SQLite Database
                                                    │
                                              Dashboard (Flask)
                                                    │
                                              Email Alerts

The system runs on a simple cron job. Every hour, the collector fetches current prices and stores them. The dashboard reads from the same database.

Step 1: Set Up the Price Collector

First, install the dependencies:

pip install requests sqlite3 smtplib

Create the collector script:

import requests
import sqlite3
import json
from datetime import datetime

API_KEY = "your_multicartapi_key"
BASE_URL = "https://multicartapi.com/api/v1"

# Products to monitor
PRODUCTS = [
    {"asin": "B0DFJJFL4M", "domain": "com.au", "name": "AirPods Pro 2"},
    {"asin": "B0CHX3QBCH", "domain": "com.au", "name": "iPad Air M2"},
    {"asin": "B0BDJ279KF", "domain": "com.au", "name": "Kindle Paperwhite"},
]

def init_db():
    conn = sqlite3.connect("prices.db")
    conn.execute("""
        CREATE TABLE IF NOT EXISTS price_history (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            asin TEXT NOT NULL,
            domain TEXT NOT NULL,
            product_name TEXT,
            price REAL,
            currency TEXT,
            in_stock BOOLEAN,
            seller TEXT,
            timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
        )
    """)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS alerts (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            asin TEXT NOT NULL,
            threshold REAL NOT NULL,
            email TEXT NOT NULL,
            active BOOLEAN DEFAULT 1
        )
    """)
    conn.commit()
    return conn

def fetch_price(asin, domain):
    response = requests.get(
        f"{BASE_URL}/amazon/product",
        params={"asin": asin, "domain": domain},
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    if response.status_code == 200:
        data = response.json()
        return {
            "price": data.get("price", {}).get("current"),
            "currency": data.get("price", {}).get("currency", "AUD"),
            "in_stock": data.get("availability", {}).get("in_stock", False),
            "seller": data.get("availability", {}).get("fulfilment", "Unknown"),
        }
    return None

def collect_prices():
    conn = init_db()

    for product in PRODUCTS:
        result = fetch_price(product["asin"], product["domain"])
        if result and result["price"]:
            conn.execute(
                """INSERT INTO price_history 
                   (asin, domain, product_name, price, currency, in_stock, seller)
                   VALUES (?, ?, ?, ?, ?, ?, ?)""",
                (
                    product["asin"],
                    product["domain"],
                    product["name"],
                    result["price"],
                    result["currency"],
                    result["in_stock"],
                    result["seller"],
                ),
            )
            print(f"  {product['name']}: ${result['price']} {result['currency']}")

    conn.commit()
    conn.close()

if __name__ == "__main__":
    print(f"Collecting prices at {datetime.now()}")
    collect_prices()
    print("Done.")

Step 2: Schedule Regular Collection

Add a cron job to run the collector every hour:

crontab -e
0 * * * * cd /path/to/project && python collect_prices.py >> /var/log/price-monitor.log 2>&1

This gives you 24 data points per day per product — enough to spot trends without burning through API credits.

Step 3: Build the Dashboard

Create a minimal Flask dashboard to visualise the data:

from flask import Flask, render_template_string
import sqlite3
import json

app = Flask(__name__)

DASHBOARD_HTML = """
<!DOCTYPE html>
<html>
<head>
    <title>Price Monitor</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        body { font-family: system-ui; max-width: 1200px; margin: 0 auto; padding: 20px; }
        .product-card { border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; margin: 16px 0; }
        .price { font-size: 2em; font-weight: bold; color: #2563eb; }
        .change-up { color: #dc2626; }
        .change-down { color: #16a34a; }
        canvas { max-height: 300px; }
    </style>
</head>
<body>
    <h1>Price Monitor Dashboard</h1>
    {% for product in products %}
    <div class="product-card">
        <h2>{{ product.name }}</h2>
        <div class="price">${{ "%.2f"|format(product.current_price) }} {{ product.currency }}</div>
        {% if product.price_change != 0 %}
        <span class="{{ 'change-up' if product.price_change > 0 else 'change-down' }}">
            {{ "%.2f"|format(product.price_change) }} ({{ "%.1f"|format(product.price_change_pct) }}%)
        </span>
        {% endif %}
        <canvas id="chart-{{ loop.index }}"></canvas>
    </div>
    <script>
        new Chart(document.getElementById('chart-{{ loop.index }}'), {
            type: 'line',
            data: {
                labels: {{ product.dates | tojson }},
                datasets: [{
                    label: 'Price',
                    data: {{ product.prices | tojson }},
                    borderColor: '#2563eb',
                    tension: 0.1
                }]
            }
        });
    </script>
    {% endfor %}
</body>
</html>
"""

@app.route("/")
def dashboard():
    conn = sqlite3.connect("prices.db")
    
    products = []
    for row in conn.execute("SELECT DISTINCT asin, domain, product_name FROM price_history"):
        asin, domain, name = row
        
        history = conn.execute(
            "SELECT price, currency, timestamp FROM price_history WHERE asin=? ORDER BY timestamp DESC LIMIT 168",
            (asin,)
        ).fetchall()
        
        if not history:
            continue
        
        current = history[0][0]
        previous = history[1][0] if len(history) > 1 else current
        
        products.append({
            "name": name,
            "current_price": current,
            "currency": history[0][1],
            "price_change": current - previous,
            "price_change_pct": ((current - previous) / previous * 100) if previous else 0,
            "dates": [h[2][:10] for h in reversed(history)],
            "prices": [h[0] for h in reversed(history)],
        })
    
    conn.close()
    return render_template_string(DASHBOARD_HTML, products=products)

if __name__ == "__main__":
    app.run(port=5000, debug=True)

Step 4: Add Price Drop Alerts

Extend the collector to check thresholds and send alerts:

import smtplib
from email.mime.text import MIMEText

def check_alerts(conn, asin, current_price, product_name):
    alerts = conn.execute(
        "SELECT email, threshold FROM alerts WHERE asin=? AND active=1",
        (asin,)
    ).fetchall()
    
    for email, threshold in alerts:
        if current_price <= threshold:
            send_alert(email, product_name, current_price, threshold)

def send_alert(to_email, product_name, price, threshold):
    msg = MIMEText(
        f"{product_name} has dropped to ${price:.2f}, "
        f"which is below your threshold of ${threshold:.2f}.\n\n"
        f"Check your dashboard for details."
    )
    msg["Subject"] = f"Price Alert: {product_name} is now ${price:.2f}"
    msg["From"] = "[email protected]"
    msg["To"] = to_email
    
    with smtplib.SMTP("localhost") as server:
        server.send_message(msg)

Scaling Beyond Amazon

The same approach works for any retailer that MultiCartAPI supports. Add Walmart, eBay, or specialty retailers to your monitoring list:

# Monitor the same product across multiple retailers
CROSS_RETAILER = [
    {"source": "amazon", "id": "B0DFJJFL4M", "domain": "com.au"},
    {"source": "ebay", "id": "12345678", "domain": "com.au"},
    {"source": "walmart", "id": "987654", "domain": "com"},
]

This gives you a complete picture of competitive pricing across the market, not just within a single marketplace.

Key Takeaways

  1. Automate early — Manual price checking doesn't scale. Set up automated collection from day one.
  2. Store history — Current prices are useful. Price trends over time are powerful. Always store historical data.
  3. Alert, don't poll — Build alerts so you only look at the dashboard when something changes.
  4. Use structured data — MultiCartAPI returns clean JSON, so you spend time analysing data instead of parsing HTML.

Next Steps

  • Add more products and retailers to your monitoring list
  • Build weekly price reports that summarise trends
  • Integrate with your pricing engine to auto-adjust prices based on competitor movements
  • Check out our API documentation for the full list of supported retailers and data fields