# Shopify Product Change Tracker (`foo121/shopify-change-events`) Actor

Monitor any Shopify store for new/removed products, price changes and inventory (in/out of stock) — emitted as structured, webhook-ready change-events. Built for scheduled runs. Pay per result.

- **URL**: https://apify.com/foo121/shopify-change-events.md
- **Developed by:** [ziv shay](https://apify.com/foo121) (community)
- **Categories:** E-commerce, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 result items

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 Product Change Tracker

**Monitor any Shopify store and get a clean, machine-consumable feed of *change-events*** — new products, removed products, price changes, and inventory (in/out of stock) flips. Built for scheduled runs + webhooks. Pay per result.

Price-tracking dashboards (Prisync and friends) show you a *screen*. They don't hand a developer the raw event feed. This actor emits **one row per discrete change**, in exactly the shape an automation needs:

- `product_added` / `product_removed`
- `price_changed` (with `oldPrice`, `newPrice`, `priceDelta`, `pctChange`, `direction`)
- `came_in_stock` / `went_out_of_stock`
- `compare_at_changed` (sale started/ended; `nowOnSale`)
- `title_changed`

### How it works

- Reads the store's **public `/products.json`** endpoint (no login, no anti-bot) across all catalog pages.
- Compares the catalog to the **previous scheduled run** (state persists in a named Key-Value store between runs).
- Emits only the changes since last run. On the first run it stores a baseline silently (or, optionally, emits the whole catalog as `first_seen`).

### Why it's different

- **Event feed, not a dashboard.** Every row is a single actionable change with before/after fields — ready for a webhook, Slack alert, reprice bot, or drop-watcher.
- **Built on the proven Shopify `/products.json` scraper** with a real diff layer on top.
- **In/out-of-stock detection per variant** — catch restocks and sellouts the moment they happen.

### Input

| Field | Type | Description |
|---|---|---|
| `domains` | array | Shopify store domains/URLs to monitor (e.g. `allbirds.com`). |
| `watch` | array | Which change types to emit: `added`, `removed`, `price`, `inventory`, `compareAt`, `title` (default: all). |
| `emitFirstSnapshot` | boolean | Emit the full catalog as `first_seen` on the first run (default off → first run is a silent baseline). |
| `maxPagesPerStore` | integer | Catalog pages per store (250 products/page). |
| `proxyConfiguration` | object | Apify proxy (recommended). |

#### Example input

```json
{
  "domains": ["aquariumcoop.com", "allbirds.com"],
  "watch": ["price", "inventory", "added"]
}
```

### Output

```json
{
  "shop": "aquariumcoop.com",
  "eventType": "price_changed",
  "productTitle": "Easy Green All-In-One Fertilizer",
  "variantTitle": "8 oz Pump Bottle",
  "sku": "EG-8OZ",
  "oldPrice": "14.99",
  "newPrice": "12.99",
  "priceDelta": -2,
  "pctChange": -13.34,
  "direction": "down",
  "url": "https://aquariumcoop.com/products/easy-green",
  "detectedAt": "2026-06-21T13:40:00.000Z"
}
```

```json
{
  "shop": "aquariumcoop.com",
  "eventType": "came_in_stock",
  "productTitle": "Fluval 307 Canister Filter",
  "variantTitle": "Default",
  "available": true,
  "price": "189.99",
  "url": "https://aquariumcoop.com/products/fluval-307",
  "detectedAt": "2026-06-21T13:40:00.000Z"
}
```

### Schedule + webhook

1. **Schedule** the actor (hourly/daily). The first run stores a baseline; from the second run on, every run emits the changes since the last.
2. Add an Apify **webhook** on *run succeeded* → your endpoint receives the new change-events. Filter by `eventType`.

### Pricing

Pay per result — charged per change-event row. Steady-state monitoring of a stable catalog is cheap (no changes → no rows). Turn on `emitFirstSnapshot` only if you want the initial catalog billed as events.

***

*Built by MoneyMachine. Public `/products.json` data only; respect each store's terms.*

# Actor input Schema

## `domains` (type: `array`):

Store domains or URLs to monitor, e.g. allbirds.com or https://shop.example.com. Each is read via its public /products.json endpoint (no login). Run on a schedule; each run emits the changes since the previous run.

## `watch` (type: `array`):

Which kinds of change-events to emit. Defaults to all: added (new products), removed, price (variant price changes), inventory (in/out of stock), compareAt (sale-price changes), title (renames).

## `emitFirstSnapshot` (type: `boolean`):

On the very first run for a store there is no prior snapshot to diff. If on, the whole catalog is emitted as `first_seen` events (you pay per product). If off (default), the first run only stores a baseline and emits nothing — changes start from the second run.

## `maxPagesPerStore` (type: `integer`):

Each page is 250 products. 50 pages = up to 12,500 products.

## `requestTimeoutSecs` (type: `integer`):

Abort a single page fetch after this many seconds.

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

Proxy for outbound requests. Apify proxy recommended to spread requests across scheduled runs.

## Actor input object example

```json
{
  "domains": [
    "aquariumcoop.com"
  ],
  "watch": [
    "added",
    "removed",
    "price",
    "inventory",
    "compareAt",
    "title"
  ],
  "emitFirstSnapshot": false,
  "maxPagesPerStore": 50,
  "requestTimeoutSecs": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "domains": [
        "aquariumcoop.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("foo121/shopify-change-events").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 = { "domains": ["aquariumcoop.com"] }

# Run the Actor and wait for it to finish
run = client.actor("foo121/shopify-change-events").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "domains": [
    "aquariumcoop.com"
  ]
}' |
apify call foo121/shopify-change-events --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=foo121/shopify-change-events",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/E9PMXcfnhchLKYBAC/builds/RSvA9yPpUZ2EZGX2K/openapi.json
