# Changelog of Shopify Price & Stock Change Tracker (`scrapebench/shopify-change-tracker`) Actor

- **URL**: https://apify.com/scrapebench/shopify-change-tracker/changelog.md
- **Full Actor documentation**: https://apify.com/scrapebench/shopify-change-tracker.md

## Changelog

### 0.3 — 2026-07-31

#### Fixed

- **A store that refused us is no longer reported as a store with no catalog.** Any non-200 on
  `/products.json` produced the same `unavailable` marker, so a rate-limit on a big storefront
  read as "this store does not publish a catalog" — a confident wrong answer. The marker now
  carries `fetch_error`: null means the store genuinely publishes no catalog, `HTTP 429` (or
  similar) means we were refused and the run is worth repeating.
- **Blocked stores are retried through the residential pool automatically**, the way
  `shopify-store-intel` already did it. No proxy toggle to find; only refused domains use
  residential bandwidth.
- **A refusal costs seconds instead of minutes.** Neither pool now sits through a long backoff on
  refusals that were never going to clear — a comparable run spent 262s to return nothing.
- **A connection error degrades instead of failing the run**, so it no longer counts against the
  Store maintenance badge.

### 0.2 — 2026-07-21

#### Fixed

- **Runs no longer time out delivering their own results (#132).** Delivery was one `push_data`
  plus one `charge_result` round-trip per record — ~2.6s/item, which capped a run at roughly 90
  rows and timed out **1 of 3** customer runs at the inherited 300s platform timeout. Rows now go
  out in chunks of 50 with one charge per chunk. The actor's default run timeout was also raised
  from 300s to 3600s.
- **A truncated run says so.** When the PPE budget cap ends a run early, a free `truncated` marker
  is emitted with the number of undelivered changes. Previously the `snapshot` heartbeat announced
  every change the diff found (e.g. 248) while the dataset held only what fit (e.g. 82), and
  nothing told the customer the difference.

#### Note on charging

Push still precedes charge, so a customer is never billed for a row they did not receive. The
trade-off of batching is the mirror image: if the budget cap lands mid-chunk, up to 49 rows were
delivered free. That error is bounded and falls in the customer's favour.

### 0.1 — initial build

- Monitor Shopify stores for catalog changes via the public `/products.json` endpoint.
- Diff each store against the previous run's snapshot (persisted in a named KV store):
  price increases/decreases, back-in-stock / out-of-stock flips, products added/removed.
- First run per domain captures a free baseline; subsequent runs emit a free per-store
  heartbeat plus one billable record per change.
- `minPriceChangePercent` noise filter; `maxProductsPerStore` cost cap; optional proxy.
- PPE: charge per detected change (`dataset-item`); never charge for runs with no changes.
