# Shopify AI Readiness Audit - products.json & AI crawler check (`highbrow_fame/shopify-ai-readiness-audit`) Actor

Shopify AI readiness audit: bulk products.json audit and AI crawler access check for any list of Shopify stores ($0.01 per store, 500 stores = $5)

- **URL**: https://apify.com/highbrow_fame/shopify-ai-readiness-audit.md
- **Developed by:** [yestrue](https://apify.com/highbrow_fame) (community)
- **Categories:** E-commerce, SEO tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 1,000 store auditeds

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

## Shopify AI Readiness Audit - products.json & AI crawler check

**Shopify AI readiness audit for a whole list of stores: $0.01 per store, 500 stores = $5.** Paste Shopify store domains (or a link to a CSV file) and get one row per store: a 0-100 readiness score, the three fixes that would add the most points, how complete the public product feed is, whether the product page carries Product structured data (JSON-LD), and which AI crawlers (GPTBot, OAI-SearchBot, PerplexityBot, ClaudeBot, Google-Extended) the store's robots.txt lets in.

**Run it now:** press **Start** - the prefilled input audits a public Shopify demo store in a few seconds. Replace it with your own list of stores, set a *Maximum charge* if you like (500 stores = $5), and download the rows as JSON, CSV or Excel. Stores that cannot be audited are free.

### EU customs identifiers (from 1 Nov 2026)

From 1 Nov 2026, EU customs declarations for B2C distance sales need product identifiers: your own product code (the SKU), a manufacturer code, and a GTIN where the product has one. Merchants selling to EU customers are checking their catalogs now. Each audited store gets these extra fields:

- `euSkuCoveragePct`: share of the sampled variants with a real SKU (empty values and fillers such as N/A or TBD do not count).
- `euVariantsWithoutSku`: how many sampled variants have no usable SKU.
- `euDuplicateSkus`: how many SKU values are used by more than one variant.
- `euGtinInJsonLd`: `true` when the product page that is read shows a GTIN with a valid GS1 check digit, `false` when it shows none or a wrong one.

If SKUs are missing, one of the top fixes says so: "Give every variant its own SKU". These fields do not change the 0-100 score.

**What this is, and is not:** the public `products.json` feed carries no barcodes and no manufacturer codes, so this is a readiness proxy based on SKUs and one product page, not a full check of your customs data. It is not legal advice; confirm what you must declare with your carrier or customs broker.

### What one row looks like

Illustrative output with placeholder store names:

| Store | Score | Products in feed | Product JSON-LD | AI crawlers blocked | Top fix |
| --- | --- | --- | --- | --- | --- |
| `store-a.example.com` | 93 | 250+ | yes | none | Give every variant its own SKU: EU customs declarations from 1 Nov 2026 use it as your product code |
| `store-b.example.com` | 49 | 84 | no | OAI-SearchBot, PerplexityBot | Add Product structured data (JSON-LD) to your product pages |
| `store-c.example.com` | 41 | 19 | yes | GPTBot, ClaudeBot | Write fuller product descriptions: 88% of audited products have under 150 characters |
| `store-d.example.com` | - | - | - | - | status `feed_unavailable`: products.json is not public (free) |

```json
{
  "input": "store-b.example.com",
  "store": "https://store-b.example.com",
  "status": "ok",
  "readinessScore": 49,
  "topFixes": [
    "Add Product structured data (JSON-LD) to your product pages: the audited product page has none, so crawlers cannot read price and availability reliably.",
    "Your robots.txt blocks OAI-SearchBot and PerplexityBot on product pages (the crawler behind ChatGPT search results; the crawler behind Perplexity answers). If you want your products to be found there, allow them.",
    "Give every variant its own SKU: EU customs declarations from 1 Nov 2026 use it as your product code. 120 of 300 sampled variants have none."
  ],
  "scoreFeed": 34.9, "scoreStructuredData": 0, "scoreAiCrawlerAccess": 14,
  "productCount": 84, "productCountIsMinimum": false, "productsAudited": 50,
  "titlePct": 100, "descriptionPct": 70, "pricePct": 100, "imagePct": 100, "skuPct": 60,
  "tagsPct": 90, "productTypePct": 80, "vendorPct": 100, "variantNamesPct": 100,
  "euSkuCoveragePct": 60, "euVariantsWithoutSku": 120, "euDuplicateSkus": 2, "euVariantsSampled": 300, "euGtinInJsonLd": false,
  "productJsonLd": false,
  "robotsTxtFound": true,
  "oaiSearchBotAllowed": false, "perplexityBotAllowed": false, "gptBotAllowed": true, "claudeBotAllowed": true, "googleExtendedAllowed": true,
  "aiCrawlersBlocked": ["OAI-SearchBot", "PerplexityBot"],
  "checkedAt": "2026-10-23T09:00:00.000Z"
}
```

### Who it is for

- **Agencies and freelancers** who audit client catalogs and want a scored, comparable table instead of opening every store by hand.
- **Shopify app builders and SEO tools** that need a lead list sorted by how much a store has to fix.
- **Store owners and operators** with several stores or a long competitor list.

### What it checks

| Part | Points | What is measured |
| --- | --- | --- |
| Feed completeness | 40 | From the store's public `/products.json`: share of audited products with a title, a description of at least 150 characters, a price above zero, an image, a SKU on every variant, tags, a product type, a vendor, and named variant options (Size, Color instead of "Title") |
| Product structured data | 30 | One product page: is there Product JSON-LD, with price, availability, GTIN, SKU and brand? |
| AI crawler access | 30 | The store's robots.txt, judged on a product URL, for OAI-SearchBot, PerplexityBot, GPTBot, ClaudeBot and Google-Extended |

Each row also carries the product count, the percentage for every feed field, and the plain-English **top three fixes**, ordered by the points they would add.

### Input

- **Shopify stores**: domains or any URL on the store, one per line. Duplicates are audited once. Up to 5,000 per run.
- **CSV link** (optional): a public https link to a CSV or text file with one store per line; the first domain or URL on each line is used.
- **Products to audit per store**: 1-250, default 50. The feed is read in one request of up to 250 products, so the product count is exact up to 250.
- **Stores in parallel** and **pause between requests**: defaults 5 stores at a time and 800 ms.

### Price

**$0.01 per store audited** (pay per event: one `store-audited` event per store with status `ok`). 100 stores = $1, 500 stores = $5, 1,000 stores = $10. Apify plan discounts apply on top (Bronze -10%, Silver -20%, Gold and above -30%). Everything else is free: `feed_unavailable`, `robots_disallowed`, `blocked`, `rate_limited`, `unreachable`, `not_shopify`, `empty_catalog`, `duplicate` and `invalid_input` rows are not charged. Set a *Maximum charge* on the run and it stops cleanly when the budget is used up. Apify's small per-run platform fee applies to every Actor.

### FAQ

#### Is products.json public?

For most Shopify stores, yes: the storefront serves `/products.json` (a product list in JSON) to anyone, without a login, unless the store is password protected or the merchant has switched it off. This Actor reads only that public feed and one public product page, never anything behind a login. A store that does not publish the feed comes back as `feed_unavailable` and costs nothing.

#### How much for 1,000 stores?

$10 at the list price of $0.01 per store, less with an Apify plan discount, and less still if some stores cannot be audited, because those rows are free. A run of 1,000 stores takes roughly 10 minutes at the default settings.

#### What is the score based on?

40 points for feed completeness, 30 for Product structured data on one product page, 30 for letting AI crawlers read product pages. It is a transparent checklist, not an official Shopify or AI-platform rating. If a store's product page cannot be read, the score is computed from the other two parts and the row says so in `note`.

#### Does it check EU customs product identifiers?

Partly. It measures the part the public storefront shows: whether every sampled variant has its own SKU (`euSkuCoveragePct`, `euVariantsWithoutSku`, `euDuplicateSkus`) and whether one product page exposes a valid GTIN (`euGtinInJsonLd`). Manufacturer codes and most barcodes are not published in `products.json`, so a clean result means your SKUs are in order, not that your customs data is complete. It is not legal advice; confirm with your carrier or customs broker.

#### Does a high score mean AI assistants will recommend the store?

No. It measures whether the basics an AI shopping tool needs are present and reachable on the store's public pages. It cannot see what ChatGPT, Perplexity or Gemini actually answer; the AI Search Visibility Tracker below measures that.

### Good to know

- **Barcodes (GTIN) are not in products.json.** They can only be seen in the Product structured data of the one product page that is read, so `jsonLdHasGtin` describes that page, not the whole catalog.
- **One product page per store.** Structured data is judged on the first product of the feed, not on every product.
- **Image alt text is not checked.** products.json does not carry it.
- **robots.txt access is not a visit log.** `oaiSearchBotAllowed: true` means the store's rules allow the crawler, not that it has visited. Blocking some AI crawlers can be a deliberate choice; the fixes say so.
- **Products to audit** samples the start of the feed; stores with thousands of products are judged on the sample.

### Polite by design

The robots.txt of every store is read **first** and obeyed: if it does not allow this robot to read `/products.json`, nothing else is requested (`robots_disallowed`). At most three requests per store (robots.txt, products.json, one product page), one request at a time per store with a pause between them, the store's Crawl-delay honoured up to 10 seconds, a clear user agent (`ShopifyReadinessAudit/1.0`), no proxy, no retry after an HTTP 403 or 429, and no attempt to get around bot protection.

### More AI visibility tools from highbrow_fame

| Actor | The question it answers | Price |
| --- | --- | --- |
| [AI Search Visibility Tracker](https://apify.com/highbrow_fame/ai-search-visibility-tracker) | Is my brand cited by ChatGPT, Perplexity and Gemini, and which competitors are cited instead? | full audit about $4.80 |
| [AI Brand Share of Voice](https://apify.com/highbrow_fame/ai-brand-share-of-voice) | Which brands do AI engines recommend for my category? | $0.08 per prompt |
| [Google AI Overview Citation Checker](https://apify.com/highbrow_fame/ai-overview-citation-checker) | Which sites does Google's AI Overview cite for my keywords? | $0.03 per keyword |

Found this useful? A short review on the Actor's Store page helps other store owners find it and tells us what to improve next.

# Actor input Schema

## `stores` (type: `array`):

Store domains or any URL on the store, one per line (example-store.com or https://example-store.com/products/x). Each store is reduced to its address; duplicates are audited once. Up to 5,000 per run.

## `csvUrl` (type: `string`):

Optional. A public https link to a CSV or text file with one store per line; the first cell on each line that is a domain or URL is used. Stores from the list above and from the file are merged.

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

How many products of each store's public feed are checked for completeness (title, description, price, image, SKU, tags, product type, vendor, variant names). The feed is read in one request of up to 250 products, so the product count is exact up to 250.

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

Different stores are audited at the same time; one store is only ever asked one thing at a time, with a pause between its requests.

## `delayMs` (type: `integer`):

Pause between two requests to the same store. A longer Crawl-delay in the store's robots.txt is used instead, up to 10 seconds.

## Actor input object example

```json
{
  "stores": [
    "theme-dawn-demo.myshopify.com"
  ],
  "maxProducts": 50,
  "maxConcurrency": 5,
  "delayMs": 800
}
```

# Actor output Schema

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

Every result as a JSON record, with a status for each input.

## `resultsCsv` (type: `string`):

The same records as CSV, for a spreadsheet.

# 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 = {
    "stores": [
        "theme-dawn-demo.myshopify.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("highbrow_fame/shopify-ai-readiness-audit").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 = { "stores": ["theme-dawn-demo.myshopify.com"] }

# Run the Actor and wait for it to finish
run = client.actor("highbrow_fame/shopify-ai-readiness-audit").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 '{
  "stores": [
    "theme-dawn-demo.myshopify.com"
  ]
}' |
apify call highbrow_fame/shopify-ai-readiness-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,highbrow_fame/shopify-ai-readiness-audit"
        }
    }
}
```

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/dawq6KO7Sk40cDkiO/builds/LHv14KZDISy4B3CJx/openapi.json
