AI Meta Generator
Drafts meta titles and descriptions for products, categories, and CMS pages by calling Anthropic's Claude. Architected for catalog-scale runs:
- Two-block cacheable system prompt — typical batch run hits ~90% prompt-cache discount on input tokens
- Review queue — every suggestion lands in
byte8_seosuite_meta_suggestionfor editor approval before being written to the entity (override with auto-approve for trusted batches) - Three trigger paths — bulk CLI, in-context "Generate with AI" button, and a 30-min cron auto-generator
- Token usage tracked per row — input / cached / output, so you can size cost expectations per 1000 SKUs
How it works
┌──────────────────────┐
│ Trigger │ CLI · admin button · cron
└──────────┬───────────┘
↓
┌──────────────────────┐
│ PromptBuilder │ System blocks (cached) + user prompt (per entity)
└──────────┬───────────┘
↓
┌──────────────────────┐
│ AnthropicClient │ POST /v1/messages with cache_control: ephemeral
└──────────┬───────────┘
↓
┌──────────────────────┐
│ SuggestionParser │ Strict JSON parse + char-limit enforcement
└──────────┬───────────┘
↓
┌──────────────────────┐
│ Repository.save() │ byte8_seosuite_meta_suggestion (status=pending)
└──────────┬───────────┘
↓ if auto-approve
┌──────────────────────┐
│ SuggestionApplier │ Writes to product/category/cms.meta_title + meta_description
└──────────────────────┘
Prompt design
Two cacheable system blocks + one per-entity user prompt:
| Block | Content | Why it's cacheable |
|---|---|---|
| System block 1 | Framing rules, character limits, store name + locale, brand voice, global keywords, output JSON schema | Identical for every product in a batch |
| System block 2 | Entity-type specific rules (product / category / CMS) | Identical for every entity of the same type in a batch |
| User message | The current entity's source data as JSON | Unique per entity — never cached |
Both system blocks are sent with cache_control: { type: "ephemeral" }. After the first request, subsequent requests in the same batch return cache_read_input_tokens > 0, charged at ~10% of the normal input rate.
Output format
Claude is asked to return strict JSON:
{
"meta_title": "Acme Pro Runner — Lightweight road shoe | Sample Store",
"meta_description": "Acme Pro Runner: 220g neutral road shoe with 28mm stack. Free UK delivery, 30-day returns. Discover the range at Sample Store.",
"rationale": "Title leads with model + key differentiator (lightweight + road), suffix repeats brand. Description hits weight, stack height, and a trust signal."
}
The parser:
- Strips
```jsonfences if Claude adds them - Extracts the first balanced
{ … }object - Validates
meta_titleandmeta_descriptionaren't both empty (failure → status=failed,errorpopulated) - Enforces character limits via word-boundary truncation
Truncation cuts on the nearest space within 60% of the limit, then trims trailing punctuation.
Models
| Model | Best for |
|---|---|
claude-haiku-4-5 (default) | Bulk product runs, cost-sensitive catalogs |
claude-sonnet-4-6 | Hero categories, premium brand voice |
claude-opus-4-7 | One-shot generation for the 50 highest-traffic SKUs where copy quality matters most |
You can switch models per-store, or run a Haiku batch for the long tail and an Opus batch for top sellers via different --batch IDs.
Cost rough sizing
For Haiku 4.5 on a typical product (~600 chars description input):
- Input: ~700 tokens
- System prompt (cached after row 1): ~400 tokens
- Output: ~120 tokens
A 1000-SKU run with caching working as expected: roughly $0.50–$1.00. Without caching it would be 5–10× that.
Where suggestions go
Marketing → SEO Suite → AI Meta Suggestions — full grid with mass approve/reject/delete and per-row Approve & Apply / Reject. Filter by status, entity type, batch_id, model.
Next
- Configuration — every config flag explained
- Review queue — admin grid walkthrough
- In-context button — single-entity preview from edit forms
- CLI bulk generation —
seosuite:meta:generaterecipes - Cron auto-generation — set-and-forget for new SKUs