I built a competitor pricing monitor in 3 days, here's how it actually works

Published: (April 25, 2026 at 04:53 PM EDT)
2 min read
Source: Dev.to

Source: Dev.to

The Problem

I lost a deal last month because a prospect told me my competitor had dropped their price. I started looking for a tool to automate price‑monitoring and ended up building one myself.

Tech Stack

  • Framework: Next.js 16 (App Router)
  • Scraping: Playwright
  • Storage: Supabase
  • Email: Resend
  • Hosting & Cron: Vercel

Classification Engine

The hardest part was separating signal from noise. Generic page monitoring is easy, but pricing pages change constantly (rotating banners, dynamic content, etc.). I created a classification engine that categorizes changes into four types:

TypeDescription
PRICE_CHANGEDollar amounts moving
PLAN_CHANGEPlans appearing or disappearing
FEATURE_CHANGEFeatures shifting between tiers
COSMETICEverything else (ignored)

Only PRICE_CHANGE, PLAN_CHANGE, and FEATURE_CHANGE trigger an email alert.

Key Insight: Normalized Diff

  1. Strip dates, times, navigation text, cookie notices, and social handles.
  2. Run a line‑by‑line diff on the remaining text.

This normalization dramatically reduces false positives.

Why Playwright Over Puppeteer

Pricing pages are almost always JavaScript‑heavy single‑page applications. Puppeteer often struggles with modern React apps where content loads after the initial HTML response.

Playwright, combined with waitUntil: 'networkidle' and an additional 2‑second wait, reliably handles aggressive lazy‑loading, despite a slightly larger dependency footprint.

Cron Worker

  • Runs daily at 9 AM.
  • Processes monitors sequentially with a 3‑second delay between each (no parallelism).
  • Parallel scraping quickly leads to rate‑limiting and blocks.

Workflow:

  1. First run: Save a baseline snapshot.
  2. Subsequent runs: Diff against the previous snapshot, classify the change, and send an alert if it’s significant.

What I’d Do Differently

The current diff algorithm is the weakest link. A line‑by‑line text diff catches most changes but misses subtle restructurings—e.g., when a competitor moves a feature to a different plan section without altering the text.

Next step: Extract structured data (plan name → price → features[]) and diff the structure instead of raw text.

Live Demo

The monitor is live and free:

  • No account or credit card required.
  • Paste a URL and receive email notifications when pricing changes.

Questions

Feel free to ask about any part of the implementation—scraping, the diff engine, or email delivery.

What would you build differently?

0 views
Back to Blog

Related posts

Read more »