Shopify Store Monitor: Price & Stock Changes
Pricing
from $1.00 / 1,000 results
Shopify Store Monitor: Price & Stock Changes
Monitor Shopify stores for price drops, restocks, sold-out variants, and new or removed products. The first run saves a baseline, one row per product; each later run returns only what changed. Public catalogue data, no login.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
reventadata
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
8 days ago
Last modified
Categories
Share
Unofficial. This Actor is not affiliated with, authorised by, endorsed by, or in any way officially connected to Shopify Inc. or to any store it reads. "Shopify" is a trademark of its respective owner and is used here only to describe what this tool reads. It reads the same public catalogue data a browser does.
Watch Shopify stores and get only what changed since your last run: price drops and increases, variants back in stock or sold out, new products and variants, removed products, and sales starting or ending.
Unlike a catalogue scraper that bills every product on every run, you pay for the full catalogue once (one row per product), then only for what changed: a Shopify price tracker and restock feed in one schedule (no built-in notifications; connect the dataset to your own).
What does it do?
- First run per store: a baseline. It reads the store's public catalogue
(
/products.json, falling back to the sitemap and product pages when that feed is closed), outputs onebaselinerow per product with every variant nested inside it, and saves a snapshot in a named key-value store. - Every later run: changes only. It reads the catalogue again, compares it with the
snapshot, outputs one row per changed variant plus one
summaryrow per store, and updates the snapshot.
Put it on an hourly or daily Apify schedule and the dataset of each run is your change feed.
Who is it for?
- Brands and retailers watching competitors' prices and markdowns.
- Resellers and deal hunters waiting for restocks of specific products.
- Analysts building a price history for a set of stores.
If you only need a one-off catalogue export, the first run already gives you that: one row per product, all variants included.
Input
| Field | Type | Description |
|---|---|---|
storeUrls | array | Store addresses, e.g. https://allbirds.com. Required. |
maxProductsPerStore | integer | Read at most this many products per store (default 2000). A capped read cannot report removed products. |
collection | string | Optional collection handle to watch just one collection. It has its own snapshot. |
emitBaseline | boolean | Output all products on a store's first run (default on). |
includeUnchanged | boolean | Also output unchanged variants (default off). |
includeInventory | boolean | Add inventory quantity and barcode from product detail endpoints (default off). |
maxInventoryLookups | integer | Maximum distinct product detail requests for inventory per store (default 200). |
minPriceChangePercent | number | Ignore price-only moves smaller than this percent. Stock changes are never hidden. |
stateStoreName | string | Named key-value store that holds snapshots (default shopify-monitor-state-v2). Use another name for a separate watch-list. |
resetState | boolean | Treat the run as a first run and save a fresh snapshot. |
proxyConfiguration | object | Off by default. |
There is no keyword search: the Actor watches whole stores or one collection.
Example input:
{"storeUrls": ["https://allbirds.com"],"maxProductsPerStore": 20}
Output
changeType is one of baseline, new_product, new_variant, removed_product,
removed_variant, price_drop, price_increase, back_in_stock, sold_out,
sale_changed, unchanged (only with includeUnchanged), summary, error. When one
variant changed in several ways at once, changes lists all of them and changeType holds
the first.
Baseline row (first run). Real row from a run on allbirds.com on 2026-10-12, shortened to 3 of its 16 tags and 2 of its 7 variants:
{"changeType": "baseline","changes": [],"storeDomain": "allbirds.com","currency": "USD","productId": 7340901859408,"handle": "womens-allbirds-flip-flop-dusty-pink","title": "Women's Allbirds Flip Flop - Dusty Pink","vendor": "Allbirds","productType": "Shoes","tags": ["allbirds::carbon-score => undefined","allbirds::cfId => color-a4d5d0f6620dc304306f503bf67bc5f9","allbirds::complete => true"],"url": "https://allbirds.com/products/womens-allbirds-flip-flop-dusty-pink","imageUrl": "https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_26Q2_Allbirds-Flip-Flop-Dusty-Pink_PDP_LEFT.png?v=1774646345","productUpdatedAt": "2026-10-12T01:14:41-07:00","variants": [{"variantId": 42146889039952,"variantTitle": "5","sku": "A12513W050","price": 25,"compareAtPrice": 50,"available": false,"cartUrl": "https://allbirds.com/cart/add?id=42146889039952"},{"variantId": 42146889072720,"variantTitle": "6","sku": "A12513W060","price": 25,"compareAtPrice": 50,"available": false,"cartUrl": "https://allbirds.com/cart/add?id=42146889072720"}],"scrapedAt": "2026-10-12T08:14:41.168712+00:00"}
Change rows (later runs) are one row per changed variant with storeDomain, currency,
productId, handle, title, vendor, productType, tags, url, cartUrl,
imageUrl, variantId, variantTitle, sku, price, previousPrice, priceChange,
priceChangePct, compareAtPrice, previousCompareAtPrice, available,
previousAvailable, scrapedAt, plus inventoryQuantity and barcode when
includeInventory is on. Removed products and variants carry the ids, handle, title and
the previous values.
Summary row (every run, one per store). Real row from the run right after the baseline
above, where nothing had changed. scanComplete is false because the run was capped at 20
products:
{"changeType": "summary","storeDomain": "allbirds.com","currency": "USD","mode": "diff","source": "products.json","scanComplete": false,"variantsScanned": 243,"productsScanned": 20,"changeCounts": {},"scrapedAt": "2026-10-12T08:15:09.523351+00:00"}
A store that cannot be read gives an error row instead, for example
"error": "HTTP 403, 919 B body at https://www.gymshark.com/products/gift-card.json".
What it costs
Billed per dataset item at $0.001, plus a $0.00005 start fee per run.
- Baseline: one row per product, not per variant. A 2,000-product store is about 2,001 items, about $2.00, once.
- Later runs: only the change rows plus one summary row per store. A store where nothing changed costs one row ($0.001) plus the start fee per run.
Limits
- Stock is in stock / out of stock per variant. The catalogue feed carries no quantities.
includeInventoryadds one request per distinct product to fetch quantity and barcode; many stores publish neither, and then both fields arenull. - Not every store is reachable. Some stores put a firewall in front of the whole site and
refuse automated requests on every path. Such a store returns an
errorrow; the other stores in the same run still complete. A run where every store fails ends as failed. - Prices are in the currency the store presents for this run (from
/cart.js, falling back to/meta.json);currencyis null when neither publishes it. Prices are not converted, and a store can show different currencies to different regions. - Removed products are only reported after a complete read (
scanComplete: trueon the summary row), so a capped run never reports false removals. - Password-protected stores are not supported.
- Only public catalogue data is read. No customer, seller or personal data is collected.
Scheduling
- Run the Actor once with your store list to save the baselines.
- Create an Apify schedule on this Actor (or on a saved task) with the same input.
- Keep
stateStoreNamethe same between runs; the snapshot lives there. Use a different name for each independent watch-list.
FAQ
Can I get every variant as its own row on the first run? No; baseline rows nest variants to keep the first run cheap. Change rows are per variant.
How do I start over? Set resetState to true for one run, or use a new stateStoreName.