DEV Community

CBT Tools
CBT Tools

Posted on

How I Built a Big Data Price Discrimination Detector in 198 Lines of Vanilla JS

You've probably heard of 大数据杀熟 (big data price discrimination). It's the practice where platforms charge loyal customers MORE than new users for the exact same product. Same hotel, same flight, same restaurant — different price based on whether the algorithm thinks you'll pay more.

It's illegal in China under three separate laws. But proving it happens? That's the hard part. You need to document the same product across two accounts, at the same time, with screenshots and timestamps, then format it into a formal complaint citing the right legal articles.

So I built a tool to do it. In 198 lines of vanilla JavaScript. No framework, no backend, no signup, no dependencies.

What It Does

The Price Discrimination Detector does five things:

  1. Price entry form — log a price snapshot: product name, platform, price, account type (new/existing/VIP), device, timestamp
  2. Comparison engine — automatically flags price discrepancies >5% for the same product across accounts
  3. Evidence log — everything stored in localStorage, exports to JSON/CSV for your records
  4. Complaint report generator — formats your evidence into a formal complaint citing the specific legal articles (消费者权益保护法 Article 10 + 26, 个人信息保护法 Article 24)
  5. Analytics dashboard — price discrepancy trends over time, worst-offender platforms

The Architecture (Why Vanilla JS)

I've built 22 mental health tools with this exact architecture. It works:

single HTML file
  ├── <style> (inline CSS)
  ├── <body> (semantic HTML)
  └── <script> (vanilla JS, localStorage)
Enter fullscreen mode Exit fullscreen mode

Why no framework? Because the user is a stressed consumer who just discovered they're being overcharged. They don't want to install anything. They don't want to sign up. They want to open a webpage, log the price, and get their complaint document. Zero friction = maximum adoption.

Why no backend? Because price discrimination evidence is sensitive. Storing it on someone else's server creates a data liability. localStorage keeps it on the user's device. They export it when they're ready to file a complaint.

Why 198 lines? Because the problem is simple once you strip away the framework ceremony. The comparison engine is a filter + reduce. The complaint generator is a template literal. The analytics is a groupBy + avg. The hard part was the legal research, not the code.

The Comparison Engine (The Core Logic)

function detectDiscrimination(entries) {
  // Group by product name
  const byProduct = groupBy(entries, e => e.productName);

  const discrepancies = [];
  for (const [product, prices] of Object.entries(byProduct)) {
    if (prices.length < 2) continue; // need 2+ entries to compare

    const newPrice = prices.find(p => p.accountType === 'new')?.price;
    const existingPrice = prices.find(p => p.accountType === 'existing')?.price;

    if (newPrice && existingPrice) {
      const diff = (existingPrice - newPrice) / newPrice;
      if (Math.abs(diff) > 0.05) { // >5% discrepancy
        discrepancies.push({
          product,
          newPrice,
          existingPrice,
          percentDiff: (diff * 100).toFixed(1),
          direction: diff > 0 ? 'existing-charged-more' : 'new-charged-more'
        });
      }
    }
  }
  return discrepancies;
}
Enter fullscreen mode Exit fullscreen mode

That's it. Group by product, find the new-vs-existing price pair, flag if the difference exceeds 5%. The 5% threshold filters out legitimate price fluctuations (tax, fees) while catching real discrimination.

The Legal Layer

This is what makes the tool actually useful instead of just a spreadsheet. The complaint generator doesn't just dump your data — it cites the specific laws:

  • 《消费者权益保护法》第十条 — 消费者享有公平交易的权利 (right to fair trade)
  • 《消费者权益保护法》第二十六条 — 经营者不得以格式条款等方式作出对消费者不公平的规定 (no unfair terms)
  • 《个人信息保护法》第二十四条 — 自动化决策不得对个人在交易价格等交易条件上实行不合理的差别待遇 (no unreasonable differential treatment via automated decisions)
  • 《反垄断法》 — 滥用市场支配地位 (abuse of market dominance, for platform-level cases)

The generated complaint includes your evidence table, the legal citations, and a formal complaint structure ready to submit to 12315 (China's consumer complaint hotline) or the platform's customer service.

What I Learned Building This

  1. The problem is documentation, not detection. Everyone who suspects price discrimination already "detected" it. What they lack is systematic evidence + a formatted complaint. The tool's value is the output, not the input.

  2. Legal research > code. I spent more time reading 消费者权益保护法 than writing JavaScript. The 198 lines were easy; knowing which article to cite was hard.

  3. Vanilla JS is underrated for tools. The entire tool — form, comparison, storage, export, complaint generator, analytics — fits in 198 lines. A React version would be 500+ lines with a build step and node_modules. For a consumer-facing tool that needs to load instantly on a phone, vanilla wins.

  4. Zero-backend is a feature, not a limitation. Price discrimination evidence is legally sensitive. Keeping it in localStorage (user's device) avoids creating a data honeypot. The user exports when they're ready to file.

Try It

→ Try the live tool here — no install, no signup, no server. Just open and start logging prices.

Free tool: Price Discrimination Detector (this article)
Pro pack (if you want it): Notion template with pre-filled legal references, 12315 complaint formatting, escalation timeline tracker, and platform-specific evidence checklists.


This is the 23rd tool I've built with the zero-backend vanilla JS architecture. The first 22 were mental health tools (CBT thought records, anxiety trackers, etc.). This one's different — it's consumer rights, not psychology. But the architecture transfers: single file, localStorage, zero friction. If you're building a consumer-facing tool, consider going framework-free.

The tool is open-source. The legal citations are specific to China, but the architecture works for any jurisdiction — just swap the legal references.

Top comments (0)