# Shop SEO & Product Schema Audit - Merchant-Ready Check (`digivibetech/shop-seo-product-audit`) Actor

Audit shop pages for SEO and product data: title, meta, H1, canonical, noindex, alt text plus Product/Offer JSON-LD (price, currency, availability, image, brand, GTIN check digit, shipping, returns) and price mismatches. Score + fix list. $0.005 per page; failures free.

- **URL**: https://apify.com/digivibetech/shop-seo-product-audit.md
- **Developed by:** [DigiVibeTech](https://apify.com/digivibetech) (community)
- **Categories:** SEO tools, E-commerce, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 page audited (html page fetched and analysed)s

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

## Shop SEO & Product Schema Audit

Audit the pages of your online shop for **SEO basics and product structured data** in one run. For every page you get an SEO score, a **product score**, a **Merchant-ready** flag and one prioritised fix list.

Built for shop owners, agencies and developers working on WooCommerce, Shopify, Shopware, Magento, PrestaShop or custom shops: check product pages before launch, after a theme update or before submitting a Google Merchant Center feed.

### What it checks

**Product data (Product / Offer JSON-LD, microdata, Open Graph)**

- Product structured data present (and not only Open Graph tags)
- Name, price, `priceCurrency` (ISO 4217), availability, image, brand
- GTIN with **check-digit validation**, or MPN
- `shippingDetails` and `hasMerchantReturnPolicy` (Merchant listing enhancements)
- **Price mismatch** between JSON-LD and the microdata/Open Graph price, including the classic cents-vs-units (x100) error
- Variants (`ProductGroup` / `hasVariant`, AggregateOffer price range)

**SEO**: title and meta description length, H1, canonical, noindex (meta and `X-Robots-Tag`), hreflang, viewport, HTTPS and mixed content, image alt text, thin content, Open Graph, invalid JSON-LD, slow response, redirect chains.

### Input

`startUrls` (required), `maxPagesPerSite` (1 = only the listed pages; higher = crawl the same host), `productPagesOnly` (when crawling, save and charge only product pages).

### Output

One item per audited page: all SEO fields, `seoScore`, `issues[]`, `isProductPage`, `product` (source, title, brand, sku, gtin, mpn, price, currency, availability, imageUrl, variantsCount, priceCheck), `productIssues[]`, `productScore`, `merchantReady` and `fixList` (high first). Failed URLs are in **ERRORS**; totals in **SUMMARY**.

```json
{"url": "https://shop.example/p/blue-mug", "seoScore": 87, "productScore": 79, "merchantReady": false,
 "product": {"price": 12.5, "currency": "EUR", "availability": "in_stock", "gtin": "4006381333931"},
 "fixList": ["[medium] Offer has no availability (e.g. https://schema.org/InStock).", "[low] No brand (recommended for Merchant listings)."]}
```

### Limits

- It reads the HTML the server returns. Prices or schema injected later by JavaScript are not seen, which can show up as a missing-product warning.
- `merchantReady` follows Google's published Merchant listing fields; it is a checklist, not a guarantee that Google will accept the listing.
- Amazon and Google hosts are refused, and pages blocked by robots.txt are skipped.
- GTIN validation checks the check digit only. It cannot confirm that the number is registered to that product.

### Responsible crawling

We follow each site's **robots.txt** (disallowed pages are skipped and not charged), send at most about one request per second per site, use an honest User-Agent (`ShopAudit/1.0`) and never log in, use proxies or bypass bot protection. Amazon and Google hosts are refused. Audit shops you own or are allowed to analyse. Email addresses and phone numbers are not exported.

### Example input

```json
{
  "startUrls": [
    "https://woocommerce.com/products/woocommerce-subscriptions/"
  ],
  "maxPagesPerSite": 1
}
```

### Example output (one record, some fields shortened)

Real record from a test run on the input above (dates and values change over time).

```json
{
  "url": "https://woocommerce.com/products/woocommerce-subscriptions/",
  "httpStatus": 200,
  "https": true,
  "title": "WooCommerce Subscriptions - WooCommerce",
  "titleLength": 39,
  "metaDescriptionLength": 510,
  "h1Count": 1,
  "canonicalSelf": true,
  "noindex": false,
  "lang": "en-US",
  "structuredDataTypes": [
    "BreadcrumbList",
    "ImageObject",
    "ItemPage",
    "Organization",
    "Product",
    "WebPage",
    "WebSite"
  ],
  "imagesMissingAlt": 1,
  "seoScore": 90,
  "isProductPage": true,
  "product": {
    "source": "json-ld",
    "title": "WooCommerce Subscriptions",
    "brand": "Woo",
    "sku": "WOO508",
    "gtin": null,
    "mpn": null,
    "price": 279,
    "currency": "USD",
    "availability": "in_stock",
    "regularPrice": null,
    "priceMin": 279,
    "priceMax": 279,
    "imageUrl": "https://woocommerce.com/wp-content/uploads/2012/09/Woo_Subscriptions_icon-marketplace-160x160-2.png",
    "variantsCount": 0,
    "rating": {
      "value": 3.9,
      "count": 137
    },
    "priceCheck": {
      "status": "match",
      "comparedWith": [
        "opengraph"
      ]
    }
  },
  "productScore": 94,
  "merchantReady": true,
  "issues": [
    {
      "code": "meta-description-too-long",
      "severity": "low",
      "message": "Meta description is longer than 160 characters."
    },
    {
      "code": "images-missing-alt",
      "severity": "medium",
      "message": "Images without alt text."
    }
  ],
  "productIssues": [
    {
      "code": "product-identifier-missing",
      "severity": "low",
      "message": "No GTIN or MPN (recommended product identifiers)."
    },
    {
      "code": "product-shipping-missing",
      "severity": "low",
      "message": "No shippingDetails in the offer (Merchant listing enhancement)."
    }
  ]
}
```

### Pricing

| Event | Price |
|---|---|
| Page audited (HTML page fetched and analysed) | $0.005 |

Failed, robots-skipped and non-HTML URLs are free, and there is no start fee. A 200-product shop costs $1.00.

### Use it in n8n, Make or Zapier

Run it weekly on your product sitemap pages and alert when `merchantReady` turns false.

*Maintained by DigiVibeTech. Questions: [digivibetech.com/support](https://digivibetech.com/support/)*

# Actor input Schema

## `startUrls` (type: `array`):

Product, category or home pages of your shop (up to 1,000). Public pages only; robots.txt is respected. Amazon and Google hosts are refused.

## `maxPagesPerSite` (type: `integer`):

1 = audit only the listed pages. Higher = crawl internal links on the same host (breadth-first).

## `productPagesOnly` (type: `boolean`):

When crawling, save (and charge) only pages that look like product pages; other pages are scanned for links for free.

## Actor input object example

```json
{
  "startUrls": [
    "https://woocommerce.com/products/woocommerce-subscriptions/"
  ],
  "maxPagesPerSite": 1,
  "productPagesOnly": false
}
```

# Actor output Schema

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

All result items (overview view)

## `errors` (type: `string`):

Inputs that could not be processed, with the reason

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

Counts of processed, billed and failed items

# 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 = {
    "startUrls": [
        "https://woocommerce.com/products/woocommerce-subscriptions/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("digivibetech/shop-seo-product-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 = { "startUrls": ["https://woocommerce.com/products/woocommerce-subscriptions/"] }

# Run the Actor and wait for it to finish
run = client.actor("digivibetech/shop-seo-product-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 '{
  "startUrls": [
    "https://woocommerce.com/products/woocommerce-subscriptions/"
  ]
}' |
apify call digivibetech/shop-seo-product-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,digivibetech/shop-seo-product-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/FuSBcNEVd05U3ZvoD/builds/pSgbfM0zOdTq8Qt1b/openapi.json
