# Agentic Commerce Readiness Index - UCP, ACP & AI-Shopping Audit (`yasaslive/agentic-commerce-radar`) Actor

Score any storefront 0-100 on how ready it is for AI shopping agents — Universal Commerce Protocol manifest, ACP product-feed conformance, structured data, AI-crawler policy — and track adoption over time. Cohort mode turns 500 merchants into an adoption curve you cannot buy retroactively.

- **URL**: https://apify.com/yasaslive/agentic-commerce-radar.md
- **Developed by:** [Eonix Pvt Ltd](https://apify.com/yasaslive) (community)
- **Categories:** AI, E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 88.9% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00005 / actor start

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

## Agentic Commerce Readiness Index — UCP, ACP & AI-Shopping Audit

**The adoption curve you cannot buy retroactively.**

The Universal Commerce Protocol went self-serve on Shopify in June 2026. Right now, every week, merchants are switching it on. Nobody is writing that down.

This actor scores any storefront 0–100 on how ready it is for AI shopping agents — and, because it snapshots every scan, it turns a merchant list into a **longitudinal dataset of protocol adoption**. Run it once and you get an audit. Run it weekly against 500 merchants and you get something that cannot be reconstructed after the fact at any price: who adopted, when, in what order, and what they turned on first.

A competitor can clone the audit in an afternoon. Nobody can clone six months of history.

***

### The lead example: audit 500 merchants, show me who switched UCP on this month

```json
{
    "domains": ["merchant1.com", "merchant2.com", "…498 more"],
    "productSampleSize": 25,
    "generateReports": false
}
```

Put that on a weekly Schedule. Every run writes `COHORT.json` and emits a typed `change` record for every merchant whose posture moved:

```
ucp_adopted              gymshark.com switched UCP on at version 2026-04-08.
capability_added         kith.com added the UCP capability dev.ucp.shopping.checkout.
payment_handler_changed  mejuri.com changed its UCP payment handlers.
ucp_version_changed      skims.com moved from UCP 2026-01-23 to 2026-04-08.
```

Read `CHANGES.json` and filter `changeType` to `ucp_adopted`. That is your answer, and it gets more valuable every week you keep the schedule running.

> Change events are in the dataset too, as `kind: "change"` rows. Reach for `CHANGES.json` when you want the changes on their own: an Apify dataset **view** selects columns without filtering rows, so the dataset's "Adoption changes" view still returns every audit row with the change columns blank.

**Auditing your own single store is the demo, not the product.** A per-store UCP validator already exists and does that job well. What this actor sells is the cohort view and the adoption deltas.

***

### What you get

| Output               | Where                                      | What it is                                                                                         |
| -------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------- |
| Per-domain audit     | dataset, `kind: "record"`                  | Full readiness profile: score, six sub-scores, raw UCP manifest, ACP feed gaps, crawler matrix     |
| Adoption changes     | dataset, `kind: "change"`                  | Typed events since the previous scan of that domain                                                |
| Product feed gaps    | dataset, `kind: "record"` with `productId` | Per-product missing-field list (opt in with `includeProductDetail`)                                |
| Run summary          | dataset, `kind: "summary"`                 | Totals, artifact URLs                                                                              |
| `CHANGES.json`       | key-value store                            | **The change feed alone** — the only output that is just changes, with counts by type              |
| `COHORT.json`        | key-value store                            | **Adoption rates by capability, payment handler, platform and version; median score; leaderboard** |
| `INDEX.json`         | key-value store                            | Every domain, sortable                                                                             |
| `REPORT-<domain>.md` | key-value store                            | Human-readable audit (opt in — see pricing)                                                        |
| `SUMMARY.json`       | key-value store                            | Same as the summary record                                                                         |
| `COST-ESTIMATE.json` | key-value store                            | What this run will cost you, written before work begins                                            |

***

### Real sample output

Copy-pasted from a real local run against `allbirds.com` on 16 August 2026. Trimmed only where marked.

```json
{
    "kind": "record",
    "target": "allbirds.com",
    "status": "ok",
    "collectedAt": "2026-08-16T18:21:15.116Z",
    "source": "agentic-commerce-radar",
    "score": 89.8,
    "grade": "A",
    "ucpPresent": true,
    "ucpVersion": "2026-04-08",
    "platform": "shopify",
    "acpReadyPct": 100,
    "subScores": {
        "ucpManifest": 30,
        "ucpCapabilityDepth": 10,
        "acpFeedConformance": 23.8,
        "structuredData": 16,
        "agentCrawlerPolicy": 10,
        "agentCard": 0
    },
    "maxScores": {
        "ucpManifest": 30,
        "ucpCapabilityDepth": 10,
        "acpFeedConformance": 25,
        "structuredData": 20,
        "agentCrawlerPolicy": 10,
        "agentCard": 5
    },
    "topFixes": [
        {
            "area": "agentCard",
            "pointsAvailable": 5,
            "action": "Publish an agent card at /.well-known/agent-card.json describing your agent-facing endpoints. Optional today, and a cheap leading signal."
        },
        {
            "area": "structuredData",
            "pointsAvailable": 4,
            "action": "Add JSON-LD Organization markup to product pages — this is how agents read a store that has no UCP manifest."
        }
    ],
    "ucp": {
        "present": true,
        "httpStatus": 200,
        "version": "2026-04-08",
        "supportedVersions": ["2026-04-08", "2026-01-23"],
        "capabilities": [
            "dev.ucp.shopping.checkout",
            "dev.ucp.shopping.fulfillment",
            "dev.ucp.shopping.discount",
            "dev.ucp.shopping.cart",
            "dev.ucp.shopping.order",
            "dev.ucp.shopping.catalog.search",
            "dev.ucp.shopping.catalog.lookup",
            "dev.shopify.catalog"
        ],
        "transports": ["mcp", "embedded"],
        "paymentHandlers": ["com.google.pay", "dev.shopify.card", "dev.shopify.shop_pay"],
        "services": [
            {
                "serviceId": "dev.ucp.shopping",
                "transport": "mcp",
                "endpoint": "https://weareallbirds.myshopify.com/api/ucp/mcp"
            },
            { "serviceId": "dev.ucp.shopping", "transport": "embedded", "endpoint": null }
        ],
        "drift": false,
        "rawManifest": "<full manifest stored verbatim — trimmed here>"
    },
    "crawlerPolicy": {
        "robotsPresent": true,
        "allowedCount": 11,
        "blockedCount": 0,
        "payPerCrawl": false,
        "policyHash": "882049824c94f373"
    },
    "feed": {
        "surface": "shopify-products-json",
        "productsSampled": 25,
        "acpReadyCount": 25,
        "acpReadyPct": 100,
        "fieldGapCounts": {},
        "seller": {
            "missingFields": ["seller_name"],
            "truncationWarnings": [],
            "sellerName": null,
            "sellerUrl": "https://allbirds.com"
        }
    },
    "structuredData": {
        "homepageBlocks": 0,
        "productBlocks": 5,
        "types": ["ProductGroup"],
        "hasProduct": true,
        "hasOffer": true,
        "hasAggregateRating": true,
        "productCompleteness": 1
    },
    "warnings": [],
    "durationMs": 2118
}
```

***

### Scoring — published weights, always with sub-scores

The total is never given without the parts. If you disagree with the weighting, recompute your own total from `subScores` without re-running the audit — that is why they are first-class output.

| Area                 | Weight | What earns it                                                                                                                                                                                |
| -------------------- | -----: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ucpManifest`        |     30 | A live, parseable manifest at `/.well-known/ucp`. Most of the weight is presence; the rest rewards a declared version, multiple supported versions, and a service with a reachable endpoint. |
| `ucpCapabilityDepth` |     10 | How much of a purchase can actually complete — coverage of catalog search/lookup, cart, checkout, fulfillment, discount, order — plus declared payment handlers.                             |
| `acpFeedConformance` |     25 | 20 for the share of sampled products carrying every required ACP field, 5 for seller-level fields.                                                                                           |
| `structuredData`     |     20 | JSON-LD Product/Offer/Organization/AggregateRating presence, weighted toward how *complete* the richest Product/Offer actually is.                                                           |
| `agentCrawlerPolicy` |     10 | Share of tracked AI crawlers permitted by `robots.txt`.                                                                                                                                      |
| `agentCard`          |      5 | A published `agent-card.json` or `ai-plugin.json`.                                                                                                                                           |

Grades: **A** ≥ 85 · **B** ≥ 70 · **C** ≥ 55 · **D** ≥ 35 · **F** < 35.

Two deliberate calls worth knowing about:

- **A pay-per-crawl posture (HTTP 402) is not scored as a block.** Charging agents for access is a legitimate commercial stance, so it costs a small deduction for friction rather than the full ten points.
- **`productSampleSize: 0` redistributes its 25 points** across the other areas instead of capping every store at 75. `maxScores` always tells you what was actually attainable. A store whose catalog genuinely cannot be read scores 0 there — an agent cannot read it either.

#### Robots.txt is a scoring input, not a product

The AI-crawler matrix lives inside the score object and nowhere else. This actor deliberately does not emit a standalone crawler-policy feed — that overlaps a site-health auditor and a dedicated crawler panel.

***

### Free plan limits

**Unmonetized runs are capped to 1 target and 5 records. Paid plans run uncapped.** Report generation is a paid feature. The run still produces a complete, real audit for that one domain, and the log says plainly what was capped.

"Unmonetized" means pay-per-event pricing is not active on the run — a local `apify run`, or an Actor with no pricing configured. Once pay-per-event pricing is live, runs are uncapped and bounded by the platform's own total-charge ceiling instead. Verify either side locally:

```bash
ACTOR_TEST_PAY_PER_EVENT=true npx tsx scripts/check-gating.ts
```

***

### What a run costs you

Prices are per event. The actor writes `COST-ESTIMATE.json` and logs a table **before any work begins**, so you never discover the bill afterwards.

| Event               |  Price | Fires                                                |
| ------------------- | -----: | ---------------------------------------------------- |
| `domain-audited`    |  $0.02 | Once per domain, after its record is pushed          |
| `manifest-parsed`   |  $0.03 | Only when a UCP manifest was found and parsed        |
| `product-validated` |  $0.02 | Per 100 products validated, rounded up, once per run |
| `store-report`      |  $2.00 | Per `REPORT.md` written — **off by default**         |
| `adoption-change`   |  $0.01 | Per change event                                     |
| `request-served`    | $0.001 | Standby requests only                                |

**Worked example — the shipped default (3 domains, 25 products each, no reports):**

```
domain-audited      3 × $0.02  = $0.06
manifest-parsed     2 × $0.03  = $0.06   (store.google.com has no manifest, so it is not charged)
product-validated   1 × $0.02  = $0.02   (50 products → 1 charge unit)
adoption-change     0 × $0.01  = $0.00   (first scan of each domain is a baseline)
                                 ------
                                  $0.14
```

**A 500-merchant cohort sweep** costs roughly `500 × $0.02` + `(adopters × $0.03)` + `~$2.50` of product validation ≈ **$13–$28 per run** depending on adoption rate. Weekly, that is a dataset for the price of lunch.

> **Reports are the one expensive event.** At $2.00 each, a 500-domain sweep with `generateReports` on bills over $1,000. It ships **off** for exactly that reason. Turn it on for the handful of merchants you want a document for, not for a sweep.

Things you are never charged for: unreachable domains, domains with no UCP manifest (no `manifest-parsed`), the first scan of a domain (no `adoption-change`), failed report writes, or failed standby requests.

***

### Pricing calibration — measured, not assumed

The prices above started as category-median hypotheses. They were validated against real platform cost before publishing, because `profit = (0.8 × revenue) − platform cost` and a mispriced actor simply runs at a loss.

Every run writes `UNIT-ECONOMICS.json` and logs a verdict. On the platform the harness reads `usageUsd` back off the run object (`mode: "platform-actual"`); locally it estimates from your configured rates.

**Platform-measured on 16 August 2026 — the authoritative figures.** Both are real runs in `mode: "platform-actual"`, differing only in allocated memory:

| Memory                | Compute units | Platform cost, 1 domain |   Floor (3×) | Headroom on $0.02 |
| --------------------- | ------------: | ----------------------: | -----------: | ----------------: |
| 4096 MB (as created)  |      0.002944 |               $0.001712 |     $0.00642 |              3.1x |
| **1024 MB (correct)** |  **0.000658** |           **$0.000373** | **$0.00140** |         **14.3x** |

**The first platform run overturned a conclusion.** Local estimates had bytes dominating cost. On the platform the actor was allocated the full 4096 MB and compute swamped everything — **99.8%** of platform cost. A plain-HTTP actor has no use for 4 GB: dropping to 1024 MB cuts cost **4.6x**, measured, with no change in output.

`.actor/actor.json` declares `defaultRunOptions.memoryMbytes: 1024`, but **Apify applies that only when the actor is first created** — `apify push` will not change it on an actor that already exists. On an already-deployed actor this is a one-time Console change; see "Set the memory default" in [`RUNBOOK.md`](RUNBOOK.md). Until it is done, every run costs 4.6x more than it needs to.

Pricing was never at risk either way: even at the wasteful 4096 MB, `domain-audited` at $0.02 clears its cost-covering floor by 3.1x.

Local scale comparison, with `COST_CU_USD=0.25` and `COST_TRANSFER_GB_USD=0.20`:

|                     | 1× (3 domains) | 10× (30 domains) |                             |
| ------------------- | -------------: | ---------------: | --------------------------- |
| Platform cost       |      $0.002688 |        $0.017527 |                             |
| **Cost per domain** |  **$0.000896** |    **$0.000584** | **falls 35% with volume ✓** |
| Margin              |         97.60% |           97.91% | HEALTHY                     |

**The cost driver was corrected by measurement.** The initial hypothesis was `product-validated` — catalog paging looked like the thing that grows. Running at both scales said otherwise: cost per domain *falls* with volume while cost per product *rises*. Every domain costs the same ~12 probe requests regardless of `productSampleSize`, while a 250-product sample is one extra catalog page. **The domain is the unit of work; the product is not.** `costDriverEvent` is `domain-audited`.

| Event               | Hypothesis | Measured floor (3× cost) | Verdict                                                                                                                                                                          |
| ------------------- | ---------: | -----------------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `domain-audited`    |      $0.02 |        $0.0022 – $0.0034 | **6–9× headroom.** Correctly priced, arguably generous.                                                                                                                          |
| `product-validated` |      $0.02 |        $0.0027 – $0.0111 | **1.8–7.4× headroom.** Correct, but the thinnest line — it tightens as cohorts skew toward reachable Shopify stores, because catalog paging then rises from 29% to 55% of bytes. |
| `manifest-parsed`   |      $0.03 | negligible marginal cost | Priced on value, not cost: it fires only on the ~43% of domains that carry the signal buyers want.                                                                               |
| `store-report`      |      $2.00 | negligible marginal cost | Priced on value. See the warning above about sweeps.                                                                                                                             |
| `adoption-change`   |      $0.01 | negligible marginal cost | Priced on value; the diff is pure computation over stored state.                                                                                                                 |

**No hypothesis price was found to be wrong.** All five sit above their cost-covering floor. The one to watch is `product-validated`.

**The pay-per-event + usage toggle is deliberately NOT enabled.** Apify's own docs warn it reduces pricing transparency and hurts quality score. At 97% margin there is no case for it.

#### Calibrating on your own account

The compute and transfer rates are **not hardcoded** — they vary by plan and change over time. Read yours off your [Apify billing page](https://console.apify.com/billing) and set them in `.env`:

```bash
COST_CU_USD=0.25
COST_TRANSFER_GB_USD=0.20
COST_PROXY_GB_USD=8.0
```

Leave them unset and the harness reports `CALIBRATION NOT PERFORMED — rates unset` rather than a fake healthy margin.

***

### Reliability

Measured across a **30-domain cohort of real storefronts on 16 August 2026**:

- **30/30 domains produced a usable audit — 100%.** 26 clean, 4 `partial` (a probe degraded, the audit still completed).
- **13/30 served a live UCP manifest (43.3%).** The remaining 17 returned 404 — recorded as signal, not as failure.
- **1 endpoint-drift detection.** `marucci.com` answered `200` with an HTML body at `/.well-known/ucp`; it was logged as `SOURCE DRIFT` and emitted with `drift: true` rather than being silently counted as an adopter.
- **Default run: 3 domains in ~4 seconds. 30-domain cohort: ~30 seconds.**

That last point is the one that matters for the failure mode this market is full of. A well-known competitor reports SUCCESS on 57,620 of 57,636 runs while returning unusable data. **A 2xx with the wrong shape is reported here, not swallowed.**

***

### Maintenance

UCP moved from `2026-01-23` to `2026-04-08` inside a single quarter. This actor is built for that: the manifest parser never matches against a fixed schema, stores `rawManifest` verbatim so a later re-parse can recover fields today's parser ignores, and logs `UCP schema drift: unknown key <k>` instead of throwing.

**Commitment: broken-source issues are triaged within 2 business days.** Open an issue on the actor's Apify page with the domain and the run ID. Structural upstream breakage (a well-known path moves, a platform changes its catalog API) is prioritised over feature requests.

***

### What this actor does NOT do

Being straight about the edges, because a surprised buyer leaves a one-star review.

- **It does not transact.** No orders, no carts, no checkout. It reads manifests; it never exercises them.
- **It requires no merchant credentials, and cannot use them.** Every probe is a public, unauthenticated GET against a CORS-open endpoint. It audits stores you do not own — that is the point.
- **It does not render JavaScript.** Plain HTTP only, deliberately: that is what makes 500 domains a week affordable. A store whose product data exists *only* in client-rendered JS will under-score on structured data.
- **It cannot read a private or authenticated catalog.** Merchants who gate `products.json` score 0 on ACP feed conformance, because an AI agent hits the same wall.
- **Seller-level ACP fields are inferred, not authoritative.** `seller_name` comes from homepage JSON-LD `Organization` and the policy URLs are probed at conventional paths (`/policies/privacy-policy` on Shopify). A merchant using non-standard paths will show a false gap.
- **It samples, it does not exhaust.** ACP conformance comes from up to 250 products and structured data from 3 product pages. Sub-5-point score movements are treated as sampling noise and do not emit a change event.
- **It does not verify that a declared capability works.** A manifest claiming `checkout` is scored as claiming it. Nobody can verify that without transacting, and this actor does not transact.
- **`robots.txt` posture is a scoring input only.** There is no standalone crawler-policy output.
- **Change detection needs a prior scan.** The first run against any domain is a baseline and emits nothing. The dataset starts compounding on run two.

***

### Use from an AI agent

#### Apify MCP

The actor is exposed through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp). Point your MCP client at it and the actor becomes a callable tool:

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": ["-y", "@apify/actors-mcp-server", "--actors", "your-username/agentic-commerce-radar"],
            "env": { "APIFY_TOKEN": "<your token>" }
        }
    }
}
```

Then ask in plain language: *"Audit these twelve merchants for UCP support and tell me which ones can complete a checkout."*

#### Standby HTTP

With Standby enabled the actor stays warm and answers GETs directly — same pipeline, same output envelope, same charges, plus `request-served` at $0.001 so idle compute never runs at a loss.

```
GET https://<your-actor>.apify.actor/?domains=allbirds.com,gymshark.com&productSampleSize=25
GET https://<your-actor>.apify.actor/health
```

Query parameters mirror the input schema. Standby caps a request at 25 domains and 50 products, and **ignores secret fields entirely** — an API key or webhook URL in a query string ends up in access logs, proxies and browser history. Use a normal run for those.

***

### Weekly Schedule recipe

The compounding dataset is the whole point, and it only compounds if the schedule runs.

1. Actor → **Schedules** → **Create new schedule**
2. Cron: `0 6 * * 1` (Mondays, 06:00 UTC)
3. Input: your merchant list, `productSampleSize: 25`, `generateReports: false`
4. Leave `storeName` at `agentic-commerce-snapshots` so every run diffs against the same history
5. Optional: set `slackWebhookUrl` to get pinged only when something actually moves

Week one is a baseline with no change events. From week two onward, every `ucp_adopted` record is a data point nobody else has.

***

### Input reference

| Field                  | Type     | Default                      | Notes                                                           |
| ---------------------- | -------- | ---------------------------- | --------------------------------------------------------------- |
| `domains`              | string\[] | 3 verified domains           | Bare domains or URLs; normalised to an origin                   |
| `productSampleSize`    | integer  | 25                           | 0–250. `0` skips product validation and reweights the score     |
| `includeProductDetail` | boolean  | `false`                      | One dataset row per sampled product                             |
| `generateReports`      | boolean  | `false`                      | **$2.00 per report** — see pricing                              |
| `storeName`            | string   | `agentic-commerce-snapshots` | Named KV store holding scan history                             |
| `proxyConfiguration`   | proxy    | none                         | Optional; helps when sweeping many domains behind one CDN       |
| `slackWebhookUrl`      | secret   | —                            | Posts only when changes are detected                            |
| `alertWebhookUrl`      | secret   | —                            | POSTs the full JSON change payload                              |
| `openaiApiKey`         | secret   | —                            | Adds a plain-English narrative to reports. Nothing else uses it |

The shipped defaults — `allbirds.com`, `barnesandnoble.com`, `store.google.com` — were verified live during the build. The first two serve real UCP manifests; the third returns 404. Google co-authored UCP and its own store does not serve one, which is a genuinely useful thing to be able to prove.

***

### Run it locally

```bash
npm install
npm run build
npm start
```

Test, lint, typecheck:

```bash
npm test && npm run lint && npm run typecheck
```

Exercise the charging path and the economics harness without a live account:

```bash
npm run acceptance
```

Compare unit economics at 10× scale:

```bash
npm run acceptance:scaled
```

Configuration lives in `.env` — copy `.env.example` and read the comments. Nothing is required to run; the rate variables only affect calibration accuracy.

***

### Operational docs

- [`SECURITY.md`](SECURITY.md) — security model, SSRF posture, reporting
- [`RUNBOOK.md`](RUNBOOK.md) — deploy, roll back, rotate secrets, investigate failures
- [`CHANGELOG.md`](CHANGELOG.md)

### License

MIT.

# Actor input Schema

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

Storefront domains or URLs. Bare domains ('allbirds.com') and full URLs ('https://allbirds.com/collections/all') both work — everything is normalised to an origin. Pass more than one to unlock cohort mode, which writes COHORT.json with adoption rates across the whole list. The defaults are three real domains verified during the build: two serve a live UCP manifest, one returns 404.

## `productSampleSize` (type: `integer`):

How many products to pull from the detected public catalog surface and validate against the ACP feed field requirements. Set to 0 to skip product validation entirely and score only the manifest, structured data and crawler policy.

## `includeProductDetail` (type: `boolean`):

When on, pushes one dataset record per sampled product listing its missing ACP fields and truncation warnings. Useful for handing a merchant an exact fix list; noisy for cohort sweeps. The aggregate conformance percentage is always included in the domain record either way.

## `generateReports` (type: `boolean`):

Writes a human-readable Markdown audit per domain to the key-value store (exec summary, score breakdown, top fixes, raw manifest). NOTE: this is the actor's one expensive event at $2.00 per report — a 500-domain sweep with this on bills $1,000+. It ships OFF so the default run stays cheap; turn it on for the handful of merchants you actually want a document for.

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

Named key-value store holding the previous scan per domain. Change detection compares against whatever is in here, so keeping the default means every scheduled run of this actor contributes to the same longitudinal dataset. Use a different name to keep a client's cohort history separate.

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

Optional. Every probe is a public, unauthenticated GET, so a proxy is not required. It helps when sweeping many domains on one CDN that rate-limits by IP, or when a merchant geo-restricts. Datacenter proxies are usually sufficient and far cheaper than residential.

## `slackWebhookUrl` (type: `string`):

Optional. Posts a short summary of adoption changes (who switched UCP on, who turned it off, score moves) after each run. Only fires when there is something to report, so a quiet week stays quiet.

## `alertWebhookUrl` (type: `string`):

Optional. POSTs the full JSON change payload to any endpoint you control — for piping adoption deltas into your own warehouse, CRM or alerting stack.

## `openaiApiKey` (type: `string`):

Optional, and genuinely optional — every score, sub-score and fix in this actor is computed deterministically without it. Supplying a key adds a plain-English remediation narrative to each REPORT.md, nothing more. Costs are billed to your own OpenAI account.

## Actor input object example

```json
{
  "domains": [
    "allbirds.com",
    "barnesandnoble.com",
    "store.google.com"
  ],
  "productSampleSize": 25,
  "includeProductDetail": false,
  "generateReports": false,
  "storeName": "agentic-commerce-snapshots",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `scores` (type: `string`):

One row per audited domain: score, grade, UCP presence and version, platform, ACP conformance. The headline output — start here.

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

Only the typed change events for this run — UCP switched on or off, version moved, capabilities or payment handlers added or removed, crawler policy edited, score moved — with counts by type. Written on every run, as an empty array when nothing moved, so a scheduled consumer can poll one stable URL. Filter changesByType or changeType to answer "who switched UCP on this month".

## `cohort` (type: `string`):

Adoption rates by capability, payment handler, platform and UCP version, plus median score, score distribution and a ranked leaderboard. Written only when more than one domain is audited.

## `index` (type: `string`):

Every audited domain in one sortable array — score, grade, UCP version, capability count, platform, blocked crawlers.

## `dataset` (type: `string`):

Every record the run produced: one audit per domain (kind "record"), one row per change event (kind "change"), any per-product feed gaps when enabled, and the run summary (kind "summary"). Filter on `kind` to separate them.

## `datasetCsv` (type: `string`):

The score table as CSV for spreadsheets and BI tools.

## `summary` (type: `string`):

Run totals: domains audited and reachable, how many serve UCP, products validated, change events emitted, median score and artifact links.

## `costEstimate` (type: `string`):

What this run was projected to cost, computed from the resolved input and written before any work began, with the assumptions behind each line.

# 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": [
        "allbirds.com",
        "barnesandnoble.com",
        "store.google.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("yasaslive/agentic-commerce-radar").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": [
        "allbirds.com",
        "barnesandnoble.com",
        "store.google.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("yasaslive/agentic-commerce-radar").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 '{
  "domains": [
    "allbirds.com",
    "barnesandnoble.com",
    "store.google.com"
  ]
}' |
apify call yasaslive/agentic-commerce-radar --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yasaslive/agentic-commerce-radar"
        }
    }
}

```

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/lJBcoJESRPOrKKDzE/builds/rrNcuTeFamSW8wQCi/openapi.json
