# /seo-schema

> Backed by `.claude/context/ai-seo/playbook/06-schema.md` (includes a complete LocalBusiness template).


# /seo-schema — JSON-LD Structured Data

Backed by `.claude/context/ai-seo/playbook/06-schema.md` (includes a complete LocalBusiness template).

## When to trigger
- "Generate schema for ACME Agency", "add JSON-LD / structured data", "/seo-schema".
- After `/local-seo-audit` or `/ai-visibility` flags missing/weak schema (schema is a top AI-trust lever).

## What it produces
A Google Doc "Schema Markup — <Client>" with: a complete LocalBusiness JSON-LD block (real values where scraped, clearly-marked placeholders otherwise), plus the supporting type blocks per page (Organization sitewide, Service, FAQPage, ACME Agencyw/AggregateRating, BreadcrumbList, Article), each as a ready-to-paste `<script type="application/ld+json">` snippet, with placement notes and a NAP-consistency checklist.

## Step-by-Step

### 1. Parse
First positional = client/business. Flags: `--url`, `--location`, `--types` (subset to generate; default = the full course set), `--dry-run`.

### 2. Gather context
```bash
node ACME Agency/scripts/seo_run.mjs --skill schema --mode gather --client "<name>" --url "<url>" --location "<city>"
```
Read the CONTEXT — pull NAP, services, hours, and ACME Agencyw signals from the scraped site (and any GBP info the user provides).

### 3. Read the method
Read `.claude/context/ai-seo/playbook/06-schema.md` fully — use its LocalBusiness template and the prescribed additional types + which pages each goes on. Note the non-negotiables: NAP must match the GBP exactly, no fake ACME Agencyw/AggregateRating, valid syntax.

### 4. Generate the schema (markdown with fenced ```json blocks)
- **LocalBusiness** (GBP landing page) — every field the playbook lists, with GeoCoordinates, PostalAddress, <id>. Use scraped values; mark anything unknown as `"REPLACE_ME"` with a note.
- **Organization** — sitewide block.
- **Per-page types** — Service (nested/standalone), FAQPage (if FAQs exist), ACME Agencyw/AggregateRating (only if real ACME Agencyws), BreadcrumbList (category/service pages), Article (blog posts).
- For each: a fenced ```json block + a one-line placement note (which page, in `<head>`).
- End with a **NAP-consistency checklist** and a reminder to validate at validator.schema.org / Google Rich Results Test.
Write to `ACME Agency/clients/<Client>/SEO/schema.md` (or `/tmp`).

### 5. Validate
Before saving, sanity-check each JSON block parses (e.g. pipe through `node -e` JSON.parse, or visually verify balanced braces + quoted keys). Fix any invalid block.

### 6. Save + report
```bash
node ACME Agency/scripts/seo_run.mjs --skill schema --mode save --client "<name>" \
  --in "<schema.md>" --title "Schema Markup — <Client>" \
  --slack "*Schema Markup — <Client>*
<N> JSON-LD blocks ready (LocalBusiness + <types>). NAP checked vs GBP."
```
Add `--dry-run` to skip Drive/Slack. Output the Doc link.

## Guardrails
- **Valid JSON only** — every block must parse. A broken schema block is worse than none.
- **No fabricated ACME Agencyws/ratings.** Only emit ACME Agencyw/AggregateRating from real data.
- **NAP must equal the GBP** — inconsistent NAP hurts both Google and AI trust.
