# CTA Destination Regression Monitor (`prolific_hoopoe/cta-destination-regression-monitor`) Actor

Monitor public signup, checkout, pricing, and demo CTA destinations without clicking controls or submitting forms.

- **URL**: https://apify.com/prolific\_hoopoe/cta-destination-regression-monitor.md
- **Developed by:** [Bassem Hakim](https://apify.com/prolific_hoopoe) (community)
- **Categories:** Automation, Developer tools, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.10 / completed watch check

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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## CTA Destination Regression Monitor — Signup, Checkout & Demo Links

Monitor the declared destinations of visible, English-language commercial calls to action on one public page. The Actor establishes an accepted baseline, runs safely on an Apify schedule, and reports removed or disabled controls, placeholders, missing fragments, changed destinations, and bounded HTTP failures.

**This Actor does not click controls, submit forms, log in, purchase anything, or verify that a checkout or signup completes.** It monitors the public CTA and destination layer only.

### Buyer workflow

1. Run `discover` with a public URL and a stable `watchId`.
2. Review every detected CTA in `observedCtas`.
3. Run `lock_baseline` explicitly with the same URL and `watchId`.
4. Save a new Apify Task with `mode` set to `check`.
5. schedule the Task daily or weekly without overlapping runs.
6. Route dataset results through an Apify-native webhook or integration if alerts are needed.

The first baseline run never emits a regression. A baseline is never learned or changed automatically. Replacing one requires `replace_baseline` plus the exact current baseline hash.

### What counts as an alert

The default requires the same conclusive change in two consecutive checks. This prevents a single transient failure from being called confirmed.

- `confirmed_regression`: a removed or disabled CTA, placeholder target, changed declared destination, missing fragment, or completed 4xx/5xx route probe persisted for the configured confirmation count.
- `recovered`: every monitored dimension returned to the locked baseline for the configured confirmation count.
- `inconclusive`: an access challenge, duplicate semantic CTA label, timeout, rate limit, probe failure, route cap, robots/nofollow skip, or incomplete removal evidence. Inconclusive runs never close an open incident.

CTA identity uses normalized intent and label, never the destination or DOM position. Destination changes therefore remain attached to the same CTA. If duplicate normalized labels make that identity ambiguous, the Actor reports `inconclusive` instead of inventing a match.

### State and billing safety

- Persistent state lives in the caller's named `revenuepath-watch-state` key-value store. Normal Apify users therefore keep isolated state under limited Actor permissions.
- The URL and `watchId` are hashed into the record namespace; one watch cannot read another watch's pointer.
- Each state revision is immutable behind a small pointer record.
- The PPE event is `completed-watch-check`. Production code verifies that the event is registered and that one event remains within the caller's limit before scanning.
- The result is pushed and its event accepted before state advances. A rejected charge performs no state write.
- Apify key-value storage has no atomic compare-and-swap. Pre- and post-charge revision checks reduce overlap races, but exactly-once alerts cannot be promised. Keep schedules non-overlapping; a crash or final write race can repeat an alert.
- x402 and Skyfire calls should be treated as one-shot checks unless the caller supplies a durable normal Apify identity and schedule.

The Store price is `$0.10` for one accepted `completed-watch-check` event, plus a one-time `$0.00005` Actor Start event per run. Platform usage is not separately passed through to the user.

### Safety boundary

The scanner accepts public HTTP/HTTPS targets on ports 80/443, rejects credentials and private/reserved network addresses, pins resolved addresses for direct probes, honors robots rules, blocks non-GET/HEAD browser traffic, and limits routes, bytes, redirects, and runtime. It does not claim lost revenue, full transaction coverage, or security-vulnerability detection.

### Local verification

```bash
npm test
````

The suite covers browser extraction, full healthy inventory capture, explicit baseline locking, six controlled regression classes, transient suppression, recovery, inconclusive handling, ten unchanged page variants across three repetitions, semantic identity, duplicate ambiguity, URL/watch isolation, stale-writer rejection, PPE registration, charge-before-state ordering, and pre/post-charge conflict behavior.

# Actor input Schema

## `url` (type: `string`):

A public HTTP or HTTPS page on standard port 80 or 443.

## `watchId` (type: `string`):

A stable 1-64 character identifier. Reuse it with the exact URL for every scheduled check.

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

Discover without state, explicitly lock a first baseline, check it, or explicitly replace it with the current baseline hash.

## `expectedBaselineHash` (type: `string`):

Required only for replace\_baseline. Copy the exact baselineHash from a prior result.

## `confirmationRuns` (type: `integer`):

Matching conclusive checks required before a regression or recovery alert.

## `maxRoutes` (type: `integer`):

Maximum commercial same-origin GET destinations to probe.

## `maxCtas` (type: `integer`):

Maximum visible commercial controls included in one bounded scan.

## `timeoutSeconds` (type: `integer`):

Timeout for each bounded navigation or probe.

## Actor input object example

```json
{
  "url": "https://example.com",
  "watchId": "primary-funnel",
  "mode": "discover",
  "confirmationRuns": 2,
  "maxRoutes": 6,
  "maxCtas": 30,
  "timeoutSeconds": 15
}
```

# Actor output Schema

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

The structured result 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("prolific_hoopoe/cta-destination-regression-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("prolific_hoopoe/cta-destination-regression-monitor").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 '{}' |
apify call prolific_hoopoe/cta-destination-regression-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=prolific_hoopoe/cta-destination-regression-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "CTA Destination Regression Monitor",
        "description": "Monitor public signup, checkout, pricing, and demo CTA destinations without clicking controls or submitting forms.",
        "version": "0.1",
        "x-build-id": "kn5J9QGJprhxs3MQi"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/prolific_hoopoe~cta-destination-regression-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-prolific_hoopoe-cta-destination-regression-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/prolific_hoopoe~cta-destination-regression-monitor/runs": {
            "post": {
                "operationId": "runs-sync-prolific_hoopoe-cta-destination-regression-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/prolific_hoopoe~cta-destination-regression-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-prolific_hoopoe-cta-destination-regression-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "url",
                    "watchId",
                    "mode"
                ],
                "properties": {
                    "url": {
                        "title": "Public page URL",
                        "type": "string",
                        "description": "A public HTTP or HTTPS page on standard port 80 or 443.",
                        "default": "https://example.com"
                    },
                    "watchId": {
                        "title": "Watch ID",
                        "pattern": "^[A-Za-z0-9._-]{1,64}$",
                        "type": "string",
                        "description": "A stable 1-64 character identifier. Reuse it with the exact URL for every scheduled check.",
                        "default": "primary-funnel"
                    },
                    "mode": {
                        "title": "Operation",
                        "enum": [
                            "discover",
                            "lock_baseline",
                            "check",
                            "replace_baseline"
                        ],
                        "type": "string",
                        "description": "Discover without state, explicitly lock a first baseline, check it, or explicitly replace it with the current baseline hash.",
                        "default": "discover"
                    },
                    "expectedBaselineHash": {
                        "title": "Current baseline hash",
                        "type": "string",
                        "description": "Required only for replace_baseline. Copy the exact baselineHash from a prior result."
                    },
                    "confirmationRuns": {
                        "title": "Consecutive confirmations",
                        "minimum": 2,
                        "maximum": 3,
                        "type": "integer",
                        "description": "Matching conclusive checks required before a regression or recovery alert.",
                        "default": 2
                    },
                    "maxRoutes": {
                        "title": "Maximum same-origin routes",
                        "minimum": 0,
                        "maximum": 6,
                        "type": "integer",
                        "description": "Maximum commercial same-origin GET destinations to probe.",
                        "default": 6
                    },
                    "maxCtas": {
                        "title": "Maximum CTAs",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Maximum visible commercial controls included in one bounded scan.",
                        "default": 30
                    },
                    "timeoutSeconds": {
                        "title": "Navigation timeout",
                        "minimum": 5,
                        "maximum": 30,
                        "type": "integer",
                        "description": "Timeout for each bounded navigation or probe.",
                        "default": 15
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
