Product Price History & Deal Quality Scorer
Pricing
from $1.70 / 1,000 products
Product Price History & Deal Quality Scorer
Track marketplaces and storefront product pages, build price history, detect fake discounts, and score whether deals are real, weak, or inflated.
Pricing
from $1.70 / 1,000 products
Rating
0.0
(0)
Developer
Trove Vault
Actor stats
1
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Track major marketplaces, common storefront platforms, and custom product pages, build reusable price history, detect fake discounts, and score whether a deal looks real, weak, or inflated. The actor compares the current price with the store's claimed reference price and the observed historical median, then returns a dealQualityScore, referenceIntegrity, alertWorthy, confidence, and a short plain-English reason.
It is built for Black Friday and Cyber Monday, but it stays useful year-round for deal media, shopping apps, affiliate publishers, competitor monitoring, price-alert workflows, and consumer trust layers.
The first run starts building history. Every later run gets smarter because the actor reuses a persistent Apify dataset of past observations.
Why use Deal Quality Scorer?
Most price trackers stop at "this product is 30% off". That is not enough.
Users want to know:
- Is this actually a strong deal?
- Is the markdown real or just a raised compare-at price?
- Is the product near its usual low, or only slightly below normal?
- Should I alert users, publish this in a newsletter, or ignore it?
Deal Quality Scorer adds that missing layer:
- Builds reusable price history over time instead of judging deals in isolation
- Scores against observed pricing, not only against the page's marketing badge
- Flags likely inflated reference prices when claimed savings do not match historical behavior
- Returns user-facing output such as
dealLabel,referenceIntegrity,alertWorthy,recommendation, andreason - Supports Amazon, eBay, Target, Shopify, WooCommerce, and broader platform-specific plus generic product-page extraction paths
What storefronts does it support?
Marketplaces
Direct support for Amazon, eBay, Target, and Walmart-specific patterns. Some marketplaces still benefit from proxy usage when they rate-limit or block direct requests.
Storefront platforms
Strongest support today is Shopify and WooCommerce. The actor also includes platform-aware extraction patterns for Magento, BigCommerce, PrestaShop, and Shopware.
Generic product pages
Everything else falls back to structured-data and selector-based extraction through:
- JSON-LD product markup
- meta price tags
- common visible price selectors
- optional custom CSS selectors you can provide in input
This means the actor is not limited to Shopify or WooCommerce. It is designed as a cross-store deal scorer, with selector overrides when a custom storefront uses non-standard markup.
What does the actor return?
| Field | Description |
|---|---|
currentPrice | Current observed selling price |
claimedReferencePrice | Store-provided original, regular, compare-at, or list price |
claimedSavingsAmount | Claimed absolute savings amount |
observedSavingsAmount | Savings amount versus the observed historical median |
discountVsClaimedPrice | Discount percent implied by the claimed reference price |
discountVsTypicalPrice | Discount percent versus the historical median price |
historyMaturity | new, building, usable, or strong |
dealQualityScore | 0 to 100 score estimating how strong and trustworthy the deal is |
dealLabel | Output label such as strong_real_deal, weak_deal, or likely_fake_discount |
referenceIntegrity | Whether the claimed reference price looks consistent, mixed, provisional, or suspect |
pricePosition | Whether the current price is at_low, near_low, below_typical, typical, or above_typical |
alertWorthy | true when the deal looks strong enough to surface in alerts or editorial workflows |
confidence | 0 to 1 confidence estimate based on extraction quality and history depth |
reason | Short explanation of why the actor gave this score |
Who pays for this?
Deal media and affiliate publishers
Filter out weak promotions before they hit your site, newsletter, or Telegram channel. Use alertWorthy, dealLabel, and reason to decide what deserves coverage.
Shopping apps and consumer trust layers
Add a trust score on top of raw scraped prices so users know whether a discount is worth acting on.
Competitor monitoring teams
Track how competitors price products over time and see whether their sale messaging reflects real discounting or not.
BFCM watchlists
Build history before peak sale periods, then score promotions when Black Friday and Cyber Monday arrive.
Why this is better than a plain scraper
| Feature | Raw price scraper | Deal Quality Scorer |
|---|---|---|
| Current price | Yes | Yes |
| Claimed reference price | Sometimes | Yes |
| Persistent history across runs | Rarely | Yes |
| Compare against historical median | No | Yes |
| Flag likely fake markdowns | No | Yes |
| Alert-friendly output | No | Yes |
| Shopify support | Sometimes | Yes |
| WooCommerce support | Sometimes | Yes |
| Generic HTML fallback | Sometimes | Yes |
| Custom selectors for hard cases | Rarely | Yes |
How it works
- You provide one or more product URLs.
- The actor detects the storefront and tries the cheapest structured extraction path first.
- It reads prior observations from a persistent history dataset.
- It scores the current deal against observed pricing behavior, not just the store's marketing.
- It appends the new observation back into the history dataset unless it is a duplicate within the configured dedupe window.
Extraction priority:
- Platform-specific lightweight extractors when available
- Shopify product endpoint
- WooCommerce Store API
- JSON-LD product data
- Meta tags and visible price selectors
- Optional custom selectors from input
Input
| Field | Type | Default | Description |
|---|---|---|---|
productUrls | Array | required | Product-detail-page URLs to analyze |
historyDatasetName | String | deal-quality-history | Named dataset used to persist observations across runs |
historyDatasetId | String | optional | Existing dataset ID to use instead of the named history dataset |
historyLookbackDays | Number | 365 | Number of days of history used for scoring |
minimumHistoryPoints | Number | 3 | Minimum prior observations before scores are treated as mature |
dedupeWindowHours | Number | 12 | Skip saving duplicate history rows inside this window |
persistObservation | Boolean | true | Save the current observation back into the history dataset |
includeHistorySnapshot | Boolean | true | Include recent observations in the output |
maxHistoryEntriesInOutput | Number | 8 | Max entries inside historySnapshot |
platformHint | String | auto | Force a known platform such as amazon, target, shopify, woocommerce, or generic |
enableHtmlFallback | Boolean | true | Fall back to HTML extraction when APIs are not available |
titleSelector | String | optional | Optional CSS selector for product title |
currentPriceSelector | String | optional | Optional CSS selector for current price |
regularPriceSelector | String | optional | Optional CSS selector for original or compare-at price |
currencySelector | String | optional | Optional CSS selector for currency |
availabilitySelector | String | optional | Optional CSS selector for stock status |
canonicalUrlSelector | String | optional | Optional CSS selector for canonical URL |
proxyConfiguration | Object | disabled | Enable only if the site blocks direct requests |
datasetId | String | optional | Append scored rows to another dataset in addition to the run dataset |
runId | String | optional | Pipeline or parent run ID |
Example input:
{"productUrls": [{"url": "https://www.amazon.com/XCHI-Watercolor-Fireworks-Independence-Decorations/dp/B0GT49Z3RC/"},{"url": "https://deathwishcoffee.com/products/chocolate-hazelnut-16oz-klean-kanteen"}],"historyDatasetName": "deal-quality-history","historyLookbackDays": 365,"minimumHistoryPoints": 3,"dedupeWindowHours": 12,"persistObservation": true,"includeHistorySnapshot": true,"platformHint": "auto","enableHtmlFallback": true,"proxyConfiguration": {"useApifyProxy": false}}
Example for a custom storefront with explicit selectors:
{"productUrls": [{"url": "https://example-store.com/products/example-product","label": "custom-store"}],"currentPriceSelector": ".product-price .sale","regularPriceSelector": ".product-price .compare","currencySelector": ".product-price","availabilitySelector": ".inventory-status"}
Output
Each product becomes one scored dataset row.
{"recordType": "dealScore","productUrl": "https://deathwishcoffee.com/products/chocolate-hazelnut-16oz-klean-kanteen","platform": "shopify","extractionMethod": "shopify_product_js","priceSourceQuality": "api","title": "Chocolate Hazelnut Klean Kanteen","currency": "USD","currentPrice": 17.5,"claimedReferencePrice": 25,"claimedSavingsAmount": 7.5,"observedSavingsAmount": 0,"discountVsClaimedPrice": 30,"discountVsTypicalPrice": 0,"historyMaturity": "building","dealQualityScore": 43,"dealLabel": "provisional_discount","referenceIntegrity": "provisional","pricePosition": "at_low","alertWorthy": false,"confidence": 0.46,"recommendation": "collect_more_history","reason": "Store shows 30% off, but there are only 1 prior observations in the last 365 days. Current price $17.50 was saved so the score can mature over time."}
How to use the score
85-100: Excellent real deal. Usually at or near the historical low and materially below normal pricing.70-84: Strong real deal. Good candidate for alerts, newsletters, affiliate coverage, or price-drop pushes.55-69: Decent deal. Real, but not unusually strong.40-54: Weak or provisional deal. Keep monitoring.0-39: Poor or misleading deal. Often above normal pricing or driven by a suspect reference price.
Troubleshooting
The first runs are not very confident
That is expected. This actor improves over time. Keep persistObservation enabled and run it on a schedule so the history dataset becomes more informative.
A supported site still returns PRICE_NOT_FOUND
Leave enableHtmlFallback on and add currentPriceSelector plus regularPriceSelector if the page uses non-standard classes or variant widgets. This is the intended override path for custom HTML and edge-case storefront templates.
The actor reads the current price but not the original price
Some stores expose the live price but do not expose a usable compare-at price in HTML or structured data. The actor can still score against historical pricing, but fake-markup detection will be weaker.
Repeated runs are not adding new history rows
That is usually correct behavior. If the latest observation is identical within dedupeWindowHours, the actor skips writing a duplicate row.
A marketplace returns HTTP 403 or a robot check
Enable proxyConfiguration and try again. Some marketplaces and large retailers rate-limit direct traffic. Keep proxy usage selective, because the actor is designed to stay cheap by default.
Support
If you want stronger support for a specific storefront pattern, open an issue through the actor page and include:
- one product URL
- what you expected to extract
- what the actor returned
That is the fastest way to improve a new platform pattern.
Limitations
- Shopify and WooCommerce are still the strongest structured-storefront paths in the current version.
- Marketplace support is expanding, but some sites may require proxy usage or storefront-specific tuning.
- Generic HTML support depends on the page exposing meaningful JSON-LD, meta tags, visible prices, or selectors you can provide.
- The actor deliberately stays on low-cost HTTP paths first. It does not use a browser crawler in this version.
- Very early history can surface strong signals, but mature fake-markup detection still benefits from repeated observations over time.
Frequently asked questions
Is this only for Black Friday and Cyber Monday?
No. BFCM is a strong use case, but the actor is useful year-round for shopping apps, affiliate sites, price alerts, and competitor intelligence.
Does it work on non-Shopify sites?
Yes. It supports marketplaces, storefront platforms, and generic product pages. Shopify and WooCommerce are the strongest structured-storefront paths, but the actor is not limited to them.
Can I force a known platform?
Yes. Use platformHint if you already know the storefront type and want to skip auto-detection.
What happens on the first run?
The actor extracts the current price, saves it into the history dataset, and returns a provisional score if there is not enough prior history yet.
Can I share one history dataset across many runs?
Yes. That is the default pattern. Use historyDatasetName to keep one rolling history dataset, or set historyDatasetId if you already manage one elsewhere.
Can I integrate this into a larger workflow?
Yes. Use datasetId and runId to merge scored rows into downstream datasets or actor chains.
Can I use this output for user alerts?
Yes. alertWorthy, recommendation, dealLabel, and reason are designed exactly for that.
Does likely_fake_discount mean fraud?
No. It is a heuristic signal based on observed pricing behavior, not a legal conclusion.
API example
curl -X POST "https://api.apify.com/v2/acts/trovevault~deal-quality-scorer/runs" \-H "Authorization: Bearer YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"productUrls": [{ "url": "https://deathwishcoffee.com/products/chocolate-hazelnut-16oz-klean-kanteen" },{ "url": "https://www.amazon.com/XCHI-Watercolor-Fireworks-Independence-Decorations/dp/B0GT49Z3RC/" }],"historyDatasetName": "deal-quality-history","historyLookbackDays": 365,"minimumHistoryPoints": 3}'
Related actors
- Shopify Products Scraper: collect full Shopify catalog data cheaply
- WooCommerce Products Scraper: collect full WooCommerce catalog data from Store API
- E-Commerce Tech Stack Detector: detect storefront technology before scraping
Changelog
v0.3
- Added Amazon price-block extraction
- Added Target next-data extraction
- Expanded platform detection for Amazon, Walmart, eBay, Etsy, Target, Best Buy, Magento, BigCommerce, PrestaShop, and Shopware
- Added platform-specific selector packs for broader cross-store support
- Removed misleading example labels from input defaults and improved marketplace-focused troubleshooting
v0.2
- Added WooCommerce support through Store API
- Added generic HTML fallback with JSON-LD, meta tags, visible price selectors, and optional custom selectors
- Added
referenceIntegrity,pricePosition,claimedSavingsAmount,observedSavingsAmount,alertWorthy, andscoreDrivers - Improved multi-platform scoring and extraction diagnostics
v0.1
- Initial release with persistent price history, Shopify-first extraction, and deal scoring
Feedback
If you want stronger support for a specific storefront type or want to turn this into a more editorial or alert-driven product, send a representative product URL through the actor page. That is the fastest way to make the next version more valuable.