optbrew 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +6 -0
- package/.claude-plugin/plugin.json +6 -0
- package/.codex-plugin/plugin.json +13 -0
- package/CHANGELOG.md +20 -0
- package/LICENSE +21 -0
- package/README.ko.md +73 -0
- package/README.md +72 -2
- package/THIRD_PARTY_NOTICES.md +10 -0
- package/bin/optbrew.mjs +4 -0
- package/docs/platforms.md +31 -0
- package/docs/release.md +14 -0
- package/lib/cli.mjs +103 -0
- package/lib/doctor.mjs +44 -0
- package/lib/install.mjs +158 -0
- package/lib/paths.mjs +30 -0
- package/lib/records.mjs +44 -0
- package/lib/transaction.mjs +205 -0
- package/lib/update.mjs +181 -0
- package/package.json +39 -4
- package/plugin.json +13 -0
- package/skills/optbrew/LICENSE +21 -0
- package/skills/optbrew/SKILL.md +17 -0
- package/skills/optbrew/THIRD_PARTY_NOTICES.md +10 -0
- package/skills/optbrew/agents/openai.yaml +4 -0
- package/skills/optbrew/bundle-manifest.json +663 -0
- package/skills/optbrew/licenses/firecrawl-seo-audit.txt +15 -0
- package/skills/optbrew/licenses/magnus-seo.txt +21 -0
- package/skills/optbrew/licenses/marketing-search.txt +21 -0
- package/skills/optbrew/licenses/mblode-seo.txt +21 -0
- package/skills/optbrew/licenses/naver-searchadvisor.txt +29 -0
- package/skills/optbrew/licenses/seranking-seo.txt +21 -0
- package/skills/optbrew/modules/firecrawl-seo-audit/GUIDE.md +64 -0
- package/skills/optbrew/modules/magnus-seo/GUIDE.md +79 -0
- package/skills/optbrew/modules/magnus-seo/README.md +45 -0
- package/skills/optbrew/modules/magnus-seo/assets/audit-report-template.md +76 -0
- package/skills/optbrew/modules/magnus-seo/references/aeo-methodology.md +105 -0
- package/skills/optbrew/modules/magnus-seo/references/agent-readable-content.md +28 -0
- package/skills/optbrew/modules/magnus-seo/references/content-and-entity-architecture.md +100 -0
- package/skills/optbrew/modules/magnus-seo/references/content-strategy-seo.md +142 -0
- package/skills/optbrew/modules/magnus-seo/references/discovery-and-freshness.md +47 -0
- package/skills/optbrew/modules/magnus-seo/references/evidence-boundaries.md +75 -0
- package/skills/optbrew/modules/magnus-seo/references/ghost-metadata.md +204 -0
- package/skills/optbrew/modules/magnus-seo/references/implementation-playbook.md +114 -0
- package/skills/optbrew/modules/magnus-seo/references/measurement-and-experimentation.md +47 -0
- package/skills/optbrew/modules/magnus-seo/references/onpage-seo.md +154 -0
- package/skills/optbrew/modules/magnus-seo/references/platform-guidance.md +30 -0
- package/skills/optbrew/modules/magnus-seo/references/schema-markup.md +244 -0
- package/skills/optbrew/modules/magnus-seo/references/source-index.md +36 -0
- package/skills/optbrew/modules/magnus-seo/references/structured-data.md +56 -0
- package/skills/optbrew/modules/magnus-seo/references/technical-seo.md +99 -0
- package/skills/optbrew/modules/magnus-seo/scripts/aeo_audit.py +158 -0
- package/skills/optbrew/modules/magnus-seo/scripts/build_prompt_matrix.py +52 -0
- package/skills/optbrew/modules/magnus-seo/templates/aeo-implementation-plan.md +53 -0
- package/skills/optbrew/modules/magnus-seo/templates/citation-observation-log.md +16 -0
- package/skills/optbrew/modules/magnus-seo/templates/llms.txt.template +15 -0
- package/skills/optbrew/modules/magnus-seo/templates/question-cluster.md +27 -0
- package/skills/optbrew/modules/magnus-seo/templates/robots-ai-crawlers.txt +23 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/GUIDE.md +483 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/agent-readiness.md +57 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/citations-vs-recommendations.md +85 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/content-patterns.md +287 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/content-types.md +71 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/format-volatility.md +98 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/okf.md +104 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/platform-ranking-factors.md +154 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/youtube-ai-citations.md +60 -0
- package/skills/optbrew/modules/marketing-search/skills/analytics/GUIDE.md +303 -0
- package/skills/optbrew/modules/marketing-search/skills/analytics/references/event-library.md +260 -0
- package/skills/optbrew/modules/marketing-search/skills/analytics/references/ga4-implementation.md +300 -0
- package/skills/optbrew/modules/marketing-search/skills/analytics/references/gtm-implementation.md +390 -0
- package/skills/optbrew/modules/marketing-search/skills/content-strategy/GUIDE.md +432 -0
- package/skills/optbrew/modules/marketing-search/skills/content-strategy/references/content-distribution.md +83 -0
- package/skills/optbrew/modules/marketing-search/skills/content-strategy/references/headless-cms.md +194 -0
- package/skills/optbrew/modules/marketing-search/skills/programmatic-seo/GUIDE.md +231 -0
- package/skills/optbrew/modules/marketing-search/skills/programmatic-seo/references/playbooks.md +308 -0
- package/skills/optbrew/modules/marketing-search/skills/schema/GUIDE.md +172 -0
- package/skills/optbrew/modules/marketing-search/skills/schema/references/schema-examples.md +398 -0
- package/skills/optbrew/modules/marketing-search/skills/seo-audit/GUIDE.md +492 -0
- package/skills/optbrew/modules/marketing-search/skills/seo-audit/references/ai-writing-detection.md +200 -0
- package/skills/optbrew/modules/marketing-search/skills/seo-audit/references/international-seo.md +230 -0
- package/skills/optbrew/modules/marketing-search/skills/site-architecture/GUIDE.md +350 -0
- package/skills/optbrew/modules/marketing-search/skills/site-architecture/references/mermaid-templates.md +216 -0
- package/skills/optbrew/modules/marketing-search/skills/site-architecture/references/navigation-patterns.md +305 -0
- package/skills/optbrew/modules/marketing-search/skills/site-architecture/references/site-type-templates.md +293 -0
- package/skills/optbrew/modules/mblode-seo/GUIDE.md +74 -0
- package/skills/optbrew/modules/mblode-seo/references/answer-engines.md +58 -0
- package/skills/optbrew/modules/mblode-seo/references/audit.md +78 -0
- package/skills/optbrew/modules/mblode-seo/references/brief-template.md +47 -0
- package/skills/optbrew/modules/mblode-seo/references/monitoring.md +56 -0
- package/skills/optbrew/modules/mblode-seo/references/nextjs-implementation.md +65 -0
- package/skills/optbrew/modules/mblode-seo/references/research-protocol.md +37 -0
- package/skills/optbrew/modules/mblode-seo/references/sources.md +47 -0
- package/skills/optbrew/modules/mblode-seo/references/validation-evidence.md +21 -0
- package/skills/optbrew/modules/naver-searchadvisor/GUIDE.md +75 -0
- package/skills/optbrew/modules/naver-searchadvisor/NOTICE.md +59 -0
- package/skills/optbrew/modules/naver-searchadvisor/references/INDEX.md +97 -0
- package/skills/optbrew/modules/naver-searchadvisor/scripts/audit.mjs +714 -0
- package/skills/optbrew/modules/naver-searchadvisor/scripts/robots.mjs +77 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-ai-search-share-of-voice/GUIDE.md +94 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-api/GUIDE.md +186 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-api/references/api-surface-map.md +207 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-api/references/auth-and-keys.md +182 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-api/references/integration-patterns.md +283 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-api/references/rate-limits-and-credits.md +235 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-competitor-gap-analysis/GUIDE.md +117 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-content-audit/GUIDE.md +155 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-content-audit/references/cite.md +84 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-content-audit/references/core-eeat.md +147 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-content-audit/templates/verdict.md +63 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-firecrawl/GUIDE.md +141 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-firecrawl/references/preflight.md +73 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-geo/GUIDE.md +159 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/GUIDE.md +393 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/assets/templates/cwv-audit-report.md +48 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/assets/templates/gsc-performance-report.md +44 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/assets/templates/indexation-status-report.md +43 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/auth-setup.md +160 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/cross-skill-integration.md +187 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/ga4-data-api.md +184 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/indexing-api.md +109 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/keyword-planner-api.md +66 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/nlp-api.md +55 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/pagespeed-crux-api.md +204 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/rate-limits-quotas.md +75 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/search-console-api.md +156 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/supplementary-apis.md +99 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/youtube-api.md +49 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-keyword-niche/GUIDE.md +174 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-page/GUIDE.md +174 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-plan/GUIDE.md +220 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/GUIDE.md +135 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/references/google-rich-results.md +89 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/templates/article.json +23 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/templates/breadcrumb-list.json +18 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/templates/faq-page.json +22 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/templates/local-business.json +32 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/templates/product.json +25 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-sitemap/GUIDE.md +128 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-technical-audit/GUIDE.md +235 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-technical-audit/references/severity-mapping.md +133 -0
- package/skills/optbrew/references/api.md +45 -0
- package/skills/optbrew/references/check-registry.json +28 -0
- package/skills/optbrew/references/evidence.md +9 -0
- package/skills/optbrew/references/intake.md +9 -0
- package/skills/optbrew/references/measurement.md +29 -0
- package/skills/optbrew/references/policies.md +7 -0
- package/skills/optbrew/references/profiles.json +13 -0
- package/skills/optbrew/references/remediations.json +12 -0
- package/skills/optbrew/references/report.md +25 -0
- package/skills/optbrew/references/routing.md +15 -0
- package/skills/optbrew/references/schemas/contract.schema.json +51 -0
- package/skills/optbrew/references/scoring.md +62 -0
- package/skills/optbrew/scripts/adapters/anthropic.mjs +116 -0
- package/skills/optbrew/scripts/adapters/imports.mjs +81 -0
- package/skills/optbrew/scripts/audit.mjs +145 -0
- package/skills/optbrew/scripts/cli.mjs +41 -0
- package/skills/optbrew/scripts/core/bootstrap.mjs +31 -0
- package/skills/optbrew/scripts/core/bundle.mjs +73 -0
- package/skills/optbrew/scripts/core/capabilities.mjs +19 -0
- package/skills/optbrew/scripts/core/collector.mjs +236 -0
- package/skills/optbrew/scripts/core/compare.mjs +47 -0
- package/skills/optbrew/scripts/core/contracts.mjs +144 -0
- package/skills/optbrew/scripts/core/cost-ledger.mjs +95 -0
- package/skills/optbrew/scripts/core/findings.mjs +54 -0
- package/skills/optbrew/scripts/core/metrics.mjs +97 -0
- package/skills/optbrew/scripts/core/protocol.mjs +125 -0
- package/skills/optbrew/scripts/core/report.mjs +652 -0
- package/skills/optbrew/scripts/core/scope.mjs +52 -0
- package/skills/optbrew/scripts/core/score.mjs +71 -0
- package/skills/optbrew/scripts/core/weights.mjs +139 -0
- package/skills/optbrew/source-lock.json +2686 -0
- package/source-lock.json +2686 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
> Example output: examples/seo-schema-budgetbytes-slow-cooker-chicken-noodle-soup-20260514/SCHEMA.md (upstream-only reference; route through optbrew)
|
|
2
|
+
|
|
3
|
+
# Schema Markup
|
|
4
|
+
|
|
5
|
+
Detect, validate, and generate Schema.org JSON-LD for a page. Output is paste-ready `<script>` blocks the user can drop into their CMS or page template, plus a validation report on what's currently present and what's broken.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- **Required for detect/validate paths:** `mcp__firecrawl-mcp__firecrawl_scrape` (raw HTML access). WebFetch returns markdown only — every `<script type="application/ld+json">` block is stripped before the skill ever sees it. Without Firecrawl, the skill can still generate new schema from intent detection (steps 4–6) but cannot detect or validate what's already on the page (steps 2–3, 7).
|
|
10
|
+
- Optional: SE Ranking MCP server (used in step 7 for benchmarking competitor schema).
|
|
11
|
+
- User provides: a target URL. Optionally a hint about page intent ("this is a product page", "this is a how-to") if the URL pattern doesn't make it obvious.
|
|
12
|
+
|
|
13
|
+
## Process
|
|
14
|
+
|
|
15
|
+
1. **Fetch HTML** `mcp__firecrawl-mcp__firecrawl_scrape` (preferred) or degrade
|
|
16
|
+
- **Cost note.** Firecrawl: 1 credit for the target URL, +10 credits if step 7 (competitor benchmark) runs (1 per top-10 SERP result). User may pass `--no-firecrawl` to force the degraded path (generate-only mode) for credit conservation.
|
|
17
|
+
- **If Firecrawl available:** scrape the target URL. For SPAs, pass `waitFor: 2000` (or a CSS selector for the main content) so the JS-rendered DOM is captured. Use the response's `html` for JSON-LD parsing in step 2 and `metadata` for canonical/robots cross-reference.
|
|
18
|
+
- **If Firecrawl unavailable:** skip steps 2, 3, and 7 entirely (they all need raw HTML). Steps 4–6 still run — the skill becomes "generate-only", producing recommended JSON-LD blocks from intent detection without comparing to what's on the page. Surface clearly in `SCHEMA.md`: `Existing-schema detection: skipped — Firecrawl required (WebFetch returns markdown only). Install via optbrew capability setup (see top-level routing).`
|
|
19
|
+
- Even with Firecrawl: if JSON-LD blocks appear only after JS render, flag in the output: "JS-rendered schema may not be detected by all crawlers — server-side render JSON-LD where possible."
|
|
20
|
+
|
|
21
|
+
2. **Detect existing schema** (requires Firecrawl HTML from step 1)
|
|
22
|
+
- From the returned `html`: extract every `<script type="application/ld+json">` block.
|
|
23
|
+
- Parse each as JSON. Report syntax errors.
|
|
24
|
+
- List each detected `@type`.
|
|
25
|
+
- Also detect Microdata (`itemscope`/`itemprop`) and RDFa (`typeof`/`property`) — flag as legacy and recommend migration to JSON-LD (Google's stated preference).
|
|
26
|
+
- **If step 1 degraded:** skip this step. Record `Existing-schema detection skipped` in `01-detected.md`.
|
|
27
|
+
|
|
28
|
+
3. **Validate against Google's spec**
|
|
29
|
+
- Load `references/google-rich-results.md`.
|
|
30
|
+
- For each detected `@type`, check required and recommended properties.
|
|
31
|
+
- Surface common errors: missing `@context`, dates not in ISO 8601, prices as numbers instead of strings, `availability` as plain text instead of schema.org URL, telephone not in international format.
|
|
32
|
+
|
|
33
|
+
4. **Detect page intent**
|
|
34
|
+
- From URL pattern (`/blog/`, `/products/`, `/contact/`, `/how-to/`, `/faq/`).
|
|
35
|
+
- From `<title>` and `<h1>` tone.
|
|
36
|
+
- From content signals (numbered list of steps → HowTo; visible Q&A blocks → FAQPage; price + buy button → Product; address + hours → LocalBusiness).
|
|
37
|
+
- If multiple intents detected, generate schema for each.
|
|
38
|
+
|
|
39
|
+
5. **Generate missing JSON-LD**
|
|
40
|
+
- For each detected intent without matching valid schema, load the relevant template from `templates/`:
|
|
41
|
+
- `article.json` — for editorial/blog content
|
|
42
|
+
- `product.json` — for product/SKU pages
|
|
43
|
+
- `local-business.json` — for brick-and-mortar landing pages
|
|
44
|
+
- `faq-page.json` — for explicit Q&A blocks (gov/health allowlist only — see references/google-rich-results.md)
|
|
45
|
+
- `breadcrumb-list.json` — for any page with breadcrumb navigation
|
|
46
|
+
- Fill template fields from the live HTML (title → headline, h2s → mainEntity questions, etc.).
|
|
47
|
+
- Mark any field that couldn't be auto-filled as `{REPLACE: ...}` so the user knows to complete it.
|
|
48
|
+
- **Don't generate `HowTo`** — Google retired HowTo rich results in September 2023 (mobile + desktop). The schema can still ship for semantic clarity, but expect zero rich-result uplift; flag this in the recommendation rationale rather than treating HowTo as a live option.
|
|
49
|
+
|
|
50
|
+
6. **Validate generated JSON-LD**
|
|
51
|
+
- Re-run the same validation rubric from step 3 on the generated blocks.
|
|
52
|
+
- Surface any required fields still marked `{REPLACE: ...}`.
|
|
53
|
+
|
|
54
|
+
7. **Optional: benchmark against top SERP results** `DATA_getSerpResults` + `mcp__firecrawl-mcp__firecrawl_scrape`
|
|
55
|
+
- Identify the page's primary keyword (from `<title>` or user input).
|
|
56
|
+
- Pull top 10 organic results.
|
|
57
|
+
- **If Firecrawl available:** scrape each of the top 10 (10 Firecrawl credits). For each, parse JSON-LD blocks from the returned `html` and list detected `@type`s. This produces real schema data, not inferences from markdown.
|
|
58
|
+
- **If Firecrawl unavailable:** skip the benchmark — WebFetch's markdown strips all schema blocks, so any "detection" from it would be guesswork. Write `Competitor benchmark skipped — Firecrawl required to read JSON-LD from competitor pages.` into `04-competitor-benchmark.md`.
|
|
59
|
+
- Surface "schema types used by 6+ of the top 10 that this page is missing." High-signal addition list. (Only emitted when benchmark ran.)
|
|
60
|
+
|
|
61
|
+
8. **Synthesise** `SCHEMA.md`
|
|
62
|
+
- Validation report (existing schema, pass/fail per block).
|
|
63
|
+
- Recommended additions (with rationale linking back to step 4 detection or step 7 benchmark).
|
|
64
|
+
- Generated `<script>` blocks ready to paste.
|
|
65
|
+
|
|
66
|
+
## Output format
|
|
67
|
+
|
|
68
|
+
Create a folder `seo-schema-{target-slug}-{YYYYMMDD}/` with:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
seo-schema-{target-slug}-{YYYYMMDD}/
|
|
72
|
+
├── 01-detected.md (existing schema, validation results)
|
|
73
|
+
├── 02-recommended.md (which types this page should add and why)
|
|
74
|
+
├── 03-generated/
|
|
75
|
+
│ ├── article.jsonld
|
|
76
|
+
│ ├── faq-page.jsonld
|
|
77
|
+
│ └── ... (per generated type)
|
|
78
|
+
├── 04-competitor-benchmark.md (only if step 7 ran)
|
|
79
|
+
└── SCHEMA.md (deliverable: paste-ready blocks + install instructions)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`SCHEMA.md` follows this shape:
|
|
83
|
+
|
|
84
|
+
```markdown
|
|
85
|
+
# Schema Markup: {URL}
|
|
86
|
+
|
|
87
|
+
> Snapshot dated {YYYY-MM-DD}.
|
|
88
|
+
|
|
89
|
+
## Currently present
|
|
90
|
+
- `Article` — valid ✓
|
|
91
|
+
- `BreadcrumbList` — invalid ✗ (missing `position` on item 2)
|
|
92
|
+
- ...
|
|
93
|
+
|
|
94
|
+
## Recommended additions
|
|
95
|
+
- `FAQPage` — page has 6 visible Q&A blocks but no FAQ schema. Adding this is eligible for FAQ rich results (subject to Google's 2024+ tightening — see references/google-rich-results.md).
|
|
96
|
+
- `HowTo` — ...
|
|
97
|
+
|
|
98
|
+
## Paste these into the `<head>` of the page
|
|
99
|
+
|
|
100
|
+
### FAQPage
|
|
101
|
+
\`\`\`html
|
|
102
|
+
<script type="application/ld+json">
|
|
103
|
+
{
|
|
104
|
+
"@context": "https://schema.org",
|
|
105
|
+
"@type": "FAQPage",
|
|
106
|
+
"mainEntity": [...]
|
|
107
|
+
}
|
|
108
|
+
</script>
|
|
109
|
+
\`\`\`
|
|
110
|
+
|
|
111
|
+
### ... (per generated block)
|
|
112
|
+
|
|
113
|
+
## Validation pass
|
|
114
|
+
- All generated blocks parse cleanly ✓
|
|
115
|
+
- All required fields filled ({n} {REPLACE: ...} placeholders remain — see below)
|
|
116
|
+
- {REPLACE: ...} placeholders to fill manually:
|
|
117
|
+
- article.jsonld → `image` (need a hero image URL ≥ 1200×800)
|
|
118
|
+
- ...
|
|
119
|
+
|
|
120
|
+
## Install
|
|
121
|
+
1. Copy each `<script>` block above.
|
|
122
|
+
2. Paste into the `<head>` of the relevant page (or the global `<head>` template, gated by page type).
|
|
123
|
+
3. Test with [Google's Rich Results Test](https://search.google.com/test/rich-results).
|
|
124
|
+
4. Submit the URL to GSC for re-indexing if changes are critical.
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Tips
|
|
128
|
+
|
|
129
|
+
- JSON-LD goes in `<head>` or top of `<body>`. Don't bury it.
|
|
130
|
+
- Test every generated block in [Google's Rich Results Test](https://search.google.com/test/rich-results) before shipping. The validation in step 3/6 follows the published spec but Google's actual test is authoritative.
|
|
131
|
+
- `references/google-rich-results.md` is dated. If it's >6 months old when you run this skill, flag staleness in the output and recommend the user verify against current docs.
|
|
132
|
+
- **Don't mark up content that isn't visibly on the page.** Google penalises hidden-content schema. If a page doesn't actually have FAQs visible, don't generate FAQPage schema.
|
|
133
|
+
- For Article schema, `image` is required. If the page has no obvious hero image, leave the `{REPLACE: hero image URL}` placeholder rather than guessing.
|
|
134
|
+
- The skill is read-mostly on the SE Ranking side: zero SE Ranking credits unless step 7 (competitor benchmark) is requested — that adds ~5–10 SE Ranking credits for `DATA_getSerpResults`. Firecrawl costs are separate: 1 credit for the target URL, +10 credits when step 7 runs.
|
|
135
|
+
- **Verify after deploy:** once the generated schema is pasted into your CMS and re-deployed, re-run this skill on the same URL — the new run's "Currently present" section reflects the live state and confirms the schema actually rendered (vs sitting in the CMS but not yet pushed). Ad-hoc alternative: invoke `seo-firecrawl` on the URL and grep `META.md` for the expected `@type`s.
|
package/skills/optbrew/modules/seranking-seo/skills/seo-schema/references/google-rich-results.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Google Rich Results — supported types and requirements
|
|
2
|
+
|
|
3
|
+
> **Last reviewed: 2026-04-27.** Google updates supported types and requirements regularly. This file is a guide, not authoritative. Verify in [Google's Rich Results Test](https://search.google.com/test/rich-results) and the [Search Gallery](https://developers.google.com/search/docs/appearance/structured-data/search-gallery).
|
|
4
|
+
|
|
5
|
+
## Type lifecycle (as of April 2026)
|
|
6
|
+
|
|
7
|
+
Use this table to decide whether a type is worth generating *for rich results*. Schema can still ship for semantic clarity even when the rich-result hook is dead — but the user should know up front.
|
|
8
|
+
|
|
9
|
+
| Type | Status | Effective date | What it means today |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| `Article` / `NewsArticle` / `BlogPosting` | **Active** | — | Eligible for top-stories, AI-overview citation hints, host carousels. Stable since 2018. |
|
|
12
|
+
| `Product` (with `Offer`) | **Active** | — | Price/availability/rating pills in SERP. Stable. |
|
|
13
|
+
| `LocalBusiness` (+ subtypes) | **Active** | — | Knowledge-panel feed, local pack enrichment. Stable. |
|
|
14
|
+
| `BreadcrumbList` | **Active** | — | Breadcrumb trail in SERP snippet. High-signal, cheap to ship. |
|
|
15
|
+
| `VideoObject` | **Active** | — | Video result + key-moments. |
|
|
16
|
+
| `Recipe` | **Active** | — | Recipe carousel + ingredients in SERP. Cooking-only since the HowTo deprecation. |
|
|
17
|
+
| `Event` | **Active** | — | Event listing pill + Google Events. |
|
|
18
|
+
| `JobPosting` | **Active** | — | Google for Jobs listing. |
|
|
19
|
+
| `Course` / `CourseInfo` | **Active** | — | Course listing pill. |
|
|
20
|
+
| `Movie` | **Active** | — | Movie carousel. |
|
|
21
|
+
| `Organization` | **Active** | — | Knowledge-panel logo + sameAs. |
|
|
22
|
+
| `WebSite` (with `SiteNavigationElement`) | **Active** | — | Sitelinks + sitelinks search box. |
|
|
23
|
+
| `FAQPage` | **Restricted** | 2023-08 | Rich results limited to "well-known authoritative government and health" sites. For everyone else, ship only if the page is unambiguously a dedicated FAQ — expect zero SERP uplift. |
|
|
24
|
+
| `Q&APage` | **Restricted** | 2023-08 | Same restriction as `FAQPage`. Limited to forum/community use cases. |
|
|
25
|
+
| `HowTo` | **Deprecated** | 2023-09 | Rich results removed from desktop and mobile (full retirement Sep 2023). Schema no longer drives any SERP feature for non-cooking content. **Do not generate** — use plain prose + step images. |
|
|
26
|
+
| `Sitelinks Search Box` | **Deprecated** | 2024-11 | Google stopped using `potentialAction.SearchAction` to render the search box. Markup is harmless but inert. |
|
|
27
|
+
|
|
28
|
+
> ⚠ **Status-check rule:** if this file is more than 6 months old at run-time, flag staleness and verify against [Google's Search Gallery](https://developers.google.com/search/docs/appearance/structured-data/search-gallery) before recommending. Status changes here ship without warning from Google.
|
|
29
|
+
|
|
30
|
+
## Supported types (April 2026 — bundled templates)
|
|
31
|
+
|
|
32
|
+
| Schema.org type | When to use | Template |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `Article` / `NewsArticle` / `BlogPosting` | Editorial content with an author | `templates/article.json` |
|
|
35
|
+
| `Product` (with `Offer`) | E-commerce product page | `templates/product.json` |
|
|
36
|
+
| `LocalBusiness` (and subtypes like `Restaurant`, `Dentist`) | Brick-and-mortar landing page | `templates/local-business.json` |
|
|
37
|
+
| `FAQPage` | Page with explicit Q&A blocks (gov/health only — see Restricted in lifecycle table) | `templates/faq-page.json` |
|
|
38
|
+
| `BreadcrumbList` | Most pages with breadcrumb navigation | `templates/breadcrumb-list.json` |
|
|
39
|
+
| `VideoObject` | Pages embedding video content | (template not bundled — see Google docs) |
|
|
40
|
+
| `Recipe` | Cooking recipes | (template not bundled) |
|
|
41
|
+
| `Event` | Time-bound events | (template not bundled) |
|
|
42
|
+
|
|
43
|
+
## Required vs recommended (highlights)
|
|
44
|
+
|
|
45
|
+
### Article / NewsArticle / BlogPosting
|
|
46
|
+
- **Required:** `headline`, `image`, `datePublished`
|
|
47
|
+
- **Recommended:** `author` (with `@type: Person` and `url`), `dateModified`, `publisher` (with logo `ImageObject`), `mainEntityOfPage`
|
|
48
|
+
- **Common errors:** `headline` over 110 chars; missing `image` or image too small (min 1200×800 for max coverage); `author` as plain string instead of `@type: Person`.
|
|
49
|
+
|
|
50
|
+
### Product
|
|
51
|
+
- **Required:** `name`, `image`, `offers` (with `price`, `priceCurrency`, `availability`)
|
|
52
|
+
- **Recommended:** `aggregateRating`, `review`, `sku`, `brand`, `gtin`/`mpn`
|
|
53
|
+
- **Common errors:** `price` as a number instead of string; `availability` as plain text instead of schema.org URL (`https://schema.org/InStock`).
|
|
54
|
+
|
|
55
|
+
### LocalBusiness
|
|
56
|
+
- **Required:** `name`, `address` (full `PostalAddress`), `telephone` OR `url`
|
|
57
|
+
- **Recommended:** `geo`, `openingHoursSpecification`, `priceRange`, `image`, `aggregateRating`
|
|
58
|
+
- **Common errors:** `telephone` not in international format (must include country code, no spaces in JSON-LD); `address` as plain string instead of `@type: PostalAddress`.
|
|
59
|
+
|
|
60
|
+
### FAQPage
|
|
61
|
+
- **Required:** `mainEntity` array of `Question` objects, each with `name` and `acceptedAnswer.text`
|
|
62
|
+
- **Common errors:** marking up FAQs that aren't visibly Q&A on the page; using `Question` for content that is just an H2 + paragraph.
|
|
63
|
+
- ⚠ **Note (2024–2026):** Google has significantly reduced FAQ rich-result eligibility — most sites no longer get FAQ rich results in SERPs. Apply this schema only to pages that are unambiguously Q&A (e.g., dedicated FAQ pages).
|
|
64
|
+
|
|
65
|
+
### HowTo — **deprecated 2023-09**
|
|
66
|
+
- Google fully retired HowTo rich results in September 2023 (mobile + desktop). The schema no longer drives any SERP feature for non-cooking content; cooking content should use `Recipe` instead.
|
|
67
|
+
- **Do not generate `HowTo` markup as a rich-results play.** It can still ship for semantic clarity, but the rationale must say so explicitly — otherwise the user will assume rich-result eligibility that no longer exists.
|
|
68
|
+
- For step-by-step content, prefer plain prose + numbered headings + `Article` schema.
|
|
69
|
+
|
|
70
|
+
### BreadcrumbList
|
|
71
|
+
- **Required:** `itemListElement` array (each with `position`, `name`, `item`)
|
|
72
|
+
- **Recommended:** include the canonical absolute URL in each `item`.
|
|
73
|
+
- **Note:** highly reliable rich result; most pages with breadcrumbs benefit.
|
|
74
|
+
|
|
75
|
+
## Validation checklist (apply after generating)
|
|
76
|
+
|
|
77
|
+
1. `@context` is exactly `https://schema.org` (lowercase, no trailing slash).
|
|
78
|
+
2. `@type` matches one of the supported types above (case-sensitive).
|
|
79
|
+
3. All URLs are **absolute**, not relative.
|
|
80
|
+
4. Dates are ISO 8601 (`2026-04-27` or `2026-04-27T10:30:00+00:00`).
|
|
81
|
+
5. The JSON parses cleanly (no trailing commas, balanced braces).
|
|
82
|
+
6. The `<script type="application/ld+json">` block is in `<head>` or top of `<body>`.
|
|
83
|
+
7. The structured data describes content **actually visible on the page**. Google penalises hidden-content schema.
|
|
84
|
+
|
|
85
|
+
## When to skip generating
|
|
86
|
+
|
|
87
|
+
- The page is a generic "kitchen sink" page that doesn't fit a single intent — generating speculative schema usually hurts.
|
|
88
|
+
- The content is JS-rendered and the team doesn't server-side render — schema in client-only JS is often missed by crawlers.
|
|
89
|
+
- The site is a low-trust domain Google has already penalised — schema doesn't unlock rich results until the trust signals improve.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": "https://schema.org",
|
|
3
|
+
"@type": "Article",
|
|
4
|
+
"headline": "{REPLACE: page title, max 110 chars}",
|
|
5
|
+
"description": "{REPLACE: meta description, ~155 chars}",
|
|
6
|
+
"author": {
|
|
7
|
+
"@type": "Person",
|
|
8
|
+
"name": "{REPLACE: author name}",
|
|
9
|
+
"url": "{REPLACE: author profile URL}"
|
|
10
|
+
},
|
|
11
|
+
"datePublished": "{REPLACE: ISO 8601 date, e.g. 2026-04-27}",
|
|
12
|
+
"dateModified": "{REPLACE: ISO 8601 date}",
|
|
13
|
+
"publisher": {
|
|
14
|
+
"@type": "Organization",
|
|
15
|
+
"name": "{REPLACE: brand name}",
|
|
16
|
+
"logo": {
|
|
17
|
+
"@type": "ImageObject",
|
|
18
|
+
"url": "{REPLACE: logo URL, min 112x112px}"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"image": "{REPLACE: hero image URL, min 1200x800px}",
|
|
22
|
+
"mainEntityOfPage": "{REPLACE: canonical URL of this page}"
|
|
23
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": "https://schema.org",
|
|
3
|
+
"@type": "BreadcrumbList",
|
|
4
|
+
"itemListElement": [
|
|
5
|
+
{
|
|
6
|
+
"@type": "ListItem",
|
|
7
|
+
"position": 1,
|
|
8
|
+
"name": "{REPLACE: breadcrumb 1 label}",
|
|
9
|
+
"item": "{REPLACE: breadcrumb 1 URL}"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"@type": "ListItem",
|
|
13
|
+
"position": 2,
|
|
14
|
+
"name": "{REPLACE: breadcrumb 2 label}",
|
|
15
|
+
"item": "{REPLACE: breadcrumb 2 URL}"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": "https://schema.org",
|
|
3
|
+
"@type": "FAQPage",
|
|
4
|
+
"mainEntity": [
|
|
5
|
+
{
|
|
6
|
+
"@type": "Question",
|
|
7
|
+
"name": "{REPLACE: question 1 — must be visibly on the page}",
|
|
8
|
+
"acceptedAnswer": {
|
|
9
|
+
"@type": "Answer",
|
|
10
|
+
"text": "{REPLACE: answer 1 — must match the visible answer}"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"@type": "Question",
|
|
15
|
+
"name": "{REPLACE: question 2}",
|
|
16
|
+
"acceptedAnswer": {
|
|
17
|
+
"@type": "Answer",
|
|
18
|
+
"text": "{REPLACE: answer 2}"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": "https://schema.org",
|
|
3
|
+
"@type": "LocalBusiness",
|
|
4
|
+
"@id": "{REPLACE: canonical URL}",
|
|
5
|
+
"name": "{REPLACE: business name}",
|
|
6
|
+
"description": "{REPLACE: short description}",
|
|
7
|
+
"url": "{REPLACE: website URL}",
|
|
8
|
+
"telephone": "{REPLACE: phone in international format, e.g. +14155550100}",
|
|
9
|
+
"address": {
|
|
10
|
+
"@type": "PostalAddress",
|
|
11
|
+
"streetAddress": "{REPLACE: street}",
|
|
12
|
+
"addressLocality": "{REPLACE: city}",
|
|
13
|
+
"addressRegion": "{REPLACE: state/region}",
|
|
14
|
+
"postalCode": "{REPLACE: postal code}",
|
|
15
|
+
"addressCountry": "{REPLACE: ISO country code, e.g. US}"
|
|
16
|
+
},
|
|
17
|
+
"geo": {
|
|
18
|
+
"@type": "GeoCoordinates",
|
|
19
|
+
"latitude": "{REPLACE: latitude}",
|
|
20
|
+
"longitude": "{REPLACE: longitude}"
|
|
21
|
+
},
|
|
22
|
+
"openingHoursSpecification": [
|
|
23
|
+
{
|
|
24
|
+
"@type": "OpeningHoursSpecification",
|
|
25
|
+
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
|
|
26
|
+
"opens": "09:00",
|
|
27
|
+
"closes": "17:00"
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"priceRange": "$$",
|
|
31
|
+
"image": "{REPLACE: storefront/exterior image URL}"
|
|
32
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": "https://schema.org",
|
|
3
|
+
"@type": "Product",
|
|
4
|
+
"name": "{REPLACE: product name}",
|
|
5
|
+
"description": "{REPLACE: product description}",
|
|
6
|
+
"image": ["{REPLACE: product image URL}"],
|
|
7
|
+
"sku": "{REPLACE: SKU}",
|
|
8
|
+
"brand": {
|
|
9
|
+
"@type": "Brand",
|
|
10
|
+
"name": "{REPLACE: brand name}"
|
|
11
|
+
},
|
|
12
|
+
"offers": {
|
|
13
|
+
"@type": "Offer",
|
|
14
|
+
"url": "{REPLACE: product URL}",
|
|
15
|
+
"priceCurrency": "USD",
|
|
16
|
+
"price": "{REPLACE: price as STRING, e.g. \"49.00\"}",
|
|
17
|
+
"availability": "https://schema.org/InStock",
|
|
18
|
+
"itemCondition": "https://schema.org/NewCondition"
|
|
19
|
+
},
|
|
20
|
+
"aggregateRating": {
|
|
21
|
+
"@type": "AggregateRating",
|
|
22
|
+
"ratingValue": "{REPLACE: average rating as string, e.g. \"4.6\"}",
|
|
23
|
+
"reviewCount": "{REPLACE: total reviews as string}"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
> Example output: examples/seo-sitemap-notion-so-20260514/SITEMAP.md (upstream-only reference; route through optbrew)
|
|
2
|
+
|
|
3
|
+
# Sitemap Analysis
|
|
4
|
+
|
|
5
|
+
Compare a domain's XML sitemap against the most recent SE Ranking website audit. Surface what the sitemap claims vs what the crawler actually found, in both directions.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- SE Ranking MCP server connected.
|
|
10
|
+
- Claude's `WebFetch` tool available.
|
|
11
|
+
- User provides: a target domain. Optional: the sitemap URL if not at `/sitemap.xml` (auto-discovery from `robots.txt` is attempted first).
|
|
12
|
+
- **Predecessor:** `seo-technical-audit` (or any prior SE Ranking audit) on this domain. Without an existing audit, this skill has nothing to compare against — chain `seo-technical-audit` first.
|
|
13
|
+
|
|
14
|
+
## Process
|
|
15
|
+
|
|
16
|
+
1. **Validate target & confirm audit**
|
|
17
|
+
- Normalise the domain.
|
|
18
|
+
- `DATA_listAudits` → confirm an audit exists for this domain. If none, surface a clear message: "Run `seo-technical-audit` first; this skill compares the sitemap to that audit's crawl."
|
|
19
|
+
- Use the most recent `done` audit by default.
|
|
20
|
+
- **Firecrawl availability check.** If `mcp__firecrawl-mcp__firecrawl_map` is available, Mode-2 (URL discovery via crawl) is offered when the sitemap is missing or suspect. Cost: ~0.5 Firecrawl credits per URL discovered, hard cap 500 URLs (~250 credits). Without Firecrawl, the skill runs Mode-1 only and notes the gap if Mode-2 was needed. User may pass `--no-firecrawl` to force Mode-1 even when Firecrawl is available (saves credits at the cost of orphan/missing analysis when sitemap is broken).
|
|
21
|
+
|
|
22
|
+
2. **Build URL lists** `WebFetch` (sitemap) + `mcp__firecrawl-mcp__firecrawl_map` (optional Mode-2)
|
|
23
|
+
- **Mode-1 (default).** Try `https://{domain}/sitemap.xml`. If 404, fetch `/robots.txt` and look for `Sitemap:` directives. For sitemap-of-sitemaps, recursively fetch each child sitemap. Build the canonical URL list from the sitemap.
|
|
24
|
+
- **Mode-2 trigger.** Switch on Mode-2 when (a) no sitemap is reachable, (b) the sitemap returns < 10% of the audit's `DATA_getCrawledPages` count, or (c) the user explicitly requests `--discover`. Always surface the trigger and the cost estimate to the user before running Mode-2.
|
|
25
|
+
- **Mode-2 execution** (requires Firecrawl): call `firecrawl_map(url=domain, limit=500)`. The response is the URL list Firecrawl could discover from the homepage and internal linking. Use this list as the "sitemap-equivalent" in step 6 — the diffs run identically, just with discovered URLs in place of declared sitemap URLs.
|
|
26
|
+
- **If Mode-2 is needed but Firecrawl is unavailable:** continue with whatever sitemap data Mode-1 returned (possibly empty). Surface clearly in `SITEMAP.md`: `Mode-2 (Firecrawl URL discovery) needed but Firecrawl not installed — sitemap-vs-audit diffs run on partial data only.`
|
|
27
|
+
|
|
28
|
+
3. **Pull the audit's crawled pages** `DATA_getCrawledPages`
|
|
29
|
+
- All URLs the crawler found, with status codes, indexability flags, depth.
|
|
30
|
+
|
|
31
|
+
4. **Pull domain pages** `DATA_getDomainPages`
|
|
32
|
+
- Domain-level page inventory (broader than the audit's crawl scope in some cases).
|
|
33
|
+
|
|
34
|
+
5. **Pull orphan-page issues** `DATA_getAuditPagesByIssue`
|
|
35
|
+
- Filter for orphan-page and depth-related issues. These intersect with sitemap analysis.
|
|
36
|
+
|
|
37
|
+
6. **Compute the four diffs**
|
|
38
|
+
- **Missing from sitemap:** URLs in `DATA_getCrawledPages` (status 200, indexable) that don't appear in the sitemap. Probably should be added.
|
|
39
|
+
- **Orphans from sitemap:** URLs in the sitemap that the crawler didn't find via internal links (cross-ref `DATA_getAuditPagesByIssue` orphan flags). The sitemap is the only thing pointing at them — investigate whether they should be linked internally.
|
|
40
|
+
- **Broken sitemap entries:** sitemap URLs that returned non-200 in the audit's crawl. Remove from sitemap or fix the URL.
|
|
41
|
+
- **Lastmod issues:** sitemap entries where (a) all `<lastmod>` dates are identical (lazy generation) or (b) `<lastmod>` is older than the audit's crawl date for the page even though the page changed (stale).
|
|
42
|
+
|
|
43
|
+
7. **Validation**
|
|
44
|
+
- URL count <50,000 per file (sitemap protocol limit). Flag if exceeded.
|
|
45
|
+
- Sitemap referenced in `robots.txt`.
|
|
46
|
+
- Encoding: each URL is XML-safe (ampersands escaped, etc.).
|
|
47
|
+
- HTTPS consistency: sitemap URLs match the canonical protocol.
|
|
48
|
+
- **`<lastmod>` is the only optional tag Google still consumes.** Validate it (step 6). `<priority>` and `<changefreq>` have been **explicitly ignored by Google for years** (per [Google's sitemap docs](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap) — "Google ignores `priority` and `changefreq` values"). Don't validate them; if present, flag as low-signal noise the user can strip to shrink the sitemap.
|
|
49
|
+
|
|
50
|
+
8. **Synthesise** `SITEMAP.md`
|
|
51
|
+
|
|
52
|
+
## Output format
|
|
53
|
+
|
|
54
|
+
Create a folder `seo-sitemap-{target-slug}-{YYYYMMDD}/` with:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
seo-sitemap-{target-slug}-{YYYYMMDD}/
|
|
58
|
+
├── SITEMAP.md (synthesised report — primary deliverable)
|
|
59
|
+
├── recommended-sitemap-diff.md (proposed changes: add X, remove Y — load-bearing artefact engineering applies to sitemap.xml)
|
|
60
|
+
└── evidence/
|
|
61
|
+
└── source-data.md (consolidated raw step output: fetched sitemap content, Firecrawl-discovered URLs if Mode-2 ran, audit's crawled-pages list, the four diffs (missing/orphans/broken/lastmod-issues) — preserved for reproducibility)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Top-level: `SITEMAP.md` + `recommended-sitemap-diff.md`. The seven raw step files (`01-sitemap-raw`, `01b-firecrawl-discovered`, `02-audit-pages`, `03-missing-from-sitemap`, `04-orphans-from-sitemap`, `05-broken-entries`, `06-lastmod-issues`) are consolidated into a single `evidence/source-data.md` document with the same per-step section headers — a reader who needs to replay the diff has all raw inputs in one file rather than seven.
|
|
65
|
+
|
|
66
|
+
`SITEMAP.md` follows this shape:
|
|
67
|
+
|
|
68
|
+
```markdown
|
|
69
|
+
# Sitemap Analysis: {domain}
|
|
70
|
+
|
|
71
|
+
> Sitemap pulled {YYYY-MM-DD} · Audit reference {audit-date}
|
|
72
|
+
|
|
73
|
+
## Mode
|
|
74
|
+
|
|
75
|
+
- **Mode-1 (sitemap-vs-audit):** {ran / skipped — no sitemap reachable}
|
|
76
|
+
- **Mode-2 (Firecrawl URL discovery):** {ran with {n} URLs / not triggered / triggered but Firecrawl not installed}
|
|
77
|
+
|
|
78
|
+
## Health summary
|
|
79
|
+
|
|
80
|
+
| Metric | Value | Status |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| Sitemap URLs (Mode-1) | {n} | — |
|
|
83
|
+
| Discovered URLs (Mode-2, if ran) | {n} | — |
|
|
84
|
+
| Audit crawled URLs (200, indexable) | {n} | — |
|
|
85
|
+
| Missing from sitemap (probable adds) | {n} | {🔴 if >5%} |
|
|
86
|
+
| Orphans from sitemap (probable cuts or link-ins) | {n} | {🟡 if >5} |
|
|
87
|
+
| Broken sitemap entries (non-200) | {n} | {🔴 if >0} |
|
|
88
|
+
| Lastmod issues | {n} | {🟡 if uniform; 🔴 if stale} |
|
|
89
|
+
|
|
90
|
+
## Recommended changes
|
|
91
|
+
|
|
92
|
+
### Add to sitemap ({n} URLs)
|
|
93
|
+
- {URL} — found by crawler at depth {n}, status 200, indexable.
|
|
94
|
+
- ...
|
|
95
|
+
|
|
96
|
+
### Remove from sitemap ({n} URLs)
|
|
97
|
+
- {URL} — returns {status code}.
|
|
98
|
+
- ...
|
|
99
|
+
|
|
100
|
+
### Investigate (orphan from sitemap, {n} URLs)
|
|
101
|
+
- {URL} — in sitemap but not reachable via internal links. Either link from {suggested parent} or remove from sitemap.
|
|
102
|
+
- ...
|
|
103
|
+
|
|
104
|
+
### Fix lastmod ({n} URLs)
|
|
105
|
+
- {URL} — lastmod is {date} but the audit crawled the page on {date} and detected changes since.
|
|
106
|
+
- ...
|
|
107
|
+
|
|
108
|
+
## Validation
|
|
109
|
+
|
|
110
|
+
- Total URL count: {n} ({✓ under 50k limit | ✗ exceeds — split into sitemap-of-sitemaps})
|
|
111
|
+
- Referenced in robots.txt: {✓/✗}
|
|
112
|
+
- HTTPS consistency: {✓/✗}
|
|
113
|
+
- Encoding: {✓/✗}
|
|
114
|
+
|
|
115
|
+
## Apply
|
|
116
|
+
- See `recommended-sitemap-diff.md` for the proposed sitemap.xml changes.
|
|
117
|
+
- After applying, re-run `seo-technical-audit` to refresh the crawl, then re-run this skill to verify.
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Tips
|
|
121
|
+
|
|
122
|
+
- Run `seo-technical-audit` first. Without an audit, this skill has nothing to compare.
|
|
123
|
+
- Re-run after deploys that change page inventory (new content, removed pages, URL restructures).
|
|
124
|
+
- Sitemap-of-sitemaps fan-out can be large for big sites — the skill recursively fetches all child sitemaps. For sites with 50+ child sitemaps, fetching dominates runtime; not credit cost.
|
|
125
|
+
- `<priority>` and `<changefreq>` are dead signals — Google explicitly ignores both. Don't waste time tuning them; if your sitemap generator emits them, the bytes are pure overhead. `<lastmod>` is still consumed, so keep that one accurate.
|
|
126
|
+
- The "investigate orphans" list is often the highest-leverage finding — pages that exist but aren't linked are usually accidentally orphaned, and adding a couple of internal links can revive them.
|
|
127
|
+
- Pair with `seo-drift` to track sitemap composition over time (URL count, lastmod patterns).
|
|
128
|
+
- Cost: ~5–10 SE Ranking credits typical (mostly the `getCrawledPages` and `getDomainPages` calls). Mode-2 adds Firecrawl credits at ~0.5 per discovered URL — surface the estimate before triggering.
|