# B2B Competitor Monitor — Website Change Tracking (AI) (`fuze/b2b-competitor-monitor`) Actor

Watch competitor pages (pricing, product, homepage, blog) and get an AI summary of exactly what changed and why it matters between runs. Schedule it for always-on competitive intelligence.

- **URL**: https://apify.com/fuze/b2b-competitor-monitor.md
- **Developed by:** [Fredrik Hansson](https://apify.com/fuze) (community)
- **Categories:** AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $44.00 / 1,000 page checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## B2B Competitor Monitor — Website Change Tracking (AI)

**Know the moment a competitor changes their pricing, launches a feature, or rewrites their pitch.** This Actor watches a list of competitor pages — pricing, product, homepage, blog — and on every run it fetches each page, compares it to the last stored snapshot, and uses OpenAI to tell you **exactly what changed and why it matters**. Point it at your rivals, put it on a schedule, and turn "did something change?" into a ready-to-read competitive-intelligence feed.

You bring the URLs. It hands back a changelog of your competition.

![B2B Competitor Monitor — Website Change Tracking (AI) — input and sample output](https://datatools-hub.vercel.app/actor-shots/b2b-competitor-monitor.png)

### 🔗 Chain it after your scraper

Already building company lists with **[Google Maps Scraper (`compass/crawler-google-places`)](https://apify.com/compass/crawler-google-places)**, **[LinkedIn Company Details Scraper (`harvestapi/linkedin-company`)](https://apify.com/harvestapi/linkedin-company)** or **[Shopify Store Leads Scraper (`clearpath/shopify-store-leads`)](https://apify.com/clearpath/shopify-store-leads)**? Pipe the dataset straight in — paste its dataset ID (via the Integrations tab) and put the whole list on a schedule to get an AI "what changed & why it matters" feed. Works with any Maps, LinkedIn or company scraper's output.

### Quick start

1. **Fill in the input** — set the fields in the input tab (prefilled with a working example).
2. **Click Start** — the Actor runs and writes one record per item to the dataset.
3. **Get your data** — export to **JSON, CSV or Excel**, or pull it via the API.

***

### The flow

```
   urls              fetch each         diff vs. last          AI: "what changed"
 (pricing,     →     page & clean   →   stored snapshot    →   + why it matters
  product,          to text             (named KV store)       + significance
  homepage)                                                     + recommended action
```

1. **Give it competitor page URLs** — the ones you actually care about watching (pricing pages are gold).
2. **It fetches and cleans each page** to text, then compares it to the snapshot it stored the last time it ran.
3. **If nothing changed, it says so** — and skips the AI call, so you don't pay for a summary of "no change".
4. **If the page changed, AI reads the old and new text side by side** and writes a concrete summary of what moved.

Snapshots live in a **named key-value store** that persists between runs — that's what makes change tracking possible. The first run captures a **baseline**; every run after that is a real diff.

***

### What you get per page

For every URL checked, the Actor returns:

1. **`changed`** — `true` / `false`. Did the page's visible content materially change since the last run?
2. **`firstRun`** — `true` on the very first check of a URL (baseline captured, nothing to compare against yet).
3. **`changeSummary`** — a concrete description of what changed, quoting specific prices, plan names, features or wording where possible.
4. **`changeType`** — one or more of `pricing`, `product`, `feature`, `messaging`, `pricing-page`, `team`, `legal`, `other`.
5. **`significance`** — `low` / `medium` / `high`, how much this change should matter to you.
6. **`whyItMatters`** — one sentence of so-what.
7. **`recommendedAction`** — one sentence on what to do about it.
8. **`previousCheckedAt`** / **`checkedAt`** — when the last snapshot and this one were taken.

The AI layer (OpenAI `gpt-4o-mini`, a fast and low-cost model) is **only called when a change is actually detected**, so an unchanged page costs you the fetch, not a token.

***

### Three ways people use it

- **Competitive intelligence monitoring** — keep a standing watch on every rival's key pages and get a plain-English changelog instead of eyeballing sites by hand. The fastest way to **track competitor website changes** without a full-time analyst.
- **Competitor pricing change alerts** — watch pricing pages specifically (`watchFocus: "pricing"`). The moment a competitor raises prices, adds a tier, drops a discount or changes limits, you'll have the exact before/after and a note on why it matters.
- **Product launch detection** — watch product, changelog and homepage pages (`watchFocus: "product"`) to catch new features, integrations and repositioning the day they ship — before your prospects start asking about them.

***

### Run it on a schedule

**Change tracking only works if you run it repeatedly.** A single run just captures a baseline — the value is in the diff between runs.

- Snapshots are stored in the **named key-value store** set by `storeName` (default `competitor-monitor-snapshots`). That store **survives between runs**, so each run compares today's page to the last time the Actor saw it.
- Set up a recurring run with **[Apify Schedules](https://docs.apify.com/platform/schedule)** — daily or weekly is typical for pricing and product pages.
- **Keep `storeName` identical across scheduled runs.** If you change it, the Actor starts a fresh baseline. Use different store names only when you want to track separate, independent watch lists.

Baseline on day one → real "what changed" reports every run after that.

***

### Input

| Field | Type | Notes |
|---|---|---|
| `urls` | array | Competitor page URLs to watch (pricing, product, homepage, blog). One per line. |
| `storeName` | string | Named key-value store that persists snapshots across runs. Default `competitor-monitor-snapshots`. Keep it the same between scheduled runs. |
| `watchFocus` | string | Focus the AI summary: `full` (default), `pricing`, `product`, or `messaging`. |
| `maxResults` | integer | Cap how many URLs to check per run. Default `100`. |
| `maxConcurrency` | integer | URLs fetched in parallel. Default `5`. |
| `model` | string | Override the OpenAI model. Default `gpt-4o-mini`. |

#### Minimal input example

```json
{
  "urls": [
    "https://linear.app/pricing",
    "https://www.notion.so/pricing"
  ],
  "storeName": "competitor-monitor-snapshots",
  "watchFocus": "pricing"
}
```

***

### Output example

A first run captures baselines; later runs report real changes. A dataset might look like this:

```json
[
  {
    "url": "https://www.notion.so/pricing",
    "domain": "notion.so",
    "firstRun": true,
    "changed": false,
    "changeSummary": "Baseline captured — first time this URL was monitored.",
    "changeType": [],
    "significance": null,
    "whyItMatters": null,
    "recommendedAction": null,
    "previousCheckedAt": null,
    "checkedAt": "2026-10-10T08:00:00.000Z"
  },
  {
    "url": "https://linear.app/pricing",
    "domain": "linear.app",
    "firstRun": false,
    "changed": true,
    "changeSummary": "The Business plan rose from $14 to $16 per user/month, and a new 'Enterprise' tier with SAML SSO and audit logs was added above it.",
    "changeType": ["pricing", "pricing-page", "feature"],
    "significance": "high",
    "whyItMatters": "A competitor raising prices and moving upmarket opens room to position on value and win price-sensitive buyers.",
    "recommendedAction": "Update your pricing battlecard and brief sales on the new Enterprise tier before the next renewal cycle.",
    "previousCheckedAt": "2026-10-09T08:00:00.000Z",
    "checkedAt": "2026-10-10T08:00:00.000Z"
  }
]
```

When a page is unchanged, you get `changed: false` with `changeSummary: "No change since the last run."` and no AI call is made.

***

### Pay-per-event pricing

This Actor uses **pay-per-event** billing with a single event:

| Event | Charged when |
|---|---|
| `page-checked` | Once per URL fetched and compared against its previous snapshot — whether it changed or not. The AI change summary is included when the page changed. |

Price: **$0.10 per page checked.** The fetch + fingerprint comparison is the unit of work, so you're charged once per URL per run. The Actor logs its OpenAI token usage and estimated AI cost at the end of every run, so the event price stays safely above the model cost.

***

### Setup

The AI change summary calls the OpenAI API. Set the environment variable / secret **`OPENAI_API_KEY`** on the Actor. The AI is **only called when a change is detected** — baseline and unchanged pages never touch OpenAI. Without a key, changes are still flagged (`changed: true`) but left without an AI summary.

***

### Use it from an AI agent (Apify MCP server)

This Actor is available through the [Apify MCP server](https://mcp.apify.com), so AI agents (Claude, ChatGPT, or anything that speaks MCP) can call it as a tool — hand it a list of `urls` and a `storeName`, and read back a structured changelog of what moved on your competitors' pages — with no custom integration code.

***

### Run it locally

```bash
npm install
## put your input in storage/key_value_stores/default/INPUT.json
export OPENAI_API_KEY=sk-...   # enables the AI change summary
apify run -p
```

Run it twice in a row to see the baseline → diff behaviour: the first run stores snapshots, the second compares against them.

***

### Related actors

- [B2B Pricing Extractor](https://apify.com/fuze/b2b-pricing-extractor) — Pull structured pricing plans, tiers and features off any SaaS pricing page.
- [B2B Competitor Teardown](https://apify.com/fuze/b2b-competitor-teardown) — A full AI teardown of a competitor's site: positioning, product, pricing and gaps.
- [B2B Tech Stack Detector](https://apify.com/fuze/b2b-tech-stack-detector) — Detect the technologies, frameworks and tools a company's website is built on.
- [Signal Radar](https://apify.com/fuze/signal-radar) — Monitor the web for buying signals and market-moving events around companies you track.

# Actor input Schema

## `urls` (type: `array`):

Competitor page URLs to monitor for changes (pricing, product, homepage, blog). One per line. Optional if you supply a datasetId for chaining.

## `storeName` (type: `string`):

The named key-value store used to persist page snapshots across runs. Keep this the same between scheduled runs so the Actor can compare the current page to the last stored snapshot.

## `watchFocus` (type: `string`):

Focus the AI change summary on a specific aspect of the page.

## `maxResults` (type: `integer`):

Max URLs to check per run. One pay-per-event charge per URL checked.

## `maxConcurrency` (type: `integer`):

How many URLs to fetch in parallel.

## `model` (type: `string`):

Override the model (default gpt-4o-mini).

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

Optional. Read the URLs/domains from a previous Actor run's dataset — for no-code chaining via the Integrations tab.

## `datasetField` (type: `string`):

Which dataset field holds the URL/domain. Leave blank to auto-detect (url, website, domain, pageUrl, companyUrl, link).

## Actor input object example

```json
{
  "urls": [
    "https://linear.app/pricing",
    "https://www.notion.so/pricing"
  ],
  "storeName": "competitor-monitor-snapshots",
  "watchFocus": "full",
  "maxResults": 100,
  "maxConcurrency": 5
}
```

# Actor output Schema

## `changes` (type: `string`):

All change records for this run in the default dataset.

# 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 = {
    "urls": [
        "https://linear.app/pricing",
        "https://www.notion.so/pricing"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fuze/b2b-competitor-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 = { "urls": [
        "https://linear.app/pricing",
        "https://www.notion.so/pricing",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("fuze/b2b-competitor-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 '{
  "urls": [
    "https://linear.app/pricing",
    "https://www.notion.so/pricing"
  ]
}' |
apify call fuze/b2b-competitor-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fuze/b2b-competitor-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/EwkGC4iARXGhr4eEg/builds/xFcwB038MVpoZ7gFF/openapi.json
