# Shopify Product & Price Monitor (`highbrow_qualification_z7w/shopify-product-price-monitor`) Actor

Monitor public Shopify catalogs over time. Detect product launches and removals, price and discount changes, stock updates, variants, and content changes using persistent baselines. Export structured results or add concise AI competitor insights only when changes occur.

- **URL**: https://apify.com/highbrow\_qualification\_z7w/shopify-product-price-monitor.md
- **Developed by:** [Roman Bublyk](https://apify.com/highbrow_qualification_z7w) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 product results

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Shopify Product & Price Monitor

Monitor public Shopify catalogs for product launches and removals, price and discount changes, stock status, variants, and product-content updates. Run deterministic monitoring on its own or add a concise AI competitive-intelligence report.

### What it does

For every store, the Actor:

1. Reads the public Shopify catalog endpoint.
2. Normalizes products and variants.
3. Compares the current catalog with the persistent snapshot from the previous run.
4. Returns deterministic change records.
5. Optionally asks an LLM to summarize only the detected changes.
6. Saves the current snapshot for the next run.

The first run establishes a baseline. Change detection starts with the second run.

### Changes detected

- `NEW_PRODUCT` and `REMOVED_PRODUCT`
- `PRICE_INCREASE` and `PRICE_DECREASE`
- `DISCOUNT_STARTED` and `DISCOUNT_ENDED`
- `BACK_IN_STOCK` and `OUT_OF_STOCK`
- `NEW_VARIANT` and `REMOVED_VARIANT`
- `CONTENT_CHANGED` for title, handle, vendor, product type, or tags

### Input

```json
{
  "storeUrls": ["https://colourpop.com"],
  "mode": "data",
  "maxProductsPerStore": 100,
  "aiLanguage": "English"
}
```

| Field | Type | Description |
|---|---|---|
| `storeUrls` | string\[] | One to 20 public Shopify storefront URLs. |
| `mode` | `data` or `ai` | Deterministic results only, or deterministic results plus an AI report when changes exist. |
| `maxProductsPerStore` | integer | Maximum products collected per store, from 1 to 50,000. Use the same value on recurring runs. |
| `aiLanguage` | string | Language of the optional AI report. |

AI token safeguards are fixed internally at the benchmark-validated ceilings of 5,000 input tokens and 800 output tokens per store report.

### Output

The default dataset can contain four record types:

- `product` — normalized product and variant data.
- `change-summary` — deterministic changes and the observation window.
- `ai-insight` — optional AI report and token/cost telemetry.
- `store-error` — a store-specific error that does not prevent other input stores from being processed.

Example change summary:

```json
{
  "recordType": "change-summary",
  "storeUrl": "https://colourpop.com",
  "status": "ok",
  "isBaseline": false,
  "productCount": 100,
  "observationStart": "2026-09-20T19:35:42.000Z",
  "observationEnd": "2026-09-20T19:37:39.000Z",
  "changeCount": 1,
  "changes": [
    {
      "type": "PRICE_DECREASE",
      "productId": "123",
      "productTitle": "Example product",
      "variantId": "456",
      "before": 29.99,
      "after": 19.99
    }
  ]
}
```

### AI mode

AI mode never replaces deterministic comparison. The model receives:

- exact aggregate counts calculated from the complete change set;
- a stratified sample of detailed changes that fits the internal token budget;
- the real observation window when it is available.

The report is limited to 250 words and includes an executive summary, event-volume facts, uncertainties, and recommended monitoring actions. If no changes are detected, no LLM request is made and no AI event is charged.

The `aiUsage` object reports model name, input/output/reasoning tokens, included and original change counts, truncation, completion status, and estimated provider cost.

### Recurring monitoring

Want a ready-to-run example? Open the public [ColourPop Daily Product & Price Monitor](https://apify.com/highbrow_qualification_z7w/shopify-product-price-monitor/examples/colourpop-daily-product-price-monitor) Task. It monitors up to 100 products in data mode and can be copied to your Apify account before changing the store, limits, or schedule.

For reliable comparisons:

1. Create an Apify Task with fixed store URLs and `maxProductsPerStore`.
2. Run it once to create the baseline.
3. Add an hourly, daily, or weekly schedule.
4. Read `change-summary`, or connect dataset/webhook integrations.

Changing `maxProductsPerStore` resets the store baseline for that run. This prevents artificial new/removed product events when the monitored catalog scope changes.

### API

Apify automatically generates actor-specific API examples in the Console **API** tab. Replace `YOUR_APIFY_TOKEN` and IDs returned by the API where shown.

#### REST API

Start an asynchronous Actor run:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/highbrow_qualification_z7w~shopify-product-price-monitor/runs" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "storeUrls": ["https://colourpop.com"],
    "mode": "data",
    "maxProductsPerStore": 100,
    "aiLanguage": "English"
  }'
```

The response contains the run object in `data`. After the run succeeds, read `data.defaultDatasetId` and download its records:

```bash
curl \
  "https://api.apify.com/v2/datasets/DATASET_ID/items?clean=true&format=json" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN"
```

#### JavaScript client

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('highbrow_qualification_z7w/shopify-product-price-monitor').call({
  storeUrls: ['https://colourpop.com'],
  mode: 'data',
  maxProductsPerStore: 100,
  aiLanguage: 'English',
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
const summary = items.find((item) => item.recordType === 'change-summary');
console.log(summary);
```

#### Python client

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("highbrow_qualification_z7w/shopify-product-price-monitor").call(run_input={
    "storeUrls": ["https://colourpop.com"],
    "mode": "data",
    "maxProductsPerStore": 100,
    "aiLanguage": "English",
})

items = client.dataset(run["defaultDatasetId"]).list_items().items
summary = next((item for item in items if item["recordType"] == "change-summary"), None)
print(summary)
```

#### Ready-made ColourPop Task

After copying the [public Task](https://apify.com/highbrow_qualification_z7w/shopify-product-price-monitor/examples/colourpop-daily-product-price-monitor) to your account, start your copy through its **API** tab. Apify will provide the exact task ID and a token-ready REST, JavaScript, or Python example. A Task keeps the monitoring input stable between runs, which is recommended for meaningful comparisons.

#### Stateful API behavior

- A first call for a store creates its baseline; it does not report historical changes.
- Repeated calls compare against the most recently saved snapshot for the same store.
- Keep `maxProductsPerStore` stable between calls for uninterrupted change history. If it changes, the next call safely establishes a new baseline.
- Use an Apify Task for recurring API/scheduled monitoring so the input remains consistent.
- A successful run can still contain `store-error` records for individual URLs; inspect the dataset rather than relying only on the run status.

### Limits and expected errors

- The store must expose a public Shopify `/products.json` catalog endpoint.
- Password-protected stores, non-Shopify sites, blocked endpoints, or storefronts with custom access controls can return `store-error`.
- Prices are returned as exposed by Shopify; the public catalog response does not always include an explicit currency code.
- `CONTENT_CHANGED` identifies that monitored product metadata changed, not which individual metadata field changed.
- The Actor reports catalog observations. It cannot establish sales, demand, revenue, margin, or business intent without those data sources.

### Charging events

- `product-result` — one successfully normalized product record.
- `ai-store-insight` — one completed AI insight for one store and run.

Event prices are configured in Apify Monetization. AI is charged only after a visible AI result has been produced.

### Privacy

The Actor processes public storefront catalog data. Input URLs, snapshots, results, and errors are stored in the Apify storage associated with the run and monitoring workflow. Do not submit credentials or private storefront data in the input.

### Technical validation

- Deterministic diff behavior is covered by automated tests.
- Shopify pagination and short-response retries are covered by automated tests.
- Persistent snapshots include observation timestamps and remain backward-compatible with the earlier snapshot format.
- LLM volume benchmarks were completed for 10, 100, 1,000, and 10,000 changes.
- At 1,000–10,000 changes, the bounded AI request remained near 4,000 total tokens while retaining exact full-feed aggregates.

# Actor input Schema

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

One or more public Shopify storefront URLs.

## `mode` (type: `string`):

Data returns deterministic changes. AI adds an evidence-based summary.

## `maxProductsPerStore` (type: `integer`):

Stop after this many products have been collected from each store.

## `aiLanguage` (type: `string`):

Language used for the optional AI insight report.

## Actor input object example

```json
{
  "storeUrls": [
    "https://colourpop.com"
  ],
  "mode": "data",
  "maxProductsPerStore": 100,
  "aiLanguage": "English"
}
```

# Actor output Schema

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

Normalized products, deterministic change summaries, optional AI insights, and store-specific errors from this run.

# 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": [
        "https://colourpop.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("highbrow_qualification_z7w/shopify-product-price-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": ["https://colourpop.com"] }

# Run the Actor and wait for it to finish
run = client.actor("highbrow_qualification_z7w/shopify-product-price-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": [
    "https://colourpop.com"
  ]
}' |
apify call highbrow_qualification_z7w/shopify-product-price-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,highbrow_qualification_z7w/shopify-product-price-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/f7C1qYZUu0FedJHI4/builds/GJt5kbj1MP09mHaq1/openapi.json
