Shopify Variant Availability Trends avatar

Shopify Variant Availability Trends

Pricing

from $2.00 / 1,000 variant transitions

Go to Apify Store
Shopify Variant Availability Trends

Shopify Variant Availability Trends

Compare two public Shopify variant snapshots and flag sold-out and back-in-stock transitions without guessing inventory quantities.

Pricing

from $2.00 / 1,000 variant transitions

Rating

0.0

(0)

Developer

Practical AI Lab

Practical AI Lab

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

8 days ago

Last modified

Security

Limited permissions

Share

Compare two public Shopify variant snapshots and list which variants sold out or came back in stock between them. The Actor works only from Shopify's public true/false available flag. It does not estimate inventory quantities, sales volume or demand.

What it does

  • Matches variants across an earlier ("before") and later ("after") snapshot by variant id.
  • Labels each variant: sold_out, back_in_stock, new_sold_out, new_available, removed, availability_unknown, still_sold_out, still_available.
  • Flags whether a whole product has no available variant (productAllSoldOutBefore / productAllSoldOutAfter), plus price changes seen on the same variant.
  • Saves a compact SNAPSHOT in the key-value store. Paste it as beforeSnapshot in your next run to build a recurring comparison without storing raw feeds yourself.
  • Saves a SUMMARY with counts, snapshot interval and warnings.

Input

FieldMeaning
beforeSnapshot (required)Shopify products.json object, or a previous run's SNAPSHOT.
afterSnapshotLater snapshot in the same format.
afterStoreUrlAlternative: a public https store domain. The Actor reads /products.json after checking robots.txt. Provide exactly one of afterSnapshot or afterStoreUrl; clear the pre-filled afterSnapshot when using a URL.
maxPagesLive feed pages to read (250 products each, 1-20, default 5).
beforeCapturedAt, afterCapturedAtOptional ISO 8601 times used to report the interval.
includeUnchangedAlso output variants whose availability did not change (default false).
maxRecordsUpper bound on dataset rows (default 1000).

The default input is a small copyable example and runs without any network access.

Example input

{
"beforeSnapshot": {"products": [{"id": 1002, "handle": "ceramic-mug", "title": "Ceramic Mug", "variants": [
{"id": 2003, "title": "White", "sku": "MUG-WHT", "available": false, "price": "14.00"}]}]},
"afterSnapshot": {"products": [{"id": 1002, "handle": "ceramic-mug", "title": "Ceramic Mug", "variants": [
{"id": 2003, "title": "White", "sku": "MUG-WHT", "available": true, "price": "15.00"}]}]},
"beforeCapturedAt": "2026-10-01T09:00:00Z",
"afterCapturedAt": "2026-10-08T09:00:00Z"
}

Example output row (illustrative, derived by hand from the input above)

{
"changeType": "back_in_stock",
"variantId": "2003",
"productHandle": "ceramic-mug",
"productPath": "/products/ceramic-mug",
"variantTitle": "White",
"availabilityBefore": false,
"availabilityAfter": true,
"priceBefore": "14",
"priceAfter": "15",
"priceChanged": true,
"productAllSoldOutBefore": true,
"productAllSoldOutAfter": false
}

Prices are normalized decimal strings ("14.00" becomes "14").

Safety and live-feed rules

  • Live reads use https only, a public domain name (no IP addresses, credentials, custom ports or local/internal suffixes), and refuse hosts that resolve to non-public addresses.
  • robots.txt is checked first; a disallow, or a robots server error, stops the run.
  • Redirects are not followed, pages are capped at 20, responses are size-limited, and requests are spaced one second apart.
  • Only the feed fields needed for the comparison are kept in memory.
  • Nothing is read from Google Maps, Amazon or any non-Shopify site.

Pricing event

The code reports one pay-per-event event, variant-transition, for each delivered sold_out or back_in_stock row. Context rows (new, removed, unchanged, unknown) are never charged, and runs that fail validation or fetching push nothing and charge nothing. No payable plan is configured in this repository; pricing must be set separately by the publisher.

Limitations and sample-size caveats

  • Availability only. available is a boolean. Quantities, sales and restock volume are not exposed and are not guessed.
  • Two points in time. A variant that sold out and returned between snapshots looks unchanged. Longer intervals hide more.
  • Small samples mislead. A handful of matched variants says little about a store; the summary warns below 30 matched variants. Counts are observations, not forecasts.
  • Feed quirks. Some stores hide, customize or rate-limit /products.json; draft or unpublished products never appear. Products disappearing from a feed are reported as removed, which may mean unpublished rather than discontinued.
  • Incomplete live reads. If maxPages is reached the snapshot can be partial and may produce false removed rows; a warning is added.
  • Snapshot consistency. Both snapshots should come from the same store and market. Variant ids must be unique and are the only matching key.
  • DNS timing. Public-address checks happen before connecting, but a hostile DNS server could still change answers between check and connection.
  • Demand not proven. Similar Shopify scrapers have free-tier users, but paid demand for this specific comparison has not been validated.

Local development

Tests are offline: python -m unittest discover -s tests from the project root. Running the Actor requires the Apify SDK 3.x from requirements.txt.