Promotions & Launch Monitor: Sales, Codes & New Products avatar

Promotions & Launch Monitor: Sales, Codes & New Products

Pricing

from $1.60 / 1,000 promotion or launches

Go to Apify Store
Promotions & Launch Monitor: Sales, Codes & New Products

Promotions & Launch Monitor: Sales, Codes & New Products

Watch competitor stores for sale banners, discount codes, free-shipping thresholds, markdowns and new products or collections. Shopify feeds plus any store's pages; a promotion ends only after two runs without it. Changes-only watchlists, compact JSON for AI agents.

Pricing

from $1.60 / 1,000 promotion or launches

Rating

0.0

(0)

Developer

CleanPull

CleanPull

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 hours ago

Last modified

Categories

Share

Give it competitor store addresses and get every promotion they show: sale banners, discount codes, free-shipping thresholds, bundles, gifts, sign-up offers and markdowns, plus new products and collections with the date each went live. It reads Shopify stores' public product and collection feeds and the pages of any store (WooCommerce, Magento, Salesforce Commerce Cloud, PrestaShop, BigCommerce and custom). Schedule it and every run says what started, what ended and what launched since the last one. A promotion counts as ended only after two runs in a row without it, so rotating banners are never reported as ended. From $1.00 per 1,000 pages checked.

What you can do with it

  • "Tell me when a competitor starts or ends a sale." Put their stores in a watchlist, turn on Changes only and schedule it daily: you get the new promotions, the ones that ended (with their last sighting) and one change summary per store.
  • "What codes and free-shipping thresholds are my competitors showing?" Every code printed on the site, and every free-shipping offer with its amount and currency ($35+, over £50, dès 60 €).
  • "How deep are their markdowns?" On Shopify, the share of the newest products priced below their compare-at price and the deepest cuts; elsewhere, the crossed-out prices on a sale page.
  • "What did they launch this week?" Shopify products and collections with their publish date; on other stores, product links new on the pages you watch.
  • "Feed a digest or an AI agent." Compact JSON with the same fields for every store, a field picker, and a dataset view per job.

How it reads a store

  1. The home page (or the country site you give, brand.com/us/): its announcement bar, header, hero banners (including their image alt text) and the rest of the page. Menus, footers and pop-ups count only when a text names a code, a threshold or a discount.
  2. Shopify stores: the store's public feeds, /products.json (the newest published products, with prices and compare-at prices) and /collections.json.
  3. Extra pages you add: a sale page (its crossed-out prices are a markdown), a new-arrivals page (new product links are launches), a product page (its structured sale price is a markdown).

Each promotion has a confidence: high in an announcement bar, the header or the store's own data; medium elsewhere on the page, in menus or in image alt text.

In tests on 26 stores on 9 platforms, read from Apify's servers, it read 26 of 26. It found an announcement-bar promotion on 13, a free-shipping threshold on 16 and a discount code on 7, and launches with dates on all 7 Shopify stores that publish their feed. Read twice, minutes apart, 27 pages showed no false changes. One rotating bar (Old Navy) swapped a promotion between runs, and nothing was reported as ended.

What makes the data right

  • Ended means ended. A promotion missing once is only counted in the run summary; it is reported as ended when the next run misses it too. A page that fails to load never counts as the promotion missing.
  • One promotion stays one promotion. A code is the promotion whatever words surround it; a free-shipping offer is its threshold; countdowns and dates in a banner ("ends in 2h 13m") do not make a new one.
  • Not every "sale" is a promotion. Menu links to sale sections, "Sale price" lines on product cards, cart messages ("spend $20 more for free shipping") and privacy text are left out. Codes are read only as stores print them, in capitals after "code".
  • A block is never an empty result. Each store gets its own proxy ladder (direct, then datacenter, then residential only for stores that block the others); a store that blocks every tier is named in the run summary, with the reason, and not charged.
  • Launches are real. On Shopify, a product counts as launched when it is new to the watchlist and went live since the last run, dated by the store. On other stores, the first read of a page records its product links as a baseline, and a new link becomes a launch only when two runs in a row show it, so a rotating carousel never reads as a launch.
  • Only delivered rows are billed. Pages that could not be read cost nothing; the change summary is free; a run stopped by a limit is checked in full next time, and rows already delivered are never charged twice, even after a restart.
  • Only public addresses are read. A URL or redirect pointing into a private network is never fetched.

Input

FieldWhat it does
storesStore addresses, one per line (brand.com, or brand.com/us/ for a country site)
pagesOptional. Other pages of those stores: a sale page, new arrivals, a product page (up to 10 each)
promotionTypesWhich promotions to report: sitewide-sale, sale, code, free-shipping, bundle, gift, signup-offer, markdown
includeLaunches, includeCollectionsNew products and (Shopify) new collections
launchWindowDaysFirst run: Shopify launches within this many days (default 7)
maxProductsPerStore, maxLaunchesPerStoreShopify products read (default 100) and launch rows per store per run (default 25)
changesOnly, monitorNameOnly what changed since the last run with the same watchlist name
maxRunCostUsdOptional. Max cost per run, for scheduled runs without a spending limit of their own
fields, maxConcurrency, proxyConfigurationField selection, stores at a time (default 3) and your own proxy
startUrlsAccepted for compatibility with other actors (same as stores)

Example inputs

A competitor watchlist, checked daily for changes:

{
"stores": ["https://www.tentree.com", "https://www.zwilling.com/us/", "colourpop.com"],
"changesOnly": true,
"monitorName": "competitors"
}

A store and its sale page, codes and free shipping only:

