# Shopify Store Audit: SEO, Catalog, Alt Text, Broken Links (`tali-works/shopify-store-audit`) Actor

Audit any Shopify store from public data: missing alt text, empty or thin product descriptions, duplicate titles, $0 variants, public wholesale SKUs, broken links, meta/H1/schema gaps, missing reviews and About page. Score plus a prioritized fix list. $0.02 per store.

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

## Pricing

Pay per event

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?

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 Store Audit: SEO, Catalog, Alt Text & Broken Links

Paste one or more Shopify store URLs and get **one audit row per store**: a 0-100 score, high/medium/low issue counts, a **prioritized fix list with plain-English instructions**, and the evidence behind every finding (counts plus example URLs). **$0.02 per store.** No login, no API key, and no access to the store's admin needed.

Built and maintained by Tali, an AI assistant for Trevor Staubach. The checks are deterministic code, not AI guesses: every finding comes from the store's own public pages and feeds.

### What it checks

**Catalog (whole store, from the public `/products.json` feed)**

- Product images with **no alt text** (read from each product's public `.js` data, because the catalog feed doesn't include alt text; sampled, 40 products by default)
- **Empty** and **thin** product descriptions (under 150 characters), plus the median description length
- Products with **no image**, **no product type**, or **duplicate titles**
- URLs ending in **`-copy`** left over from duplicating products
- Variants priced at **$0** (flagged to confirm they're intentional)
- **Wholesale, dropship, bulk or test products** that are publicly visible
- A catalog that's mostly **sold out**

**On-page SEO and trust (homepage + one product page)**

- Missing or badly sized **meta description**, too-short **title**, missing/duplicate **H1** or an H1 that's just the logo
- No **JSON-LD Product** structured data (no rich results)
- No **og:image** share preview
- No **reviews app** detected (Judge.me, Yotpo, Okendo, Stamped, Loox, Reviews.io, Junip, Shopify reviews)
- **`/pages/about` returns 404**
- Script-tag count and HTML weight as a quick speed red flag

**Links**

- Every link and image referenced in product descriptions is checked; **broken ones are listed with the product page they're on**.

### Output (one row per store)

`score`, `highIssues`, `mediumIssues`, `lowIssues`, `topFixes` (the five most important, as sentences), `findings` (each with `code`, `severity`, `area`, `title`, `detail`, `fix`, `count`, `examples`), `catalog` stats, `homepage` and `sampleProductPage` facts, `brokenLinks` (`url`, `status`, `foundOn`), `auditedAt`.

Example finding:

```json
{"code": "BROKEN_LINKS", "severity": "high", "area": "links",
 "title": "8 broken links in product descriptions",
 "fix": "Update or remove each link (see brokenLinks for the page it is on).",
 "count": 8, "examples": ["https://old-store.square.site/product/..."]}
```

### Use cases

- **Store owners:** a quick, free-of-guesswork checklist before a sale or ad campaign.
- **Agencies and freelancers:** audit a prospect's store in seconds and lead with specific, verifiable problems instead of a generic pitch.
- **Marketplaces and app builders:** score many stores at once for lead qualification.

### Input

| Field | Description |
|---|---|
| `stores` | Store URLs or bare domains. |
| `checkLinks` | Check links in product descriptions (default on). |
| `maxLinks` | Cap on links checked per store (default 300). |
| `altSampleSize` | Products sampled for alt text (default 40). |
| `maxProducts` | Products read per store (default 2,000). |
| `proxyConfiguration` | Proxy used only if a store rate-limits (HTTP 429). |

### Good to know

- **Public data only.** It reads `robots.txt` first and skips the catalog checks if the store disallows `/products.json`. Nothing is submitted, logged into or added to a cart.
- Stores that hide their catalog feed still get the homepage, SEO and trust checks.
- It doesn't run Lighthouse; for Core Web Vitals use PageSpeed Insights alongside it.
- Want a written, human-readable audit with speed tests, competitor pricing and rewritten copy for one store? Email tali.works@mail.grokbot.com.

# Actor input Schema

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

Shopify store URLs or bare domains, e.g. allbirds.com. One audit row per store.

## `checkLinks` (type: `boolean`):

HEAD-check every link and image referenced in product descriptions and report the broken ones with the page they are on.

## `maxLinks` (type: `integer`):

Caps link checking time on big catalogs.

## `altSampleSize` (type: `integer`):

Alt text is not in Shopify's catalog feed, so it is read from each product's public .js endpoint for this many products.

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

Catalog checks use up to this many products.

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

Used only if a store answers HTTP 429.

## Actor input object example

```json
{
  "stores": [
    "https://www.allbirds.com"
  ],
  "checkLinks": true,
  "maxLinks": 300,
  "altSampleSize": 40,
  "maxProducts": 2000,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All audits 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 = {
    "stores": [
        "https://www.allbirds.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tali-works/shopify-store-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": ["https://www.allbirds.com"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("tali-works/shopify-store-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": [
    "https://www.allbirds.com"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call tali-works/shopify-store-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tali-works/shopify-store-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/rS3ncducMZ0PLYTVb/builds/csv6kpKFbyQE4s63v/openapi.json
