# Listing SEO Length Auditor for Online Sellers (`autoaugeo/listing-seo-length-auditor-for-online-se-8a73`) Actor

Checks listing text you provide against length rules: Etsy titles (140 characters), tags (13 tags, 20 characters each, duplicates) and Shopify meta title and description target lengths (60 and 155). Returns one result per listing with each issue found. No scraping, no rewriting.

- **URL**: https://apify.com/autoaugeo/listing-seo-length-auditor-for-online-se-8a73.md
- **Developed by:** [Augeo auto](https://apify.com/autoaugeo) (community)
- **Categories:** E-commerce, SEO tools, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 results

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

## Etsy and Shopify Listing Length Audit

Checks the listing text you pass in and tells you which fields are too long, missing or duplicated, with exact character counts.

- **Etsy listings:** title length, number of tags, length of each tag, duplicate tags.
- **Shopify listings:** meta title length and meta description length, against recommended target lengths.

The Actor reads only the JSON you give it. It makes no network request and opens no website.

Not affiliated with, endorsed by or sponsored by Etsy or Shopify.

### What it does not do

- It does not fetch or scrape Etsy or Shopify. It never opens a shop, a listing page or any other website. You paste or send the text yourself.
- It does not rewrite text. It reports what is over length, missing or duplicated; the edits are yours.
- It does not measure search ranking, traffic or sales, and passing every check says nothing about where a listing will appear in search.
- It does not check keywords, spelling, images, prices, categories or policy compliance.

### The exact rules

#### Etsy (limits)

| Field | Rule | Issue code | Severity |
| --- | --- | --- | --- |
| `title` | Must not be empty | `missing` | error |
| `title` | At most 140 characters | `over_limit` | error |
| `tags` | At most 13 tags | `too_many_tags` | error |
| `tags` | Fewer than 13 tags: the unused slots are counted | `unused_tag_slots` | info |
| each tag | At most 20 characters, spaces included | `tag_too_long` | error |
| `tags` | No tag twice, ignoring capital letters | `duplicate_tag` | error |

140, 13 and 20 are the limits of Etsy's listing form, reported with `"limit_kind": "platform_limit"`.

#### Shopify (recommended target lengths, not platform limits)

| Field | Rule | Issue code | Severity |
| --- | --- | --- | --- |
| `meta_title` | Must not be empty | `missing` | error |
| `meta_title` | Recommended target length: at most 60 characters | `over_target_length` | warning |
| `meta_description` | Must not be empty | `missing` | error |
| `meta_description` | Recommended target length: at most 155 characters | `over_target_length` | warning |

60 and 155 are recommended target lengths chosen by this Actor to reduce the chance that a search engine cuts the text short. They are not Shopify field limits: Shopify accepts longer text, and a search engine may still shorten or replace text that is within the target. They are reported with `"limit_kind": "recommended_target"`.

#### How characters are counted

- Leading and trailing spaces are removed before counting.
- Characters are counted by Unicode code point, so a simple emoji counts as one character. An emoji built from several code points (a flag, a skin-tone variant) counts as more than one.
- Inside a tag, runs of spaces are collapsed to one space. Empty tags are dropped.
- `tags` may be an array of strings or one string separated by commas or new lines.
- `platform` is not case-sensitive. Any value other than `etsy` or `shopify` returns one `unknown_platform` issue and no other check is run.

Rules are verified by an automated fixtures script (tests/run_fixtures.js).

### Input

One field, `listings`: an array of 1 to 1000 listing objects.

| Field | Used for | Type | Notes |
| --- | --- | --- | --- |
| `platform` | both | string | `"etsy"` or `"shopify"`. Required. |
| `id` | both | string or number | Optional. Copied to the output unchanged. |
| `title` | Etsy | string | The listing title. For Shopify it is only counted, not checked. |
| `tags` | Etsy | array of strings, or one string | Comma or new-line separated when a string. |
| `meta_title` | Shopify | string | The page title of the search engine listing. |
| `meta_description` | Shopify | string | The meta description of the search engine listing. |

Example input:

```json
{
  "listings": [
    {
      "id": "etsy-example-1",
      "platform": "etsy",
      "title": "Hand-poured soy candle, lavender and cedar, 8 oz amber jar",
      "tags": [
        "soy candle",
        "lavender candle",
        "cedar candle",
        "amber jar candle",
        "hand poured candle",
        "scented candle",
        "gift for her",
        "housewarming gift",
        "cozy home decor",
        "vegan candle",
        "8 oz candle",
        "relaxing candle"
      ]
    },
    {
      "id": "shopify-example-1",
      "platform": "shopify",
      "title": "Linen Cross-Back Apron",
      "meta_title": "Linen Cross-Back Apron with Two Pockets, Hand-Sewn, One Size, Oat",
      "meta_description": "Cross-back linen apron with two front pockets. Hand-sewn, one size, oat colour. Machine washable."
    }
  ]
}
```

The products in this example are invented.

If `listings` is missing, is not an array, is empty or holds more than 1000 items, the run fails with a message that says why, writes nothing and charges nothing.

### Output

One dataset item per listing, in the order you sent them.

| Field | Meaning |
| --- | --- |
| `id` | The `id` you sent, or `null`. |
| `platform` | The platform in lower case, or `null` when none was given. |
| `ok` | `true` when the listing has no `error` and no `warning`. `info` notes do not make it `false`. |
| `issues` | A list of findings. Each has `field`, `code`, `severity` (`error`, `warning` or `info`), a plain-English `message`, `actual` (the measured value), `limit` (the number it was compared with) and `limit_kind` (`platform_limit` or `recommended_target`). |
| `counts` | `title_chars`, `tag_count`, `longest_tag_chars`, `meta_title_chars`, `meta_description_chars`. |

Example output for the input above:

```json
[
  {
    "id": "etsy-example-1",
    "platform": "etsy",
    "ok": true,
    "issues": [
      {
        "field": "tags",
        "code": "unused_tag_slots",
        "severity": "info",
        "message": "Listing has 12 tags; 1 of the 13 tag slots are unused.",
        "actual": 12,
        "limit": 13,
        "limit_kind": "platform_limit"
      }
    ],
    "counts": {
      "title_chars": 58,
      "tag_count": 12,
      "longest_tag_chars": 18,
      "meta_title_chars": 0,
      "meta_description_chars": 0
    }
  },
  {
    "id": "shopify-example-1",
    "platform": "shopify",
    "ok": false,
    "issues": [
      {
        "field": "meta_title",
        "code": "over_target_length",
        "severity": "warning",
        "message": "Shopify meta title is 65 characters, over the recommended 60-character target length by 5; search results may truncate it. This is a recommended length, not a Shopify field limit.",
        "actual": 65,
        "limit": 60,
        "limit_kind": "recommended_target"
      }
    ],
    "counts": {
      "title_chars": 22,
      "tag_count": 0,
      "longest_tag_chars": 0,
      "meta_title_chars": 65,
      "meta_description_chars": 97
    }
  }
]
```

### Price per result

This Actor is pay per result. One `result` event is charged for each listing written to the dataset, so a run that audits 50 listings is charged 50 results. The price of one result is the amount shown on the Pricing tab of this Actor's page in the Apify Store. A run that fails input validation charges nothing. If you set a maximum charge for a run and it is reached, the run stops early and its status message says how many listings were audited.

### Data and privacy

The Actor keeps no data of its own. Results are written to the default dataset of your run in your Apify account, under your account's retention settings. Do not put personal data in the input; the checks need only listing text.

### About

The code, the rules table and this README were drafted with AI assistance.

# Actor input Schema

## `listings` (type: `array`):

1 to 1000 listing objects. Every listing needs "platform": "etsy" or "shopify". Etsy listings use "title" and "tags" (an array, or one comma-separated string). Shopify listings use "meta_title" and "meta_description". "id" is optional and is copied to the output so you can match results to your own records.

## Actor input object example

```json
{
  "listings": [
    {
      "id": "etsy-example-1",
      "platform": "etsy",
      "title": "Hand-poured soy candle, lavender and cedar, 8 oz amber jar",
      "tags": [
        "soy candle",
        "lavender candle",
        "cedar candle",
        "amber jar candle",
        "hand poured candle",
        "scented candle",
        "gift for her",
        "housewarming gift",
        "cozy home decor",
        "vegan candle",
        "8 oz candle",
        "relaxing candle"
      ]
    },
    {
      "id": "shopify-example-1",
      "platform": "shopify",
      "title": "Linen Cross-Back Apron",
      "meta_title": "Linen Cross-Back Apron with Two Pockets, Hand-Sewn, One Size, Oat",
      "meta_description": "Cross-back linen apron with two front pockets. Hand-sewn, one size, oat colour. Machine washable."
    }
  ]
}
```

# Actor output Schema

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

No description

# 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 = {
    "listings": [
        {
            "id": "etsy-example-1",
            "platform": "etsy",
            "title": "Hand-poured soy candle, lavender and cedar, 8 oz amber jar",
            "tags": [
                "soy candle",
                "lavender candle",
                "cedar candle",
                "amber jar candle",
                "hand poured candle",
                "scented candle",
                "gift for her",
                "housewarming gift",
                "cozy home decor",
                "vegan candle",
                "8 oz candle",
                "relaxing candle"
            ]
        },
        {
            "id": "shopify-example-1",
            "platform": "shopify",
            "title": "Linen Cross-Back Apron",
            "meta_title": "Linen Cross-Back Apron with Two Pockets, Hand-Sewn, One Size, Oat",
            "meta_description": "Cross-back linen apron with two front pockets. Hand-sewn, one size, oat colour. Machine washable."
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("autoaugeo/listing-seo-length-auditor-for-online-se-8a73").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 = { "listings": [
        {
            "id": "etsy-example-1",
            "platform": "etsy",
            "title": "Hand-poured soy candle, lavender and cedar, 8 oz amber jar",
            "tags": [
                "soy candle",
                "lavender candle",
                "cedar candle",
                "amber jar candle",
                "hand poured candle",
                "scented candle",
                "gift for her",
                "housewarming gift",
                "cozy home decor",
                "vegan candle",
                "8 oz candle",
                "relaxing candle",
            ],
        },
        {
            "id": "shopify-example-1",
            "platform": "shopify",
            "title": "Linen Cross-Back Apron",
            "meta_title": "Linen Cross-Back Apron with Two Pockets, Hand-Sewn, One Size, Oat",
            "meta_description": "Cross-back linen apron with two front pockets. Hand-sewn, one size, oat colour. Machine washable.",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("autoaugeo/listing-seo-length-auditor-for-online-se-8a73").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 '{
  "listings": [
    {
      "id": "etsy-example-1",
      "platform": "etsy",
      "title": "Hand-poured soy candle, lavender and cedar, 8 oz amber jar",
      "tags": [
        "soy candle",
        "lavender candle",
        "cedar candle",
        "amber jar candle",
        "hand poured candle",
        "scented candle",
        "gift for her",
        "housewarming gift",
        "cozy home decor",
        "vegan candle",
        "8 oz candle",
        "relaxing candle"
      ]
    },
    {
      "id": "shopify-example-1",
      "platform": "shopify",
      "title": "Linen Cross-Back Apron",
      "meta_title": "Linen Cross-Back Apron with Two Pockets, Hand-Sewn, One Size, Oat",
      "meta_description": "Cross-back linen apron with two front pockets. Hand-sewn, one size, oat colour. Machine washable."
    }
  ]
}' |
apify call autoaugeo/listing-seo-length-auditor-for-online-se-8a73 --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,autoaugeo/listing-seo-length-auditor-for-online-se-8a73"
        }
    }
}
```

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/r43WIw01ovDW6RZf5/builds/2VK0Ue9ceCEJqLFlq/openapi.json
