# Shopify New Product Monitor - Competitor Launches (`gganbukim/shopify-new-arrivals-monitor`) Actor

Watch any Shopify store on a schedule and get only the products it launched recently. Remembers what it already reported between runs, so a daily schedule alerts you once per product instead of resending the whole catalogue. Scanning is free - you pay only for new arrivals.

- **URL**: https://apify.com/gganbukim/shopify-new-arrivals-monitor.md
- **Developed by:** [DONGMIN KIM](https://apify.com/gganbukim) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 new product reporteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Shopify New Product Monitor — Track Competitor Launches on a Schedule

Watch any set of Shopify stores and get **only the products they just launched**. Put it on a daily schedule and it tells you what your competitors shipped yesterday — not their whole catalogue, every morning, forever.

### The part that actually matters

This actor **remembers what it has already reported**, in a named store that persists between runs. Run it daily and each new product reaches you exactly once.

That sounds obvious and it is easy to get wrong: Apify's *default* key-value store is scoped to a single run, so a monitor that keeps its history there silently forgets everything and re-alerts the entire back catalogue on every run. This one uses a named store, and the behaviour is covered by a test.

You can point several watchlists at different memory stores, or clear the store in the Console to start fresh.

### Input

```jsonc
{
  "storeUrls": ["competitor-one.com", "competitor-two.com"],
  "withinDays": 7,
  "dateField": "published_at",
  "onlyUnseen": true,
  "onSaleOnly": false,
  "maxProductsScanned": 2000
}
```

- **withinDays** — for a daily schedule, `7` is sensible: wide enough to survive a missed run, narrow enough not to flood you.
- **dateField** — `published_at` is when shoppers could first see it. `created_at` is when it was added, which can be much earlier for a planned drop. Use `created_at` if you want the earliest possible warning.

#### Every option

The same wording you see in the Apify console, with the JSON key for API and MCP callers.

| Option | What it does | Default |
|---|---|---|
| **Shopify stores to watch** — `storeUrls` *(required)* | Bare domains or any URL on the store. Watch as many competitors as you like in one scheduled run. | — |
| **Consider new if launched within (days)** — `withinDays` | Products older than this are ignored. For a daily schedule, 7 is a sensible window — it covers a missed run without flooding you. | `30` |
| **Date to judge by** — `dateField` | published\_at is when the store made it visible to shoppers. created\_at is when it was first added, which can be much earlier for planned drops. | `"published_at"` |
| **Only report products not seen before** — `onlyUnseen` | Remembers reported product IDs between runs, so a schedule alerts you once per product. Turn off to always emit everything in the window. | `true` |
| **Memory store name** — `memoryStoreName` | Named key-value store holding the IDs already reported. Change it to run two independent watchlists, or clear that store in the Console to start alerting from scratch. | `"shopify-new-arrivals-seen"` |
| **Only new products already discounted** — `onSaleOnly` | Narrow to launches that arrived with a compare-at markdown. | `false` |
| **Max products scanned per store** — `maxProductsScanned` | The catalogue is read to find recent items. Raise for very large stores, lower to cut cost. You are only billed for the new products reported, never for scanning. | `2000` |
| **Concurrency** — `concurrency` | Stores processed in parallel. Raise it when watching many competitors at once. | `3` |
| **Proxy** — `proxyConfiguration` | Leave the default. | `{"useApifyProxy":true}` |

### Output

Newest first, one row per new product — the same full product shape the store scraper
delivers, plus two fields only a monitor can know.

```json
{
  "storeDomain": "competitor-one.com",
  "productId": 8123456789012,
  "title": "Wool Runner Mizzle",
  "handle": "wool-runner-mizzle",
  "url": "https://competitor-one.com/products/wool-runner-mizzle",
  "vendor": "Allbirds",
  "productType": "Shoes",
  "tags": "new,mens,wool",
  "createdAt": "2026-08-09T11:02:00-04:00",
  "publishedAt": "2026-08-10T14:00:00-04:00",
  "updatedAt": "2026-08-11T08:30:00-04:00",
  "ageDays": 2,
  "firstSeenAt": "2026-08-12T17:20:04.113Z",
  "minPrice": 135,
  "maxPrice": 135,
  "onSale": false,
  "inStock": true,
  "variantCount": 9,
  "availableVariantCount": 9,
  "imageUrl": "https://cdn.shopify.com/…",
  "imageCount": 5,
  "options": [{ "name": "Size", "values": ["9", "10", "11"] }],
  "description": "Water-repellent wool.",
  "variants": [
    { "variantId": 1, "title": "9", "sku": "WRM-9", "price": 135, "available": true, "option1": "9" }
  ]
}
```

#### Every field

You are billed per new product delivered, so here is everything a row can contain. A field
is absent when the store did not publish it.

| Field | What it is |
|---|---|
| `firstSeenAt` | When **this actor** first reported the product. Only a monitor can know this; the store does not publish it. |
| `ageDays` | Days between the product's date field and this run, so you can tell a same-day drop from a backfill. |
| `storeDomain` | Which store the row came from, so a multi-store run reads without a join. |
| `productId` | Shopify's numeric product id. It is also the key the run-to-run memory uses. |
| `title` | Product title. |
| `handle` | The URL slug — the stable key across renames. |
| `url` | Canonical product URL. |
| `vendor` | Brand as the store records it. |
| `productType` | The store's own product type. |
| `tags` | The store's tag string. |
| `createdAt` | When the product was created in the store's admin. |
| `publishedAt` | When it went live on the storefront. Usually the field you want **Date field** set to. |
| `updatedAt` | Last edit of any kind. |
| `description` | Body copy with HTML stripped. |
| `options` | The option axes, each with `name` and `values`. |
| `imageUrl` | First image. |
| `imageCount` | How many images the product has. |
| `variantCount` | Number of variants. |
| `availableVariantCount` | How many are in stock. |
| `inStock` | `true` when any variant is available. |
| `minPrice` / `maxPrice` | Live price range at launch — the number that dates fastest, which is the point of catching it now. |
| `compareAtPrice` | Highest compare-at price found. |
| `onSale` | `true` when a compare-at price sits above the live price. A launch already on sale is worth knowing. |
| `discountPercent` | That markdown as a whole-number percent. |
| `variants` | Per-variant rows: `variantId`, `title`, `sku`, `price`, `compareAtPrice`, `available`, `requiresShipping`, `grams`, `option1`–`option3`. |

### Who this is for

- **Competitive intelligence teams** — wire the dataset to Slack or email through a webhook and know about a launch within a day.
- **Retail buyers** — catch drops early on the stores you resell.
- **Affiliate and content publishers** — auto-publish a weekly roundup from a run that only ever returns what is new.
- **Trend watchers** — watch ten stores in a category and see what they all start stocking.

### Common uses

- **Competitor launch alerts** — wire the dataset to Slack or email via an Apify webhook and know within a day.
- **Trend spotting** — watch ten stores in a category and see what they all start stocking.
- **Retail buying** — catch drops early on stores you resell.
- **Content and affiliate sites** — auto-publish "new this week" roundups.
- **Launch archives** — accumulate a dated record of everything a brand released.

### Pricing

Pay per new product reported. **Scanning costs almost nothing** — reading a catalogue is billed at $0.00002 per run — the platform's $0.00001 minimum, once per GB, on 2 GB — and everything beyond that is charged only for the new arrivals it surfaces. On a steady daily schedule most runs report a handful of products, or none, and cost two thousandths of a cent.

### Other Actors in this family

Same engines, same billing, no account or API key on any of them.

**YouTube & video**

- [Download YouTube Subtitles in Bulk — SRT, VTT & Text](https://apify.com/gganbukim/youtube-transcript-scraper) — Bulk subtitles from videos, channels or playlists — text, SRT, VTT or RAG chunks.
- [Export YouTube Comments to CSV — Replies and Likes](https://apify.com/gganbukim/youtube-comments-scraper) — Every comment and reply thread, with likes, authors and creator flags.
- [List Every Video on a YouTube Channel — Export to CSV](https://apify.com/gganbukim/youtube-channel-scraper) — A channel's whole back catalogue plus a subscriber and RSS summary row.
- [Find YouTube Sponsors — Brand Deals, Codes & Links](https://apify.com/gganbukim/youtube-sponsorship-finder) — Which brands pay which creators, with the campaign link, the code and the timestamp.
- [YouTube Search API — Bulk Results, No Quota](https://apify.com/gganbukim/youtube-search-scraper) — Many search terms at once, every result as a row, filtered before you are billed.
- [Track Deleted YouTube Videos & Title Changes](https://apify.com/gganbukim/youtube-channel-monitor) — What a channel quietly changed: deleted videos, rewritten titles, view velocity.
- [YouTube Creator Email Finder & Sponsor Lookup](https://apify.com/gganbukim/youtube-creator-leads) — A channel list into leads: the published email, audience bands, and who already sponsors them.
- [Export a YouTube Playlist to CSV — Every Video](https://apify.com/gganbukim/youtube-playlist-scraper) — Any playlist as a table, with each video position in it.

**Search demand**

- [AnswerThePublic Alternative — Autocomplete Keyword API](https://apify.com/gganbukim/long-tail-keyword-scraper) — One seed into hundreds of real keywords from Google, YouTube and Amazon autocomplete.
- [Google Trends API — Today's Trending Searches, No Key](https://apify.com/gganbukim/google-trends-scraper) — Today's trending searches by country, with traffic bands and the news behind them.

**E-commerce**

- [Export Any Shopify Store's Products to CSV or JSON](https://apify.com/gganbukim/shopify-product-scraper) — Any Shopify catalogue: variants, SKUs, live prices, stock, images, collections.

**Hiring**

- [Greenhouse, Lever & Ashby Job Scraper — No API Key](https://apify.com/gganbukim/ats-job-scraper) — Paste a company domain, get its open roles from Greenhouse, Ashby, Lever or SmartRecruiters.
- [Ghost Job Detector — Track Reposts, Closures & Edits](https://apify.com/gganbukim/job-lifecycle-monitor) — What changed on a careers page: opened, closed, quietly reposted, or a ghost job.

### FAQ

**Will I get blocked or rate-limited?** It reads `/products.json`, the endpoint Shopify serves on every shop, on cheap datacenter proxies. Monitoring the same stores daily does not change that — the endpoint is built to be polled, and no login is involved.

**Will the first run report everything?** Yes — on the first run every product inside your date window is new to it. After that it only reports genuine arrivals. Set a small `withinDays` for the first run if you want a quiet start.

**What if a run is interrupted?** Only products actually reported are remembered, so the rest come through on the next run instead of being lost.

**Can I watch many stores?** Yes, in one run. Each store's history is tracked separately.

**Does it detect price changes too?** No — this one is about new products. Use the Shopify Store Scraper on a schedule and diff the results for price tracking.

**Can I run it on a schedule?** That is the point. Apify Schedules, webhooks, or the API. Also available over MCP for AI agents.

**Is it legal to monitor a competitor's Shopify store?** This reads the public
`/products.json` endpoint Shopify serves on every storefront — no login, nothing
bypassed. What a shop lists for sale is public commercial fact, and watching a competitor's
public catalogue is ordinary market research. Each store's own terms are a separate
contract question. Not legal advice.

**How much does 1,000 new products cost?** $2.00, plus $0.00002 for the run. **Scanning is
free** — you are billed only for genuinely new arrivals, so a daily watch on a quiet store
costs almost nothing.

**Can I export the results to Excel or Google Sheets?** Yes. Every run's dataset
downloads as CSV, Excel, JSON, XML or RSS from the Storage tab, or straight from the API
if you want a live link a spreadsheet can pull.

**Can I connect it to Zapier, Make or n8n?** Yes — Apify publishes integrations for all
three, plus webhooks that fire when a run finishes. A common setup is a schedule here and
a webhook into your own database or Slack.

**Do I need to write code?** No. Fill the form in the console and press Start. If you do
want code, the Apify client libraries for Python and JavaScript call this the same way,
and it is available over MCP so an AI agent can call it directly.

# Actor input Schema

## `storeUrls` (type: `array`):

Bare domains or any URL on the store. Watch as many competitors as you like in one scheduled run.

## `withinDays` (type: `integer`):

Products older than this are ignored. For a daily schedule, 7 is a sensible window — it covers a missed run without flooding you.

## `dateField` (type: `string`):

published\_at is when the store made it visible to shoppers. created\_at is when it was first added, which can be much earlier for planned drops.

## `onlyUnseen` (type: `boolean`):

Remembers reported product IDs between runs, so a schedule alerts you once per product. Turn off to always emit everything in the window.

## `memoryStoreName` (type: `string`):

Named key-value store holding the IDs already reported. Change it to run two independent watchlists, or clear that store in the Console to start alerting from scratch.

## `onSaleOnly` (type: `boolean`):

Narrow to launches that arrived with a compare-at markdown.

## `maxProductsScanned` (type: `integer`):

The catalogue is read to find recent items. Raise for very large stores, lower to cut cost. You are only billed for the new products reported, never for scanning.

## `concurrency` (type: `integer`):

Stores processed in parallel. Raise it when watching many competitors at once.

## `proxyConfiguration` (type: `object`):

Leave the default.

## Actor input object example

```json
{
  "storeUrls": [
    "gymshark.com"
  ],
  "withinDays": 30,
  "dateField": "published_at",
  "onlyUnseen": true,
  "memoryStoreName": "shopify-new-arrivals-seen",
  "onSaleOnly": false,
  "maxProductsScanned": 2000,
  "concurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

One row per product first seen inside your window, newest first.

## `runSummary` (type: `string`):

Counts for this run: rows delivered, rows filtered, items that failed, the proxy tier used, and whether the run stopped at its charge limit.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "storeUrls": [
        "gymshark.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("gganbukim/shopify-new-arrivals-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "storeUrls": ["gymshark.com"] }

# Run the Actor and wait for it to finish
run = client.actor("gganbukim/shopify-new-arrivals-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "storeUrls": [
    "gymshark.com"
  ]
}' |
apify call gganbukim/shopify-new-arrivals-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,gganbukim/shopify-new-arrivals-monitor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/MZ4dAULHjcOXcQ0Bd/builds/rKUJJPN5wjG30IeTX/openapi.json
