Shopify Price Stock Monitor avatar

Shopify Price Stock Monitor

Under maintenance

Pricing

Pay per event

Go to Apify Store
Shopify Price Stock Monitor

Shopify Price Stock Monitor

Under maintenance

Pricing

Pay per event

Rating

0.0

(0)

Developer

Radu Furtuna

Radu Furtuna

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

17 hours ago

Last modified

Share

Shopify Price & Stock Monitor

Every Shopify storefront exposes its full catalog at /products.json — no login, no API key, no scraping in the usual sense. This Actor polls that endpoint for the stores you pick and tells you the moment a price, sale price, or stock status changes on a product you already know about.

The market gap this fills, measured 10.09.2026: general Shopify data scrapers have real demand (2000+ users at the category leader), but the specific monitor niche — "tell me when something changes" rather than "give me the whole catalog again" — is wide open: about ten competing monitor products in the Store are each stuck at 2-3 users, despite the underlying demand being large.

How it works

  1. For each store (domain), fetch /products.json?limit=250&page=N — Shopify's own documented pagination, up to maxPagesPerStore pages (250 products each).
  2. The first run for a store establishes a baseline — no changes to report yet, nothing to compare against. You're billed for the check, not for a stack of "new" rows on data you never had before.
  3. Every run after that diffs the new snapshot against the last confirmed one and returns one row per changed field: price, compareAtPrice, available, or removed (a variant that disappeared).

Input

{
"monitorId": "my-competitors",
"watches": [{"watchId": "acme-store", "domain": "acme.com"}],
"maxPagesPerStore": 20
}

Output row

FieldMeaning
variantId, productHandle, productTitlewhat changed
fieldprice, compareAtPrice, available, or removed
oldValue, newValueas strings (Shopify itself returns price as a string; comparing strings avoids float-rounding false positives on money)
checkSequencewhich check of this store this change was found on

Pricing

Pay per event:

  • store-checked — charged once per store per run that returned parsable data. This is where the real cost of the run sits (an HTTP call per page), not the number of rows.
  • product-change-detected — charged per changed field, after the row is written to the dataset. A run that finds nothing beyond establishing a baseline is charged for the check, nothing more.

What happens if a run is interrupted. This Actor keeps a durable four-state delivery ledger (intent → written → charge started → billed) per monitor, and a single-flight lease so two overlapping runs of the same monitor can't double-process it. Delivery is at-least-once (a crash at exactly the wrong instant can duplicate a row, which costs you nothing); charging is at-most-once with a tracked uncertain window (chargeUncertainRows) for the one case that can't be resolved automatically — a crash inside the charge call itself.

Honest limits

  • New variants are not reported. This Actor is scoped to price/stock changes on variants it already has a baseline for. A brand-new product appearing is a different signal (and a different product) from "the price changed" — conflating them would blur both.
  • A store that hit the page cap is not treated as fully seen. If maxPagesPerStore cuts off before the store's own pagination ends, a variant that simply wasn't re-fetched this run is not reported as removed — only variants confirmed absent from a complete pass are. Price/stock changes on variants actually seen are still reported normally either way.
  • 404 and "not a Shopify store" are indistinguishable — both return HTTP 404 from /products.json. Either way, the watch is reported as a permanent configuration error, not retried.

Coverage record

Every run writes a coverage record: per-watch status and reason, pages fetched, whether pagination was complete, rows delivered and billed. If part of the run failed, the record says which part and why.

Author: OmniCoder (https://t.me/OmniCoder)