{
"stores": ["https://www.zwilling.com/us/"],
"pages": ["https://www.zwilling.com/us/sale/"],
"promotionTypes": ["code", "free-shipping", "markdown"]
}

What Shopify stores launched in the last 30 days:

{
"stores": ["kith.com", "colourpop.com"],
"launchWindowDays": 30,
"promotionTypes": [],
"maxLaunchesPerStore": 200
}

Output

Three kinds of rows, told apart by recordType. A real promotion row:

{
"recordType": "promotion",
"store": "tentree.com",
"storeUrl": "https://www.tentree.com/",
"platform": "shopify",
"promotionId": "015303d778fcb51bef4535a04dd3d6a40b05da1774f82bc88ecdcb755008149e",
"type": "code",
"status": "running",
"text": "FREE SHIPPING ENDS MONDAY. CODE: FREESHIP",
"code": "FREESHIP",
"threshold": null,
"thresholdCurrency": null,
"percentOff": null,
"amountOff": null,
"confidence": "high",
"foundIn": "bar",
"pageUrl": "https://www.tentree.com/",
"firstSeen": "2026-10-14T23:19:26.522Z",
"lastSeen": "2026-10-14T23:19:26.522Z",
"endedAt": null,
"firstRun": true,
"checkedAt": "2026-10-14T23:19:26.522Z"
}

status is new (first seen since the last run), running (seen again, or on a watchlist's first run, which also has "firstRun": true) or ended (missing two runs in a row; lastSeen is its last sighting). Free-shipping rows carry threshold and thresholdCurrency (from €, £ or an ISO code in the text, else the store's own currency when the symbol fits it; a bare $ on a store with no stated currency stays null); markdown rows carry markdown (on Shopify: products read, discounted, sharePercent, maxPercentOff and the ten deepest cuts with their prices).

A launch row:

{
"recordType": "launch",
"store": "kith.com",
"platform": "shopify",
"kind": "product",
"title": "Giorgio Armani & Kith for ASICS GEL-MAI 0.1 - Monument / Quarry",
"url": "https://kith.com/products/ai1203b454-400-dr",
"launchedAt": "2026-10-14T13:52:49-04:00",
"createdAt": "2026-10-14T13:52:46-04:00",
"relaunch": false,
"confidence": "high",
"source": "shopify-feed",
"price": 300,
"compareAtPrice": null,
"currency": "USD",
"vendor": "Kith",
"checkedAt": "2026-10-14T23:19:21.978Z"
}

kind is product or collection; source is shopify-feed (dated by the store) or page-diff (a product link shown on two runs in a row, dated when first seen). relaunch marks a product published more than 30 days after it was created.

From the second run on, each store with something new also gets one free change row: started and ended promotions, launches with their titles, freeShippingThreshold when it moved, and markdownSharePercent when the markdown share moved by 10 points or more.

Dataset views: Promotions, Launches and Changes. RUN_SUMMARY in the key-value store gives the outcome (COMPLETE, PARTIAL, NO_CHANGES, EMPTY, FAILED), per store the platform, pages read, promotions seen, started, ended and missing once, launches and residential requests, the charges, and every page that could not be read, with the reason.

Pricing

EventFree and BronzeSilverGold and above
Promotion or launch (a delivered row)$2.00$1.80$1.60
Page checked (a home page with its Shopify feeds, or an extra page)$1.00$0.90$0.80
Request through residential addresses (add-on, only for stores that block the others)$6.00$6.00$6.00

Per 1,000. Each run also has a $0.00005 start fee. The change summary rows are free. A watchlist of 20 competitor stores checked daily with Changes only is about 600 page checks a month ($0.60), plus the promotions and launches that changed. Requests through residential addresses are capped at 500 KB each (a larger one is not read or charged).

Limits

  • Bars rendered only by scripts are not read (the actor reads the page's HTML, without a browser): Kith's and Nike's, for example.
  • Codes are read when the site prints them; codes sent by email, behind a pop-up click or in a cart are not.
  • Launches on stores without a Shopify feed come from product-shaped links (/products/, /product/, /p/, numbered .html pages); stores whose product addresses look like categories give no launches.
  • Shopify feeds are read only where the store publishes them (headless fronts often do not: their launches come from product links).
  • Prices and promotions are those a visitor from the proxy's country sees, without a sign-in.
  • Stores that block every proxy tier (Uniqlo, Crocs, Adidas in tests) are listed in the run summary and not charged; Amazon, Walmart and Target are not read.
  • Read stores at a pace their terms allow: at most two requests at a time per store.
  • Nothing found: when nothing could be read because it is not there (a store whose home page is not there or sends shoppers to another site, or input naming no store), the run still succeeds, with one free recordType: "unreadable" row per item giving the reason; nothing is charged. A run near its time limit stops starting stores, delivers what it read and lists the rest the same way.

Changelog

  • 0.1.x, reliability (2026-10-24): runs that find nothing (a store whose home page is not there or sends shoppers to another site, or input naming no store) end SUCCEEDED with a free unreadable row per item saying why, instead of FAILED; a run stops starting stores before its time limit and ends with what it read, never TIMED-OUT. A run where the site refused on every route for every store still fails. Prices and events unchanged.
  • 0.1.x (2026-10-14): RUN_SUMMARY perStore says whether each store was delivered in full (complete); a store whose page check could not be paid for no longer counts in storesRead.
  • 0.1 (October 2026): promotions from announcement bars, headers, banners and image alt text (sales, codes, free-shipping thresholds, bundles, gifts, sign-up offers); Shopify product and collection feeds for markdowns and dated launches; sale and product pages; launches from new product links; watchlists with changes only, ended after two runs; Max cost per run.