# Catalog SEO Planner (`autosecurelogin/catalog-seo-planner`) Actor

Reviewable English product-title, meta-description and metadata-derived alt-text plans. Up to 100 supplied records; no store writes or model key.

- **URL**: https://apify.com/autosecurelogin/catalog-seo-planner.md
- **Developed by:** [Hunter Melnick](https://apify.com/autosecurelogin) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.05 / actor start

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

## Catalog SEO Planner

Turn your English product records into a reviewable plan for product titles,
meta descriptions and image alt text. Uses supplied text with deterministic
rules; no model key, store credentials or additional subscription is required.

### Start

1. Keep the sample Product records to try the example, or paste your own JSON array.
2. Supply 1-100 products, each with a unique `id` and nonblank `title`.
3. Optionally provide acronyms to preserve and a handle prefix to exclude.
4. Run the Actor. Open **Complete plan and skip summary**, then the **OUTPUT** JSON file, for the full report and
   **Proposed changes** for the downloadable results table.
5. Review each before/after value before applying changes with your own store tools.

### Price

**$0.05 per run**, charged once when the Actor starts. Up to 100 products and
all proposed changes are included; no extra per-result charge or platform-usage
surcharge. The run uses 128 MB. Set your maximum cost per run to at least $0.05.
The start charge also applies when input is rejected or no changes are needed,
so validate your records against the limits below before starting.

### Accepted data

The full input is a JSON object with `products`, optional `acronyms` (at most 100,
30 characters each), and optional `skipHandlePrefix` (at most 100 characters).
Maximum serialized input is 1 MiB. The supported product fields are:

| Field | Meaning |
|---|---|
| `id` | Unique nonempty string (200 characters max) or safe integer |
| `title` | Required nonblank product title, at most 1,000 characters |
| `handle`, `vendor`, `category`, `productType` | Optional strings, at most 1,000 characters |
| `titleTag`, `metaDescription` | Existing SEO text, at most 1,000 characters |
| `seo` | Optional object with `title` and/or `description` strings |
| `description`, `descriptionHtml` | Optional supplied copy, at most 10,000 characters |
| `images` | Up to 20 objects with optional `id`, `alt`, `altText` |

Omit optional values that are unknown. `null`, unsupported fields, duplicate
product IDs and out-of-limit inputs are rejected. Image alt strings have a
1,000-character limit; image IDs use the same string/safe-integer format as IDs.

### Results

The complete JSON plan includes `titles`, `metas`, `alts` and an overall `summary`.
Each section contains proposed before/after changes and relevant skip counts.
Unresolved shared titles remain explicit instead of being silently overwritten.
The dataset contains one row per proposed change, labeled with its section.
An empty dataset can be a successful run with no changes; read the full plan.

Existing populated image alt text is preserved. The included two-product sample
produces one title change, two meta descriptions and two alt-text suggestions.
Applying those suggestions and running again produces no additional changes.

### Limits and privacy

- English text heuristics only; no translation or search-ranking guarantee.
- Image alt text comes from metadata, not image recognition. Review it against
  the actual image before publication.
- No websites are fetched and no changes are written to a store.
- Input and output are stored in your Apify run storage under Apify's retention
  and access controls. Supply only authorized records; remove data when no longer needed.
- The hosted result does not grant redistribution rights to the implementation.

### Support

Open an issue from this Actor's page with a minimal non-sensitive reproduction,
the run ID, expected behavior and actual behavior. Do not post passwords, API
keys, private exports or customer information.

# Actor input Schema

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

1–100 product records; each requires id and title. See README for allowed fields.

## `acronyms` (type: `array`):

Up to 100 acronyms, each at most 30 characters.

## `skipHandlePrefix` (type: `string`):

Optional handle prefix to exclude.

## Actor input object example

```json
{
  "products": [
    {
      "id": "p1",
      "handle": "garden-bed",
      "title": "CEDAR RAISED GARDEN BED | TOOL-FREE CORNERS | 4 PACK",
      "category": "Garden > Raised Garden Beds",
      "vendor": "Acme",
      "description": "Cedar panels form a raised garden bed with interlocking corners for simple assembly. The natural wood panels create a defined planting space for flowers and vegetables. Free shipping on all orders.",
      "images": [
        {},
        {}
      ]
    },
    {
      "id": "p2",
      "title": "Steel Garden Pruner with Comfortable Handle",
      "description": "A compact garden pruner with a comfortable handle and steel blade for everyday garden care. The shape provides a secure grip for controlled pruning of small stems.",
      "images": [
        {
          "altText": "Pruner resting on a garden bench"
        }
      ]
    }
  ],
  "acronyms": [
    "UV"
  ]
}
```

# Actor output Schema

## `plan` (type: `string`):

Full before/after plan, counts, skip reasons and unresolved title collisions. Check this even when the changes dataset is empty.

## `changes` (type: `string`):

One row per proposed title, meta description or image alt-text change. An empty dataset means no changes were proposed; consult the complete plan.

# 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": [
        {
            "id": "p1",
            "handle": "garden-bed",
            "title": "CEDAR RAISED GARDEN BED | TOOL-FREE CORNERS | 4 PACK",
            "category": "Garden > Raised Garden Beds",
            "vendor": "Acme",
            "description": "Cedar panels form a raised garden bed with interlocking corners for simple assembly. The natural wood panels create a defined planting space for flowers and vegetables. Free shipping on all orders.",
            "images": [
                {},
                {}
            ]
        },
        {
            "id": "p2",
            "title": "Steel Garden Pruner with Comfortable Handle",
            "description": "A compact garden pruner with a comfortable handle and steel blade for everyday garden care. The shape provides a secure grip for controlled pruning of small stems.",
            "images": [
                {
                    "altText": "Pruner resting on a garden bench"
                }
            ]
        }
    ],
    "acronyms": [
        "UV"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("autosecurelogin/catalog-seo-planner").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": [
        {
            "id": "p1",
            "handle": "garden-bed",
            "title": "CEDAR RAISED GARDEN BED | TOOL-FREE CORNERS | 4 PACK",
            "category": "Garden > Raised Garden Beds",
            "vendor": "Acme",
            "description": "Cedar panels form a raised garden bed with interlocking corners for simple assembly. The natural wood panels create a defined planting space for flowers and vegetables. Free shipping on all orders.",
            "images": [
                {},
                {},
            ],
        },
        {
            "id": "p2",
            "title": "Steel Garden Pruner with Comfortable Handle",
            "description": "A compact garden pruner with a comfortable handle and steel blade for everyday garden care. The shape provides a secure grip for controlled pruning of small stems.",
            "images": [{ "altText": "Pruner resting on a garden bench" }],
        },
    ],
    "acronyms": ["UV"],
}

# Run the Actor and wait for it to finish
run = client.actor("autosecurelogin/catalog-seo-planner").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": [
    {
      "id": "p1",
      "handle": "garden-bed",
      "title": "CEDAR RAISED GARDEN BED | TOOL-FREE CORNERS | 4 PACK",
      "category": "Garden > Raised Garden Beds",
      "vendor": "Acme",
      "description": "Cedar panels form a raised garden bed with interlocking corners for simple assembly. The natural wood panels create a defined planting space for flowers and vegetables. Free shipping on all orders.",
      "images": [
        {},
        {}
      ]
    },
    {
      "id": "p2",
      "title": "Steel Garden Pruner with Comfortable Handle",
      "description": "A compact garden pruner with a comfortable handle and steel blade for everyday garden care. The shape provides a secure grip for controlled pruning of small stems.",
      "images": [
        {
          "altText": "Pruner resting on a garden bench"
        }
      ]
    }
  ],
  "acronyms": [
    "UV"
  ]
}' |
apify call autosecurelogin/catalog-seo-planner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,autosecurelogin/catalog-seo-planner"
        }
    }
}
```

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/DaEDVH2wtzoAOu3hI/builds/1wIA408xYnFOXmphc/openapi.json
