Shopify Variant Discount Drift Watch avatar

Shopify Variant Discount Drift Watch

Pricing

from $2.00 / 1,000 variant drift scans

Go to Apify Store
Shopify Variant Discount Drift Watch

Shopify Variant Discount Drift Watch

Give one public Shopify store URL. Repeat runs flag variant compare-at discount drift and ignore invalid compare-at prices.

Pricing

from $2.00 / 1,000 variant drift scans

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

3 days ago

Last modified

Security

Limited permissions

Share

Give this Actor one public Shopify store URL. It reads the store's public product feed, saves a compact per-store snapshot, and on every later run reports which variants changed their compare-at ("was") discount. It also flags compare-at prices that are invalid, so they are never counted as discounts.

Quick start (one URL)

  1. Open the Actor and enter your store URL, for example https://your-store.com. Nothing else is required.
  2. Run it. The first run has nothing to compare against, so it stores a snapshot and returns a single BASELINE_CREATED summary, a sample of the currently discounted variants, and any variants whose compare-at price is already invalid.
  3. Run it again later. Each repeat run compares the new prices with the stored snapshot and returns one row per changed SKU.

Minimal input:

{ "storeUrl": "https://www.allbirds.com" }

The example URL is only a sample. Run the Actor only against stores you are allowed to check, and replace it with your own.

Running it again later

The Actor does not run itself. To get repeat runs, create an Apify Schedule (Actor page > Schedules) that starts this Actor with the same input, for example once a day or once a week. No alerts are sent by this Actor; read the dataset, or attach your own Apify integration or webhook to the schedule if you want notifications.

Snapshots are kept in a named key-value store (default name pal-variant-drift-state, one entry per store domain), because a run's default store is not shared with later runs. Keep the same stateStoreName between runs. Deleting that store, or using the resetBaseline option, starts a fresh baseline.

What gets reported

Change typeMeaning
DISCOUNT_STARTEDA valid compare-at discount appeared.
DISCOUNT_ENDEDA discount that existed in the last snapshot is gone.
DISCOUNT_DEEPENED / DISCOUNT_REDUCEDDiscount percentage moved by at least the configured number of points.
REFERENCE_PRICE_RAISEDThe discount grew only because the compare-at price rose while the selling price stayed the same.
NEW_VARIANT_DISCOUNTEDA variant that was not in the last snapshot arrived with a valid discount.
VARIANT_REMOVED_WHILE_DISCOUNTEDA discounted variant left the feed (only reported when the feed was read completely).
INVALID_COMPARE_AT_DETECTEDThe compare-at price cannot be trusted; no discount is counted.

A compare-at price counts as a discount only when it is a number strictly above a positive selling price and implies a discount of at most 95%. Equal or lower compare-at values, non-numeric values, zero prices and extreme ratios are treated as invalid. The 95% limit is a heuristic of this Actor, not a Shopify rule. A compare-at of 0 or an empty value means "no compare-at".

Each drift row includes SKU, product and variant titles, previous and current price and compare-at price, discount percentages, the change in percentage points, a suggested action, and a product URL. Every run also writes:

  • a SUMMARY row in the dataset (status, counts, sample discounted variants, caveats),
  • OUTPUT in the run's key-value store (same summary as JSON),
  • DRIFT_CSV in the run's key-value store (the drift rows as CSV). The dataset can also be exported as JSON or CSV from the Apify console.

Inputs

FieldDefaultNotes
storeUrlrequiredPublic HTTPS store URL. Only the domain is used.
minDriftPercentagePoints5Minimum discount movement to report for deepened/reduced/raised.
maxPages4Pages of up to 250 products. Maximum 10.
requestTimeoutSecs20Per request.
resetBaselinefalseReplace the saved snapshot with the current state.
stateStoreNamepal-variant-drift-stateNamed store holding snapshots.

Access rules and safety

  • Only the public /products.json feed and robots.txt of the given store are requested, nothing else. No login, cookies, proxies, or inventory endpoints.
  • robots.txt is read first and checked, with the Actor's own user-agent (PALVariantDriftWatch), before every feed request. Wildcards and longest-match precedence are supported. A missing robots.txt (404/410) means no restrictions; a forbidden, erroring, or unreachable one makes the run stop. A crawl-delay above 10 seconds also stops the run.
  • Only https store domains on the default port are accepted. IP addresses, localhost, credentials and internal-looking names are refused, and every host name is resolved and must point to public addresses only. The connection is pinned to the checked address. Redirects on product feed requests are not followed.
  • At least one second passes between requests; response sizes, pages (10 max) and stored variants (20,000 max) are capped.

Limitations and sample-size caveats

  • The first run cannot show drift. Meaningful drift needs at least two runs, and any pattern in how often a store changes discounts needs many runs over time. Treat results from a handful of scans as anecdotes.
  • Findings describe only what the public feed shows at the moment of each run. Changes that happen and revert between two runs are invisible.
  • The feed has no currency; values are compared only within one store. Stores with multiple markets may show different prices by region.
  • If a store has more products than maxPages allows, results are marked feedIncomplete, removals are not reported, and older snapshot entries are kept.
  • Some stores disable or restrict the public product feed, or are protected against automation. Those runs end with a clear error and no results.
  • A compare-at price is a merchant-set field; this Actor reports inconsistencies in it but does not judge legal or advertising compliance.
  • Page-based feed paging may behave differently on very large catalogs.

Billing

The code defines one pay-per-event event, variant-drift-scan, charged once after a scan has completed and its results and snapshot are stored. Failed runs (blocked robots, unsafe host, missing feed, network errors) push no dataset items and trigger no charge. No payable plan is configured in this repository; whether and how the event is priced is decided when the Actor is published.

Development

Tests run fully offline and need no Apify SDK:

python -m unittest discover -s tests -t .