Shopify Price Tracker | $0.80/1K | Exact Variants
Pricing
from $0.80 / 1,000 paid plans: product check (100 variants / 20 output rows)s
Shopify Price Tracker | $0.80/1K | Exact Variants
Shopify price tracker for exact sizes, colors and SKUs. Compare competitor prices and stock in the same market and currency. Keep price history, detect sales and restocks, and monitor product, collection or catalog URLs. From $0.80/1K product-check units on paid Apify plans.
Pricing
from $0.80 / 1,000 paid plans: product check (100 variants / 20 output rows)s
Rating
0.0
(0)
Developer
Hundevmode Labs
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
18 days ago
Last modified
Categories
Share
Shopify Price Tracker & Stock Monitor
Shopify Price Tracker & Stock Monitor tracks competitor prices and availability for exact product variants: a size, color, SKU or configuration. Monitor product URLs, collections or public Shopify catalogs, keep price history between scheduled runs, and compare explicitly linked offers in the same verified market and currency.
Product checks start at $0.80 per 1,000 check units on paid Apify plans. Collection and catalog checks have separate pricing. There is no extra Actor subscription. See pricing and check units before running a large watchlist.
On this page: Quick start · Inputs · CSV import and preview · Competitor comparisons · Output · History and alerts · Pricing · Schedules and API · FAQ
What can you track?
- Exact variants: monitor the price and availability of the size, color or pack you actually sell.
- Competitor offers: compare linked equivalent variants, identify the cheapest eligible offer and see whether a competitor undercuts your own price.
- Restocks and sales: detect price increases, price drops, sale changes, sold-out variants and backorders.
- Observed price history: retain previous snapshots and report observed 30-day price ranges and sample counts.
- Categories and catalogs: watch a collection or store, including products leaving a category.
- Source health: distinguish a confirmed disappearance from a blocked, incomplete or unsuccessful check. Failed checks preserve the last successful history.
Choose your first workflow
| You want to… | Start here | What to expect |
|---|---|---|
| Watch one size, color or pack | Paste its ?variant=ID product link; keep Track price and stock changes | First run: baseline and current variant. Later runs: changes and source health |
| Find the right variant first | Paste a plain product link; choose Export / discover variants and One row per variant | Current prices, SKUs, option names and exact variant links; no monitor history writes |
| Watch a category or catalog | Paste a clean collection URL or store root | All public products in that scope, subject to coverage and spending limits |
For a first try, use one product. A store domain requests the entire public catalog. Keep optional settings unchanged until you have checked the first result.
Alerts are data records. The Actor does not send email, Telegram or Slack messages itself. Use the notification workflow to connect your chosen destination.
Quick start: track one Shopify variant
Use the form without editing JSON
-
In Shopify URLs, paste your product, collection or store links, one per entry. The example link is prefilled so you can try a first check immediately.
-
To watch one size or color, use its product link with
?variant=123, replacing123with the real variant ID. A plain product link watches all variants. Copy the address after choosing the desired variant, or use the optional Exact SKUs / Exact size, color or pack fields below. If the storefront does not expose a selected variant in its URL, follow the discovery steps. -
For a specific market, enter Market country, such as
US, and optionally Expected currency, such asUSD. Leave them empty only if the store's returned market is appropriate for your watchlist. Setting currency alone does not switch the market or convert prices. For a localized link, explicitly set country or Storefront language so the requested context can be checked. -
Keep Track price and stock changes selected and run once. Save the input as a Task and add a schedule for repeat checks.
After the run, open Readable change and source-health report in the Output tab for the digest and next steps. Open Source coverage for the detailed verification records. BASELINE means the first complete selection was saved; it is normal to have no price-change events yet. Then open the observations to check that the size, SKU, country and currency are the ones you intended. If you see NO_MATCH, review the variant suggestions before scheduling.
The other settings are grouped into exact selectors, results, alerts, competitor matching, history and advanced limits. Defaults are suitable for a first product check. This equivalent API input selects one variant without a detailed target object:
{"urls": ["https://www.deathwishcoffee.com/products/valhalla-java-single-serve-pods?variant=392715452"],"country": "US","expectedCurrency": "USD","monitorId": "coffee-watch"}
How to find a Shopify variant ID, SKU or option name
-
Paste the plain product URL, without
variantoroption_values, into Shopify URLs. Clear the optional SKU and named-option selectors. -
Choose Export / discover variants (no history writes), then One row per variant (flat CSV) under Results.
-
Run once and open Variant observations. Each
observationincludesvariantId,sku,selectedOptions, price, availability and a direct varianturl. Check the exact size, color and pack; sold-out variants are included. -
Copy the desired
urlinto Shopify URLs, switch back to Track price and stock changes, and save a scheduled Task. Keep the same Task for repeat checks.
Discovery uses normal check pricing. It does not update monitor history, and a large flat export can require additional units. Start with one product rather than an entire store.
Select an exact SKU, size or color in the simple form
You can keep using Shopify URLs. Enter exact merchant SKUs in Exact SKUs, one per entry, or a small named-option object such as {"Size":"10 count"} in Exact size, color or pack. These optional fields apply to all supplied URLs. Use the names and values from discovery; the Actor does not guess translations, size equivalents or similar SKUs.
{"urls": ["https://www.deathwishcoffee.com/products/valhalla-java-single-serve-pods"],"country": "US","expectedCurrency": "USD","options": {"Size": "10 count"},"monitorId": "coffee-size-watch"}
SKU, option and URL variant restrictions are combined. For example, a URL for size M plus {"Size":"L"} produces NO_MATCH, rather than silently monitoring size L. If nothing matches a complete source, Source coverage includes up to five variant examples and copyable links for review. The Actor never changes your selection automatically.
Set different selectors per store with Advanced targets
- Clear Shopify URLs and use Advanced targets to select a variant by its ID, SKU or named options. Each target can define its own market and currency.
- Run the Actor. The first successful check creates a baseline and returns the selected variant; it does not label the baseline as a new-product alert.
- Save the input as an Apify Task and schedule repeat runs. Changes are compared with the previous successful check automatically.
This example selects a 10-count coffee pack in the US market. The merchant can change its product options; adapt the selection if needed.
{"targets": [{"targetId": "coffee-us","url": "https://www.deathwishcoffee.com/products/valhalla-java-single-serve-pods","country": "US","expectedCurrency": "USD","options": {"Size": "10 count"}}],"mode": "monitor","monitorId": "coffee-watch","outputMode": "changesOnly"}
With the default emitInitialSnapshot: true, the first run includes an observation, source status and check receipt. Repeat runs return changes, source statuses and receipts; unchanged variants do not generate price alerts. Use outputMode: "all" to export current observations on every check, or disable emitInitialSnapshot for a silent first baseline.
Task IDs isolate history automatically when monitorId is omitted. Ad hoc runs use the account's default monitor. Use a separate monitorId for each client or independent watchlist.
Shopify competitor price monitoring: common use cases
| Goal | How to use the Actor |
|---|---|
| Watch a competitor's price for your exact size or SKU | Select the variant on a product URL and schedule repeat checks |
| Know when a competing offer becomes available | Watch availability events, with separate backorder states |
| Compare your price with equivalent competing offers | Link one variant per store in a comparisonGroup; mark your offer with role: "own" |
| Follow a category's assortment | Monitor a collection URL and distinguish collection departures from market unavailability |
| Export current prices for analysis | Run mode: "snapshot" with outputMode: "all"; download Dataset JSON or CSV |
| Build an alert workflow | Filter change records and deduplicate by eventId; route source errors separately |
Import a Shopify watchlist from Excel or Google Sheets
Export your spreadsheet as CSV and paste its text into Import a CSV watchlist. Clear Shopify URLs (including the prefilled example) and Advanced targets first. The actor accepts one watchlist format at a time.
url,variantId,country,expectedCurrencyhttps://www.deathwishcoffee.com/products/valhalla-java-single-serve-pods,392715452,US,USD
Use the real product and selector values from your watchlist. CSV supports comma, semicolon or tab delimiters, UTF-8 BOM, quoted cells and up to 100 targets / 128 KiB. A downloadable one-row CSV watchlist template is also included in each run's Output tab.
| Column | What to enter |
|---|---|
url | Required public product, collection or store URL. Product URLs can already include ?variant=ID. |
variantId | One exact numeric Shopify variant ID, stored as text in your spreadsheet. Must agree with a URL variant if both are present. |
sku | One exact SKU, stored as text to keep leading zeros. |
option:Size, option:Color, option:NAME | Exact option name after the colon and exact value in the cell. Example: option:Size = M. At most three options. |
options | Alternative JSON object in a quoted CSV cell. Use this or option:NAME columns, not both in one row. |
country, language, expectedCurrency | Per-row market constraints; blank cells inherit the shared form settings. |
targetId, productId | Optional stable label / known numeric product ID. Labels must be unique; product IDs must be text. |
comparisonGroup, role | Reviewed equivalent-product group and own or competitor role. Groups require specific product URLs. |
Do not let Excel round IDs or convert them into scientific notation. 3.927E+8 and 392715452.0 are rejected. Unknown columns, conflicting selectors, duplicate scopes and malformed cells cause an input error instead of silently changing what is tracked. Empty selector cells inherit shared settings; without a selector, a product URL selects all its variants.
Preview a watchlist before checking stores
Choose Preview watchlist in What do you want to do?. This works with URLs, CSV or Advanced targets. Review canonical URLs, exact selectors, requested countries and warnings in the watchlist_preview rows or Parsed watchlist output.
Preview makes zero requests to stores, does not create or update monitor history, and incurs zero product/catalog check units. The Apify start fee still applies. It validates input structure only: it cannot confirm that a variant exists, that a store supports the market, or what a full check will cost. Switch to Track price and stock changes to verify the sources and start monitoring.
The same exact URL/market/selector scope imported from CSV reuses its existing monitor history; changing the format does not reset the baseline. Keep the same Task or monitorId.
Input: product URLs, variants, collections and stores
| Input | Purpose |
|---|---|
urls | Simple form: up to 100 public HTTPS links, one per entry. A ?variant= link selects one variant |
targets | Advanced alternative to urls: up to 100 URL strings or target objects with exact selectors/comparison groups. Use one populated list: urls, targets, or watchlistCsv |
targetId | Optional readable target label |
country | Requested market: uppercase code such as US. A top-level value applies to all links; per-target values override it. The source must confirm the country |
language | Optional requested language, such as EN or FR. Top-level values apply to all links; target values override them. The returned context must confirm it |
expectedCurrency | Reject a different returned currency. Top-level values apply to all links; target values override them. No market switching or FX conversion |
skus, options | Simple shared selectors at the top level, or individual selectors inside each Advanced target. Target values override shared values |
variantIds | Select exact Shopify variant IDs inside an Advanced target. Numeric IDs are strings and belong to that store |
productId | Optional Shopify product ID for a known product |
comparisonGroup, role | Link equivalent offers and optionally identify your own offer |
watchlistCsv | Optional CSV text instead of urls / targets; see the spreadsheet import example. |
mode | monitor retains history; snapshot exports current data without history writes; preview checks input structure without source requests or history writes |
outputMode | changesOnly by default; all includes current observations on every successful check |
observationLayout | product groups variants compactly by default; variant exports one observation per variant |
emitInitialSnapshot | Show the selected variants on the first successful monitor check; enabled by default |
monitorId | Optional stable watchlist ID. Saved Tasks isolate history automatically when this is omitted |
minimumPriceChangePercent | Decimal text such as "1" for a 1% cumulative price-alert threshold; default "0" |
historyLimit | Retained observations per variant: 90 by default, configurable from 2 to 365 |
removalConfirmations | Consecutive successful absence checks required: 2 by default, configurable to 5 |
emitNewLowAlerts, includeMetadataChanges | Optional new-low and metadata alerts; disabled by default |
emitMatchCandidates | Optional GTIN-based suggestions for human review; disabled by default |
advanced | Coverage, request, timeout, pagination and concurrency limits; Free-plan ceilings still apply |
In Advanced targets, targetId, productId, variantIds, comparisonGroup and role belong inside each target object. Country, language, currency, SKU and named-option defaults can also be set at the top level; a target's own values override those defaults. Empty URL lists are ignored, but supplying more than one nonempty watchlist (urls, targets, watchlistCsv) is rejected to prevent unintended duplicate checks.
A URL containing ?variant=123 selects that variant automatically. Multiple values within one option are OR; separate options and selector types are AND. Availability is never an output filter, so a sold-out variant stays in the tracked set.
Which Shopify links should you paste?
The URLs below are placeholders. Replace the domain, handle and IDs with real storefront values.
| Link | What gets checked |
|---|---|
https://store.example | The store's entire public catalog, subject to coverage limits |
https://store.example/collections/shoes | All products and variants in that collection, before optional SKU/options restrictions |
https://store.example/products/shoe | Every public variant of that product, before optional SKU/options restrictions |
https://store.example/products/shoe?variant=123 | Only variant 123, including when sold out |
https://store.example/products/shoe?option_values=10,20 | The variant matching those option-value IDs, in product-option order, when the source verifies them |
https://store.example/collections/shoes/products/shoe?variant=123 | The same exact product variant; the collection prefix is normalized away |
https://store.example/fr-fr/products/shoe?variant=123 | A localized product link; explicitly set country and/or language for verification |
Shopify documents both variant and option_values deep links. Option-value IDs differ from variant IDs: include one ID for every product option, in its option order. An incomplete option set cannot establish a selected variant. Unknown IDs or an impossible combination return NO_MATCH when the source is complete; the Actor does not substitute the storefront's default variant. If the public source cannot map option-value IDs, the check is unverifiable. See Shopify variant deep-link documentation.
Check the URL before saving a Task: collection filter.* parameters, tagged collections, search pages, ?selling_plan= subscription offers, cart/checkout links and unknown selection parameters are rejected with an explanation. They can imply a different selection or price. Copy a clean supported URL only if that is the scope you intend. A conflicting URL variant and Advanced variantIds is rejected as well.
Known tracking parameters such as utm_source, gclid and fbclid are ignored. Ordinary HTTP links are upgraded to HTTPS. page, sort_by and limit do not restrict coverage: the Actor checks the entire target and reports a warning. A sorted collection page 2 is not a watchlist for that page alone. Store and collection links cannot use product variant selectors.
Shopify's /collections/all catalog page can be virtual or merchant-customized. If an actual public collection with handle all exists, the Actor checks that collection. If the API does not expose it, the check returns SOURCE_UNVERIFIABLE with collection_all_not_exposed_use_store_root_for_entire_catalog. Paste the store root instead if you intend to monitor its entire public catalog. The Actor does not replace a possibly customized category silently. See Shopify catalog-page documentation.
Adding or reordering targets preserves existing target histories. Changing a target's URL, market, language, expected currency, product ID or selectors creates a new target baseline. After a product is observed, its ID is used on repeat checks, so a renamed handle does not silently lose it.
Monitor a Shopify collection or whole catalog
Use a collection URL such as https://store.example/collections/shoes or the store domain https://store.example. These are placeholders; replace them with public Shopify URLs.
{"targets": [{"targetId": "shoes-us","url": "https://store.example/collections/shoes","country": "US","expectedCurrency": "USD"}],"monitorId": "category-watch","outputMode": "all"}
Every product and variant page must complete. A cap, failed page, repeated cursor or duplicate ID produces a partial/failed status and preserves history. When a product leaves a collection, the Actor checks its product ID in the same market: LEFT_COLLECTION means the product still exists outside that category.
Compare exact competitor variants in the same market
Link products only after checking that they represent the same model, size, color, quantity, condition and purchasing terms. Matching titles or SKU strings alone do not establish equivalence across stores.
{"targets": [{"targetId": "own-store","url": "https://retailer-a.example/products/the-same-model","country": "US","expectedCurrency": "USD","options": {"Size": "42", "Color": "Black"},"role": "own","comparisonGroup": "model-black-42"},{"targetId": "competitor","url": "https://retailer-b.example/products/the-same-model","country": "US","expectedCurrency": "USD","variantIds": ["123456789"],"comparisonGroup": "model-black-42"}],"monitorId": "competitor-watch"}
The retailer URLs and variant ID are placeholders. Each group needs at least two targets, and each target must resolve to exactly one variant. At most one member can have role: "own". Ranking requires complete successful checks with the same applied country and currency. Mixed currencies, unknown markets, ambiguous selections and failed sources return an explicit comparison status without a best-price recommendation.
A valid comparison includes all offers, availability, the best eligible price, ties and price gaps. With an own offer, it also reports the cheapest eligible competitor, absolute/percentage gaps and signals such as COMPETITOR_UNDERCUTS_OWN_PRICE and OWN_UNAVAILABLE_COMPETITOR_AVAILABLE. Backorders remain visible and are excluded from ranking by default; enable includeBackordersInComparison if appropriate.
Prices are public unit prices. Checkout discounts, shipping, duties and tax adjustments are not calculated, and currencies are not converted. The Actor does not automatically change your selling price or calculate profit margins.
Find candidate matches by GTIN
Enable emitMatchCandidates to find cross-store variants sharing a checksum-valid GTIN in the same verified country and currency. UPC/EAN formats normalize to 14 digits. Suggestions include available product/options/pack details and proposedTargets to copy after review. Reused barcodes within a store are marked ambiguous.
Candidates are never automatically ranked: seller barcodes can be incorrect, and equivalent model, pack and terms still require review. The default limit is 100 suggestions. No barcode match does not prove that no equivalent product exists.
Output: prices, stock, history and change alerts
Results are stored in the Apify Dataset. The following is a shortened observation example; values illustrate the fields and are not a current price guarantee.
{"recordType": "observation","targetId": "coffee-us","productId": "171104582","variantId": "392715452","productTitle": "Valhalla Java Single-Serve Pods","sku": "5094SSC","selectedOptions": {"Size": "10 count"},"price": "14.99","compareAtPrice": null,"onSale": false,"currency": "USD","appliedCountry": "US","availableForSale": true,"availability": "IN_STOCK","backorder": false,"lowestObservedPrice30d": "14.99","highestObservedPrice30d": "14.99","observations30d": 1,"url": "https://www.deathwishcoffee.com/products/valhalla-java-single-serve-pods?variant=392715452"}
Prices use decimal strings. Each variant retains its ID, selected options, availability and history. With the default compact layout, multiple variants are grouped inside product_observation.variants. One selected variant on a product URL stays a flat observation. Large arrays are split into bounded batches with variantBatchIndex and variantBatchCount; variants are not dropped. Change records are always flat.
recordType | Contents |
|---|---|
observation | Current values for a selected variant |
product_observation | Product with its selected variants and their individual history fields |
change | Event type, stable eventId, before/after values, old/new prices and a direct variant URL |
source_status | Coverage, completeness, market, errors and whether the baseline advanced |
comparison | Linked offers, comparison status, best eligible price and own-offer signals |
check_receipt | Successfully billed target, check units and requested fees, including quiet checks |
match_candidate | Optional reviewable GTIN match suggestions |
Read the run digest and source health
Every completed scan writes REPORT (JSON) and REPORT-MARKDOWN (readable Markdown) into the run's default key-value store. Open them directly from the Output tab.
- Change counts cover unique delivered event IDs, including price drops/increases, stock events and competitor-position changes.
- Examples show the product, exact variant, before/after price or availability, and market. The digest contains up to 50 event examples;
digestTruncatedandomittedEventCountexplicitly tell you when more events remain in the full paginated dataset. - Source issues explain failed/incomplete checks, empty selections and pending disappearance confirmations, with a suggested next step. These are health notices, not confirmed product-removal events.
- Comparison issues identify groups that cannot be ranked safely.
shouldNotifyis false for a healthy baseline or quiet check, and true when changes or issues need attention.deliveryIdidentifies the whole run report; event consumers use each event'seventId.
The report summarizes rows already delivered to the dataset, including rows delivered before a run migration. Report generation adds no separately charged product/catalog event. Startup and normal check charges still apply. If the process fails before a report is written, inspect the run status/log; the notification template handles failed runs without a report separately.
A source failure preserves that source's prior history. A partially successful run can still advance history for other fully verified, billed targets. The digest does not turn a blocked storefront into a deletion alert.
Shopify product scraping for current prices and availability
For a current price export, use mode: "snapshot" and outputMode: "all". This reads supported public product data without updating monitor history. Use the compact JSON layout for large catalogs. A flat export with observationLayout: "variant" is convenient for spreadsheets but can increase invoice units; see pricing.
Dataset Console views select columns; they do not filter record types. Filter records explicitly in your integration. Download JSON for nested variants or choose a flat layout for variant CSV rows. The local tools/export_variants.py helper can flatten downloaded compact JSON without another paid Actor run.
Shopify price history, stock monitoring and restock alerts
Each retained observation records price and availability. Observation fields include firstSeenAt, lastPriceChangeAt, historyStartedAt, observed 30-day low/high prices and sample count. These describe actual retained samples; they do not prove continuous observation or a legally certified reference price.
Retention defaults to 90 observations per variant, up to 365. At hourly schedules, 90 samples cover fewer than 30 days. Inspect the history start and sample count before interpreting a 30-day figure. Removed variant histories are retained for up to 30 days to detect reappearance.
Price thresholds accumulate from the last price alert: successive small moves can cross the configured percentage. Quiet checks still advance observed history. Optional new-low alerts work independently of the percentage threshold.
For Shopify price change alerts, set Price change alert threshold (%) to 0 for any price move or 1 for a cumulative 1% change; omit the percent sign. Availability events do not depend on this price threshold.
| Events | Meaning |
|---|---|
PRICE_DECREASE, PRICE_INCREASE | Price crossed the configured threshold since its last price alert |
SOLD_OUT, RESTOCKED | Variant stopped or started accepting purchases, excluding separate backorder transitions |
BACKORDER_STARTED, BACKORDER_ENDED, BACKORDER_AVAILABLE | Purchasability and physical stock state changed with a backorder distinction |
SALE_STARTED, SALE_ENDED, SALE_REFERENCE_CHANGED | Selling/compare-at price relationship changed |
VARIANT_ADDED, VARIANT_REAPPEARED | Matching variant appeared or returned |
VARIANT_REMOVED | Product remains present but its variant is absent after confirmation |
PRODUCT_UNAVAILABLE_IN_MARKET | Product is absent from the verified public market after confirmation |
LEFT_COLLECTION | Product left the monitored category but still exists in that market |
NO_LONGER_MATCHES | Existing variant no longer matches the selected SKU/options |
BEST_OFFER_CHANGED, COMPETITIVE_POSITION_CHANGED | Verified best offer or your own offer's undercut/availability position changed |
Disappearances require two consecutive successful absence checks by default. Failed and partial runs do not count. Empty or sharply reduced catalogs are checked again within the run before counting toward disappearance. If verification disagrees or fails, history stays intact. Public-market absence is not an assertion that a merchant deleted the product in Shopify Admin.
Pricing and check units
| Target type | Paid Apify plans | Free Apify plan | One check unit covers |
|---|---|---|---|
| Specific product URL | $0.0008 ($0.80 / 1,000 units) | $0.001 ($1 / 1,000 units) | Up to 100 observed variants and 20 delivered product/change rows |
| Collection or whole catalog | $0.01 / unit | $0.02 / unit | Up to 500 current/previous product IDs, 5,000 observed variants and 500 delivered product/change rows |
Unit count is the largest rounded-up bucket count, not the sum. A product with 101–200 observed variants uses two product units. A flat 100-variant export uses five units because it writes 100 observation rows. A complete compact catalog with 692 products and 7,454 observed variants uses two catalog units ($0.02 on a paid plan); its 7,454-row flat export uses 15 ($0.15). All variants must still paginate completely.
Check fees include nonmatching products/variants scanned and successful absence checks for previously known IDs. Verified empty targets cost one unit. Separate selections of the same product are independent checks, even when they share an HTTP read; select multiple desired option values in one target when practical. Baselines and unchanged checks are billed.
History, comparisons, match suggestions and alerts have no separate event fees, but delivered product/change rows participate in the unit calculation. The automatic start fee is $0.00005 at the default 256 MB allocation: minimum one event, then one per allocated GB. Apify charges it on starts, including failed runs and resurrection. Resuming the same run does not invoice already completed check units again.
For 100 ordinary one-unit product targets checked daily for 30 days, the paid-plan event total is $2.4015, including 30 starts. A 15-product category normally uses one catalog unit, so its Free-plan total is $0.02005 including the start. There is no extra Actor subscription; any Apify plan subscription is separate. Free means the account tier, not a zero Actor price: checks consume its available credits.
Failed source verification, incomplete checks and budget-skipped targets have no check fee. Verified work already delivered remains billed if a later storage write or run step fails. Runtime platform usage is included; post-run storage access can still incur normal Apify platform charges.
Set a sufficient maxTotalChargeUsd in Apify's run options. The configured minimum is $0.00105, sufficient for one Free-plan product unit and one start. A whole target must fit the remaining budget and allowance before its check fee or history write; collection/catalog checks require a larger budget.
Free-plan limits
Free accounts have a shared limit of 100 invoice units per run across product and catalog events. Additional ceilings are 100 products and 3,000 observed variants per target, 1,000 variants per product, 80 HTTP requests and 180 seconds per run. Input cannot raise them. Resurrection shares the same allowance; a fresh run resets it. There is no Actor-level monthly free quota.
Schedule checks or use the Shopify price monitoring API
Save a configured Task in Apify Console and attach a schedule. Keep the same Task or monitorId for repeat checks. History is scoped by Actor, account and monitor in restricted storage. Overlapping runs of the same monitor are prevented by a Cloud lease.
To start an asynchronous run with the Apify API, save a valid input example as input.json and use an API token from your environment:
curl --request POST \'https://api.apify.com/v2/acts/bsyo7tfeD9bzJc38x/runs?maxTotalChargeUsd=0.10' \--header "Authorization: Bearer $APIFY_TOKEN" \--header 'Content-Type: application/json' \--data-binary @input.json
The response contains the run ID and Dataset ID. Wait for a successful run, then fetch Dataset items through the API or export them in Console. Paginate large datasets. See Apify API run documentation and Dataset items.
For email, Slack, n8n or another alert destination, connect your own workflow and filter recordType == "change". Send failed/partial source_status records to a separate health channel. The Actor returns data; it does not send messages or configure integrations for you.
Use eventId as an upsert/deduplication key. Delivery is at least once: interrupted delivery can replay an event with the same ID. Completed target checkpoints are reused after Actor migration; start a fresh run to retry failed sources. SUMMARY reports coverage and request counts, while BILLING records confirmed charges. A run with no verified source fails explicitly rather than succeeding with an unexplained empty result.
Connect price and stock events to notifications
Use an Apify run-finished integration/webhook and a workflow such as n8n or Make. No destination is configured by this Actor.
-
Save the monitor input as a Task. Add a daily or hourly schedule according to how often you need observations. Changes between scheduled checks can be missed; this is polling, not continuous real-time monitoring.
-
Trigger your workflow after a successful Actor run. Fetch that finished run's Dataset and paginate the response when needed. A successful run can still contain a failed individual source, so inspect source statuses too.
-
Keep rows with
recordType: "change". For a simple price/restock feed, selectPRICE_DECREASE,PRICE_INCREASE,SOLD_OUTandRESTOCKED. Add sale/backorder events if relevant. UseminimumPriceChangePercent: "1"to reduce small price-move noise. -
Deduplicate on
eventId. Build the notification from product title, selected options, market/currency,oldPrice→newPriceoroldAvailability→newAvailability, and the exact variant URL. A stock event can have identical old/new prices. -
Route incomplete or failed
source_statusrows separately. A failed run also needs a health notification. A quiet successful run with no change rows should not generate a price-change message.
For larger lists, collect these events into a daily digest rather than sending one message for every row. The Actor supplies a run digest in REPORT. Your workflow can forward it or build a daily digest across multiple runs. See Apify webhook documentation.
Download and connect the n8n Slack digest template
In any run's Output tab, download n8n notification template as JSON and import it into n8n. It is inactive, contains no tokens or account credentials, and schedules no checks by itself. You connect your own accounts and choose when to publish it.
-
On Apify terminal run, select a Header Auth credential. Add the same secret header to the Apify webhook's Headers template. Keep the default Apify webhook payload.
-
On both HTTP Request nodes, select the same Apify API credential with access to your own runs and their output. The template uses Simplified Custom Auth (
httpTemplatedCustomAuth): configure its authentication template as{"headers":{"Authorization":"Bearer {{api_key}}"}}and enter your token in the credential's secret field. Do not paste tokens into the workflow code, report, query strings or Actor input. Older n8n installations may require an update or an equivalent Header Auth credential. -
In Configure and validate event, enter your Slack channel ID. The expected Actor ID is preconfigured. On Send Slack digest, select your Slack credential and invite its bot to that channel. Choose your own destination; the template does not assume an account or channel.
-
Configure the Apify Task's webhook for
ACTOR.RUN.SUCCEEDED,ACTOR.RUN.FAILED,ACTOR.RUN.TIMED_OUTandACTOR.RUN.ABORTED, using the n8n production webhook URL. The workflow reads the run back from Apify, verifies its Actor/run identity, and then reads that run's report. It does not trust report content supplied in the webhook body. -
Test with your own small watchlist and destination, then publish the workflow. Healthy baseline/quiet checks stop without a Slack message. Changes and source-health issues produce one digest. A failed run with no report produces a run-failure notice; API/auth failures stop the workflow instead of fabricating healthy data.
Delivery limits: this is a small-volume, at-least-once template. It remembers confirmed Slack deliveries using n8n workflow static data, for 30 days / at most 1,000 reports. Static data persists in production executions; manual tests do not prove persistence. It is unsuitable as a strict exactly-once guarantee under concurrent/high-volume execution. Keep executions sequential for a small watchlist; use a transactional external deduplication store for stronger guarantees. A failure after Slack accepts a message but before acknowledgement can produce a duplicate. Successful delivery is marked only after Slack returns a message timestamp.
The webhook responds after processing. Apify may retry requests that fail or time out. Inspect and retry failed n8n executions; report-read HTTP errors and credentials need attention. If you want n8n failure notifications, configure your own Error Trigger handler. The template does not activate an error workflow or send messages until you connect and publish it. Merchant text is treated as plain text; Slack mentions, markup and link previews are disabled.
For a different notification destination, use the same REPORT.shouldNotify, REPORT.message and REPORT.deliveryId contract with your own email/Telegram/HTTP step. Fetch the paginated dataset if your downstream action needs every event rather than the bounded digest.
References: Apify webhook actions and duplicate delivery, n8n HTTP Request authentication and responses.
Start with a small watchlist and a predictable budget
Five product targets checked once daily for 30 days cost $0.1215 on paid Apify plans or $0.1515 on Free, including 30 starts at the default memory allocation, if each target uses one product-check unit. Five targets checked every six hours cost $0.486 paid or $0.606 Free, including 120 starts under the same assumptions.
These are Actor event estimates, not an Apify plan subscription quote. Large variant counts, flat exports, delivered change rows or more allocated memory can increase units/start fees; catalog URLs use catalog pricing. See the unit rules before scaling.
Check a small set of important comparable variants first. Keep quantity, purchase terms, country and currency aligned. Public unit-price monitoring does not establish the final delivered cost of a bundle, coupon or subscription offer.
Supported sources and practical limits
The main source is Shopify's public tokenless Storefront API. Applied market and currency are checked against the response. A store that ignores a requested country fails that check explicitly. Product and variant pagination must finish; GraphQL errors, including errors delivered with HTTP 200, do not become empty catalogs.
Ajax product JSON is a fallback only for Storefront endpoint 404/405 responses. It cannot verify an explicit country/language request, and responses with 250 variants cannot prove completeness. Such checks are rejected rather than treated as a complete catalog. See Shopify's product Ajax API.
No store login, Shopify Admin credentials, proxy configuration or cart/checkout modifications are needed. Password-protected, blocked or incompatible/headless stores may fail. Exact inventory quantities are not guaranteed; availability and backorders are reported when exposed by the source.
Paid-plan defaults allow 5,000 products and 50,000 variants per target, 5,000 variants per product, 1,000 HTTP requests, 900 seconds and 50,000 delivered product/change rows per run. Supported advanced limits can be adjusted; Free ceilings remain enforced. Changes-only output still requires source checks. Three target reads can overlap by default; each host is rate-paced.
Default memory is 256 MB, configurable up to 1 GB. For large catalogs with long retained histories, allocate 512 MB–1 GB and reduce history retention or selection size if needed. A successful short-history run does not establish capacity for months of history. Network conditions and store compatibility affect speed and coverage.
Understand quiet results and source errors
Always check source_status alongside alerts. A quiet successful check and a failed source mean different things.
| Result | What it means and what to do |
|---|---|
BASELINE | First successful check, or a changed target scope. Repeat with the same watchlist to start detecting changes |
OK with no change rows | Successful check with no reportable change. Choose All observations and changes if you need current variant rows every time |
NO_MATCH | The source loaded completely, but no current variant matched the selection, including on the first check. Review selectionHints for available variant examples/links, then check exact selectors and pending absence confirmations |
MARKET_UNSUPPORTED | The returned country/language/currency did not satisfy the request. Verify that the merchant serves that market |
ACCESS_RESTRICTED, SOURCE_FAILED, SOURCE_UNVERIFIABLE | Source could not be verified. Inspect the error detail and retry later or choose a supported public storefront; previous history is preserved |
PARTIAL | Pagination, coverage, output or another verification step did not complete. Inspect the error; reduce selection size or adjust supported limits. Free ceilings remain enforced |
Source status includes complete, error, observed/matched variant counts and baselineUpdated. selectionType identifies the selector used; resolvedOptions shows verified names/values for an option_values link. When a complete source has no match, selectionHints includes at most five examples, the candidate count and a ready-to-use discovery input. These are suggestions for manual review, not replacements. An ambiguous comparison target also gets hints to narrow it to one variant. Failed sources do not generate suggestions from unverified data.
A first complete NO_MATCH can save an empty baseline, but does not emit a new-product alert or prove a previously tracked product disappeared. Verified no-match checks are billed because the source was scanned. If a spending limit prevents a whole target from completing, it does not create a removal alert. Comparison statuses and source statuses have separate meanings; a comparison can decline to rank otherwise successful offers because their markets or selections are incompatible.
Frequently asked questions
Can I track Shopify competitor prices without their API keys?
Yes, for supported public storefronts. The Actor uses public Shopify endpoints and does not need the merchant's Admin API key. A blocked, private or incompatible store can still fail explicitly.
Can I monitor one size, color or SKU instead of a product's starting price?
Yes. Select the exact variant with a variant URL/ID, SKU or named options. Prices and availability belong to the selected variants, including sold-out variants.
How do I find the Shopify variant ID if the URL does not change?
Run one plain product URL in Export / discover variants mode with One row per variant. Review sku, selectedOptions and url in the observations, then copy the exact variant URL into a monitor Task. A product's displayed starting price is not proof that you selected a particular size.
Does it compare competitor prices in different currencies?
It ranks linked offers only in the same verified country and currency. It does not convert FX rates or equate offers from different markets. Set country and expectedCurrency for the intended comparison.
Does it return exact Shopify inventory quantities?
No guaranteed quantity is provided. The Actor tracks purchasability, stock status and backorders when exposed. Public Shopify data does not guarantee a precise warehouse count.
Will a failed store check mark its products as removed?
No. Failed and incomplete checks preserve the last successful history. Disappearance alerts require consecutive successful absence checks; collection departures and market unavailability have separate events.
Are competitor variants matched automatically?
You explicitly link equivalent variants in comparison groups. Optional GTIN candidates help find possible matches, but require review before ranking. A matching title or barcode alone is not proof of equivalent purchasing terms.
Can I use it on a Free Apify plan?
Yes, with Free-plan check prices and enforced coverage/run limits. Checks use available account credits. The advertised $0.80 per 1,000 product units applies to paid Apify plans; Free-plan product units cost $1 per 1,000.
Is price history saved automatically for scheduled runs?
Yes, in monitor mode. Reuse the same Task or monitorId; the first successful check creates the baseline. Retained sample count determines how much observed history is available.
Does it automatically reprice my Shopify store or send alerts?
It returns price/stock changes and comparison signals for your workflow. It does not edit your store, calculate a profitable selling price or send notifications itself.