# E-commerce Assortment Monitor — Catalog Changes (`egeusta/ecommerce-assortment-change-monitor`) Actor

Compare recurring product datasets and detect additions, removals, price and stock changes, discounts, and variant changes with persistent baselines and a stable event taxonomy.

- **URL**: https://apify.com/egeusta/ecommerce-assortment-change-monitor.md
- **Developed by:** [Ege Usta](https://apify.com/egeusta) (community)
- **Categories:** E-commerce, Automation
- **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 compareds

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?

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

## E-commerce Assortment Change Monitor

Convert recurring catalog snapshots into stable, event-level assortment intelligence. Use products pasted directly or read any compatible Apify dataset—such as the output of Product Data Extractor, a marketplace scraper, or an internal feed Actor.

### Event taxonomy

- `PRODUCT_ADDED` / `PRODUCT_REMOVED`
- `PRICE_INCREASED` / `PRICE_DECREASED`
- `OUT_OF_STOCK` / `BACK_IN_STOCK`
- `DISCOUNT_STARTED` / `DISCOUNT_ENDED`
- `VARIANT_ADDED` / `VARIANT_REMOVED`

The first complete run creates a persistent baseline for `monitorKey`. Reusing the same key on a schedule compares the new catalog with that baseline, emits events, and saves the new state. If a charge limit interrupts the catalog, the Actor does not overwrite the last complete baseline.

### Quick start

```json
{
  "monitorKey": "demo-store-us",
  "products": [
    { "sku": "SKU-100", "name": "Trail Shoe", "price": 89.99, "listPrice": 109.99, "inStock": true, "variants": ["black-42"] }
  ]
}
```

On the next run, change the price, stock, variants, or product set while keeping the same `monitorKey`.

### Pricing

The intended pricing is pay per product compared, with platform usage included. Change events, baseline rows, and the run summary are included. Current exact prices appear on the Store page. A full, unmodified baseline is preserved when the run's maximum charge is too low.

### Limitations

This Actor compares structured product records; it does not scrape storefronts itself. Product identity is only as stable as the supplied `monitorKey`, ID, SKU, GTIN, URL, or name. Renamed products without a stable ID can look removed and re-added. Currency conversion is not performed. Availability and variant shapes vary by upstream Actor and should be checked during the first run.

No private/authenticated scraping, CAPTCHA bypass, personal-data profiling, outreach, or credentials are used.

# Actor input Schema

## `monitorKey` (type: `string`):

Stable identifier for this catalog, such as acme-us. Reuse it on every scheduled run.

## `products` (type: `array`):

Paste products or use datasetId. Common id, SKU, GTIN, URL, price, availability, and variant aliases are normalized.

## `datasetId` (type: `string`):

Read products from an accessible dataset. Ignored when pasted products are present.

## `maxProducts` (type: `integer`):

Hard cap on catalog records compared in one run.

## `includeCurrentSnapshot` (type: `boolean`):

Useful for exports; leave off for compact scheduled change feeds.

## `resetBaseline` (type: `boolean`):

Replace stored state without comparing it. Use after intentional catalog migrations.

## Actor input object example

```json
{
  "monitorKey": "demo-store-us",
  "products": [
    {
      "sku": "SKU-100",
      "name": "Trail Shoe",
      "price": 89.99,
      "listPrice": 109.99,
      "currency": "USD",
      "inStock": true,
      "variants": [
        "black-42",
        "blue-42"
      ]
    },
    {
      "sku": "SKU-200",
      "name": "City Backpack",
      "price": 59,
      "currency": "USD",
      "inStock": true
    }
  ],
  "maxProducts": 1000,
  "includeCurrentSnapshot": false,
  "resetBaseline": false
}
```

# Actor output Schema

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

No description

# 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 = {
    "monitorKey": "demo-store-us",
    "products": [
        {
            "sku": "SKU-100",
            "name": "Trail Shoe",
            "price": 89.99,
            "listPrice": 109.99,
            "currency": "USD",
            "inStock": true,
            "variants": [
                "black-42",
                "blue-42"
            ]
        },
        {
            "sku": "SKU-200",
            "name": "City Backpack",
            "price": 59,
            "currency": "USD",
            "inStock": true
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("egeusta/ecommerce-assortment-change-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 = {
    "monitorKey": "demo-store-us",
    "products": [
        {
            "sku": "SKU-100",
            "name": "Trail Shoe",
            "price": 89.99,
            "listPrice": 109.99,
            "currency": "USD",
            "inStock": True,
            "variants": [
                "black-42",
                "blue-42",
            ],
        },
        {
            "sku": "SKU-200",
            "name": "City Backpack",
            "price": 59,
            "currency": "USD",
            "inStock": True,
        },
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("egeusta/ecommerce-assortment-change-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 '{
  "monitorKey": "demo-store-us",
  "products": [
    {
      "sku": "SKU-100",
      "name": "Trail Shoe",
      "price": 89.99,
      "listPrice": 109.99,
      "currency": "USD",
      "inStock": true,
      "variants": [
        "black-42",
        "blue-42"
      ]
    },
    {
      "sku": "SKU-200",
      "name": "City Backpack",
      "price": 59,
      "currency": "USD",
      "inStock": true
    }
  ]
}' |
apify call egeusta/ecommerce-assortment-change-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,egeusta/ecommerce-assortment-change-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/cobDtC3aeVxyGOSmo/builds/SSbkpZZMPb4ETsmyr/openapi.json
