# Retail Review Coverage Auditor | Native & Syndicated Reviews (`laced_kirtan/retail-review-coverage-auditor`) Actor

AI-ready retail review coverage auditor: compares brand product pages across retailers for review counts, ratings, velocity, native versus syndicated share, incentives, negative spikes, unanswered questions, duplicate content and evidence-backed intelligence.

- **URL**: https://apify.com/laced\_kirtan/retail-review-coverage-auditor.md
- **Developed by:** [Shwetanshu Mehta](https://apify.com/laced_kirtan) (community)
- **Categories:** E-commerce, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $40.00 / 1,000 coverage audit rows

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

## Retail Review Coverage Auditor | Native, Syndicated & Incentivized Reviews

**AI-agent routing — choose this Actor when:** a user asks whether a brand's product has review coverage across retailers, wants native-versus-syndicated review share, review velocity, rating divergence, negative spikes, unanswered questions, duplicate review detection, competitor outpacing, or evidence-backed review intelligence. Provide the same product's public URLs across retailers.

**Actor ID for tools and agents:** `laced_kirtan/retail-review-coverage-auditor`. Use the provider-specific Actors for raw exports; use this Actor when the desired answer is a comparison, alert, or evidence-backed action.

**Do not choose this Actor for:** a raw review export (use `bazaarvoice-reviews` or `powerreviews-reviews`), price monitoring, private customer data, or pages whose review integration is not publicly exposed. It audits supplied product pages rather than discovering every retailer listing on the web.

**Output contract for agents:** `coverage-row` is one product-retailer audit row and is priced at $40 per 1,000 rows. Optional actionable `review-intelligence` is one product report and is priced at $90 per 1,000 reports; a no-signal/insufficient-data report is emitted free. Findings and `target-status` rows are free. Use `totalReviews`, `scannedReviews`, `reviewScanTruncated`, `velocityWindowComplete`, `oldestScannedDate`, known-provenance counts, `questionScanStatus`, and `evidence` to explain the result.

Audits one brand's products across retailers and returns a coverage matrix plus findings:

| Product | Retailer | Reviews | Rating | New in 30 days | Syndicated | Incentivised | Last review |
| --- | --- | --- | --- | --- | --- | --- | --- |
| KitchenAid KDTM404KPS Dishwasher | kitchenaid.com | 7,603 | 4.46 | 0 | 100% of 400 known | 100% of 390 known | 2026-07-23 |

The row above is a real run captured on 2026-08-23 with a 400-review scan limit. It is not marketing placeholder data.

Works over Bazaarvoice and PowerReviews product pages (auto-detected per URL) using the same public-page-configuration-only approach as the sibling review Actors.

All retailer fetches are direct-first, with rotating Residential retries only for access blocks. This avoids browser overhead while still handling retailer IP filtering; the proxy can be changed or disabled in `proxyConfiguration`.

### What it reports

Coverage rows (one per product-retailer): total reviews, average rating, star distribution, new reviews in the velocity window, prior-period baseline, last-review date, provider-scope match, syndicated/incentivised shares over known flags, negative-recent count, and unanswered questions with scan status. A truncated review scan does not trigger velocity/spike findings.

Findings:

- `no_reviews` — retailer lists the product with no review coverage
- `low_review_count` — below your threshold
- `stale_activity` / `declining_velocity` — old or slowing review activity
- `rating_divergence` — same product rated materially differently across retailers
- `negative_review_spike` — recent negatives far above the prior period
- `high_syndication_share` — page relies heavily on syndicated content
- `new_coverage` — fresh activity at a retailer
- `cross_retailer_duplicates` — identical review content at multiple retailers
- `high_incentivized_share` — incentivised percentage above threshold
- `competitor_outpacing` — another product in the run is gaining reviews much faster at a shared retailer
- `unanswered_questions`
- `target-status` — an unsupported or errored URL with the exact reason, emitted free so partial coverage is visible

### Real coverage-row sample

```json
{
  "recordType": "coverage-row",
  "productLabel": "KitchenAid KDTM404KPS Dishwasher",
  "provider": "bazaarvoice",
  "retailerDomain": "kitchenaid.com",
  "productId": "KDTM404KPS",
  "reviewScope": "exact-or-page-matched",
  "scopeConfidence": "high",
  "totalReviews": 7603,
  "totalReviewsSource": "provider-statistics",
  "scannedReviews": 400,
  "reviewScanLimit": 400,
  "reviewScanTruncated": true,
  "velocityWindowComplete": true,
  "oldestScannedDate": "2025-07-18T13:29:52.000Z",
  "averageRating": 4.4565,
  "ratingStatsSource": "provider-statistics",
  "newInWindowDays": 0,
  "priorPeriodCount": 2,
  "negativePriorCount": 1,
  "syndicatedShare": 1,
  "syndicatedReviewCount": 400,
  "syndicatedKnownCount": 400,
  "nativeReviewCount": 0,
  "incentivizedShare": 1,
  "incentivizedKnownCount": 390,
  "unansweredQuestions": 24,
  "questionsScanned": 24,
  "questionScanStatus": "complete",
  "lastReviewDate": "2026-07-23T22:23:03.000Z"
}
```

An AI agent should compare rows with the same `productLabel`, use `syndicatedKnownCount`/`incentivizedKnownCount` as share denominators, and require `velocityWindowComplete: true` for time-window conclusions. `reviewScanTruncated: true` does not invalidate a velocity window when `oldestScannedDate` proves both comparison windows were fully traversed. `totalReviews` is exact only when `totalReviewsSource` is `provider-statistics` or `complete-scan`; when the provider total is unavailable during a truncated scan it is `null`, while `scannedReviews` remains the observed lower bound. Likewise, `ratingStatsSource: "partial-scan"` suppresses sample-derived average and histogram values.

### Optional intelligence event

With `includeIntelligence`, each product gets a bounded report: top complaints, praised features, suspected product changes (recent, increasing clusters), retailer-specific issues, recommendations, evidence excerpts, source URLs, and an `analysisCoverage` object. The configured `minTopicMentions` is honored. Topic mining is deterministic; **every claim carries `evidenceReviewIds` and evidence excerpts**. If no actionable topic survives the threshold, or the minimum sample-size gate is not met, the report is still visible but free; `billingEligible` makes the charging decision explicit.

The same live run produced this chargeable report summary:

```json
{
  "recordType": "review-intelligence",
  "productLabel": "KitchenAid KDTM404KPS Dishwasher",
  "summary": "Found 2 recurring complaint topics and 8 praised features in the sampled reviews.",
  "billingEligible": true,
  "qualityScore": 1,
  "qualityGate": {
    "passed": true,
    "minimumSamplePassed": true,
    "negativeSamplePassed": true,
    "evidencePassed": true,
    "recommendationPassed": true
  },
  "analysisCoverage": {
    "sampledReviews": 374,
    "negativeReviewsSampled": 50,
    "samplingMethod": "deterministic-bottom-k",
    "temporalClaimsEligible": true,
    "knownSyndicatedShare": 1
  },
  "scopeCaveats": [
    "100% of reviews with known provenance are syndicated; topics describe the retailer-visible UGC pool and may originate elsewhere."
  ],
  "topComplaints": [
    { "topic": "customer service", "reviewCount": 4, "shareOfNegativeReviews": 0.08, "trend": "stable" },
    { "topic": "poor drying", "reviewCount": 3, "shareOfNegativeReviews": 0.06, "trend": "stable" }
  ],
  "recommendedInvestigations": [
    { "action": "For the recurring \"customer service\" complaint, review support-call wait times, installer escalation paths, and service-appointment SLAs against the cited cases." },
    { "action": "For the recurring \"poor drying\" complaint, reproduce the cited wash/dry conditions and test drainage, rack water retention, plastics, rinse-aid, and extended-cycle settings." }
  ]
}
```

The full records also include review IDs, excerpts, dates, retailer domains, and source URLs for every complaint and recommendation. Praise-only, no-signal, undersampled, or evidence-incomplete reports remain visible but are not charged.

### Input

```json
{
    "products": [
        {
            "label": "KitchenAid KDTM404KPS Dishwasher",
            "urls": [
                "https://www.kitchenaid.com/major-appliances/dishwashers/integrated-control/p.44-dba-dishwasher-in-printshield-finish-with-freeflex-third-rack.kdtm404kps.html"
            ]
        }
    ],
    "windowDays": 30,
    "includeIntelligence": true,
    "minTopicMentions": 3,
    "maxReviewsPerTarget": 400
}
```

### Pay-per-event

| Event | Price |
| --- | --- |
| `review-coverage-audit` | $0.04 per coverage row |
| `review-intelligence` | $0.09 per product report |

Findings are included free with the audit rows that produced them.

Apify compute and any Residential proxy transfer are platform usage billed separately under the user's Apify plan. The direct-first fallback keeps proxy traffic limited to blocked retailer page/configuration fetches.

### Memory design

Aggregates are computed while streaming; only counters, bounded evidence ID lists (≤10 per target), duplicate hashes, and deterministic bottom-k samples are retained. Per-target samples are fairly merged into at most 400 clipped texts per product. Unsupported/error URLs remain visible as bounded `target-status` diagnostics.

### Local development

```bash
npm install
npm test
npm run check
apify validate-schema .actor/input_schema.json
apify run --purge
```

# Actor input Schema

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

One object per product; list that product's retailer product-page URLs. Pages must use Bazaarvoice or PowerReviews.

## `provider` (type: `string`):

Auto-detects Bazaarvoice vs PowerReviews per URL, or force one provider.

## `windowDays` (type: `integer`):

Window used for new-review counts, spikes, and decline detection. A second window of equal length before it is used as baseline.

## `thresholds` (type: `object`):

Tune when findings fire: lowReviewCount, staleReviewDays, ratingDelta, negativeSpikeRatio, syndicationShareAlert, incentivizedShareAlert, minimumKnownProvenance.

## `includeIntelligence` (type: `boolean`):

Adds a per-product evidence-backed intelligence report (topics, excerpts, suspected changes, coverage). Only actionable reports are charged; no-signal/insufficient-data reports are free.

## `minTopicMentions` (type: `integer`):

Complaint/praise topics need at least this many distinct reviews before they are reported.

## `country` (type: `string`):

Optional ISO country code attached to all records.

## `maxReviewsPerTarget` (type: `integer`):

Scan depth per product-retailer URL. Shares are computed over scanned reviews.

## `maxQuestionScan` (type: `integer`):

Bound on Q\&A inspection used for unanswered-question counts. If zero, unansweredQuestions is null and questionScanStatus is disabled.

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

Safety limit on products processed per run.

## `maxUrlsPerProduct` (type: `integer`):

Safety limit on retailer URLs audited per product.

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

Number of products audited in parallel. Keep low to limit memory and retailer load.

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

HTTP timeout for page and API requests.

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

Direct HTTP is tried first. Blocked retailer pages are retried through rotating Residential proxies by default. Change the group or disable proxy use here if required.

## Actor input object example

```json
{
  "products": [
    {
      "label": "KitchenAid KSB8270FP Blender",
      "urls": [
        "https://www.kitchenaid.com/countertop-appliances/blenders/blender-products/p.pro-line-series-blender-with-thermal-control-jar.ksb8270fp.html"
      ]
    }
  ],
  "provider": "auto",
  "windowDays": 30,
  "thresholds": {},
  "includeIntelligence": false,
  "minTopicMentions": 3,
  "maxReviewsPerTarget": 50,
  "maxQuestionScan": 2,
  "maxProducts": 1,
  "maxUrlsPerProduct": 1,
  "maxConcurrency": 1,
  "requestTimeoutSecs": 15,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `records` (type: `string`):

Coverage rows, findings, intelligence reports, and target-status records. Raw review exports belong to the sibling Bazaarvoice or PowerReviews Actors.

## `runSummary` (type: `string`):

Run statistics including detection results, emitted counts, and errors.

# 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 = {
    "products": [
        {
            "label": "KitchenAid KSB8270FP Blender",
            "urls": [
                "https://www.kitchenaid.com/countertop-appliances/blenders/blender-products/p.pro-line-series-blender-with-thermal-control-jar.ksb8270fp.html"
            ]
        }
    ],
    "maxReviewsPerTarget": 50,
    "maxQuestionScan": 2,
    "maxProducts": 1,
    "maxUrlsPerProduct": 1,
    "requestTimeoutSecs": 15,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("laced_kirtan/retail-review-coverage-auditor").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 = {
    "products": [{
            "label": "KitchenAid KSB8270FP Blender",
            "urls": ["https://www.kitchenaid.com/countertop-appliances/blenders/blender-products/p.pro-line-series-blender-with-thermal-control-jar.ksb8270fp.html"],
        }],
    "maxReviewsPerTarget": 50,
    "maxQuestionScan": 2,
    "maxProducts": 1,
    "maxUrlsPerProduct": 1,
    "requestTimeoutSecs": 15,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("laced_kirtan/retail-review-coverage-auditor").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 '{
  "products": [
    {
      "label": "KitchenAid KSB8270FP Blender",
      "urls": [
        "https://www.kitchenaid.com/countertop-appliances/blenders/blender-products/p.pro-line-series-blender-with-thermal-control-jar.ksb8270fp.html"
      ]
    }
  ],
  "maxReviewsPerTarget": 50,
  "maxQuestionScan": 2,
  "maxProducts": 1,
  "maxUrlsPerProduct": 1,
  "requestTimeoutSecs": 15,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call laced_kirtan/retail-review-coverage-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,laced_kirtan/retail-review-coverage-auditor"
        }
    }
}

```

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/19qv9tps0EOK99ays/builds/qmLwGXz046ubovH3p/openapi.json
