diff --git a/AGENTS.md b/AGENTS.md index 3ec2f19..f94fd2b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -138,6 +138,7 @@ When the user mentions these keywords, load the corresponding skill: | "c4-diagramming", "c4 diagramming" | [c4-diagramming](c4-diagramming/SKILL.md) | | "technology-radar", "technology radar" | [technology-radar](technology-radar/SKILL.md) | | "verification-methodology", "verification methodology" | [verification-methodology](verification-methodology/SKILL.md) | +| "seo-audit", "seo audit" | [seo-audit](seo-audit/SKILL.md) | ## Use-When Sections Every skill description must identify when to load it. Skills with meaningful overlap should also include a `## When not to use` section naming the nearest alternative or prerequisite. Keep these sections trigger-oriented and concise; implementation details belong in references. diff --git a/README.md b/README.md index 6539418..3701f5e 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,10 @@ Turn an open question into a bounded, evidence-led investigation rather than a p Give authorized teams a disciplined way to identify and prioritize security risks without mistaking a checklist for a security guarantee. +### [seo-audit](seo-audit/SKILL.md) + +Identify search-discoverability problems through evidence, prioritize the work, and distinguish technical defects from content opportunities. + ### [site-reliability-engineering](site-reliability-engineering/SKILL.md) Build practical reliability practices around the work teams actually perform: measurable service objectives, useful alerts, incident response, and learning-oriented follow-up. diff --git a/seo-audit/README.md b/seo-audit/README.md new file mode 100644 index 0000000..30235f9 --- /dev/null +++ b/seo-audit/README.md @@ -0,0 +1,37 @@ +# Seo Audit + +Identify search-discoverability problems through evidence, prioritize the work, and distinguish technical defects from content opportunities. + +## Why Install This Skill + +Identify search-discoverability problems through evidence, prioritize the work, and distinguish technical defects from content opportunities. It preserves a practical method, local reference material, and reusable templates so an agent can do more than produce a generic answer. + +Use it when the work needs a repeatable process and an inspectable result. It is portable across Agent Skills-compatible clients and does not require a profile system or a particular task orchestrator. + +## What You Get + +| Path | What it provides | +|---|---| +| `SKILL.md` | Trigger conditions, workflow, and guidance for loading deeper resources. | +| `references/` | Reference material: `aeo-methodology.md`, `content-strategy-seo.md`, `ghost-metadata.md`, `onpage-seo.md`, `schema-markup.md`, `technical-seo.md` | +| `assets/` | Assets: `audit-report-template.md` | + +## Quick Start + +Start with the technical, on-page, or schema reference that matches the page or site under review. + +Install or expose this directory using your agent's standard Agent Skills loading mechanism, then ask for work that matches the triggers below. + +## Triggers + +- Audit websites and pages for technical SEO, on-page SEO, schema markup, content discoverability, and answer-engine readiness. Use when prioritizing search visibility improvements. +- Requests involving the method, deliverables, or review process described in `SKILL.md`. +- Work where a reusable template or reference from this skill would reduce avoidable mistakes. + +## Requirements + +Requires access to the site or page being audited. Platform-specific references are optional and must be applied only when relevant. + +## Source and maintenance + +This skill was extracted from [`magnus919/hermes-profiles`](https://github.com/magnus919/hermes-profiles) at commit [`867a555`](https://github.com/magnus919/hermes-profiles/commit/867a555). The portable methodology was retained; Hermes-specific profile, orchestration, and memory assumptions were removed. diff --git a/seo-audit/SKILL.md b/seo-audit/SKILL.md new file mode 100644 index 0000000..6171e57 --- /dev/null +++ b/seo-audit/SKILL.md @@ -0,0 +1,66 @@ +--- +name: seo-audit +description: Audit websites and pages for technical SEO, on-page SEO, schema markup, content discoverability, and answer-engine readiness. Use when prioritizing search visibility improvements. +license: MIT +compatibility: Requires access to the site or page being audited. Platform-specific references are optional and must be applied only when relevant. +metadata: + source_repo: https://github.com/magnus919/hermes-profiles + source_commit: 867a555 +--- + + +# SEO Audit + +Full-spectrum audit for sites, articles, and content strategies. Covers both traditional SEO and Answer Engine Optimization (AEO/GEO) — the practice of structuring content so LLMs and AI answer engines (ChatGPT, Perplexity, Gemini, Claude, Google AI Overviews) extract and cite it. + +Use `assets/audit-report-template.md` for a portable audit deliverable. If the host workflow uses artifact pyramids, that structure can be an optional presentation format rather than a prerequisite. + + +## SEO + AEO Audit: [Site/Page URL] + +**Overall Health:** [Good / Fair / Poor] +**Score:** [N/100] + +### SEO Priority Findings +1. [Critical] → [Action] + +### AEO Priority Findings +1. [Critical] → [Action] + +### Quick Wins +1. [Low effort, high impact] → [Action] + +### Verdict +[One paragraph summarizing the single most important thing to fix and expected impact.] +``` + +## Contents + +| File | What it covers | +|------|----------------| +| `references/technical-seo.md` | Crawlability, indexability, robots.txt, sitemaps, page speed, Core Web Vitals, mobile-friendliness, HTTPS, canonical URLs, hreflang | +| `references/onpage-seo.md` | Title tags, meta descriptions, heading hierarchy, keyword placement, content quality, internal linking, image optimization | +| `references/schema-markup.md` | Schema.org types (TechArticle, FAQPage, HowTo, Article, BlogPosting, BreadcrumbList, Organization), JSON-LD format, Google rich results, validation | +| `references/content-strategy-seo.md` | Topic clusters, pillar pages, keyword research, gap analysis, SERP feature targeting, topical authority | +| `references/ghost-metadata.md` | Ghost CMS metadata fields (meta_title, meta_description, custom_excerpt), social media cards (OG, Twitter), code-injected schema (JSON-LD, FAQPage, TechArticle, @graph), per-post and site-wide injection, validation | +| `references/aeo-methodology.md` | Answer Engine Optimization — LLM RAG pipeline, answer-first content architecture, AEO-specific schema (FAQPage 3.2× boost), Ethan Smith/Graphite frameworks, question clusters, llms.txt, content negotiation, measurement | +| `assets/audit-report-template.md` | Blank report scaffold for new audits | + +## When to Use + +Load this skill when: +- Auditing a site for technical SEO issues +- Optimizing a new article for search and AI citation before publication +- Validating structured data on an existing page +- Completing Ghost CMS metadata (meta, social cards, schema injection) before publish +- Running an AEO readiness audit (llms.txt, content negotiation, question-cluster coverage) +- Developing a content strategy with SEO + AEO in parallel +- Diagnosing why a site or page isn't performing in search or AI citation + +Do NOT load when: +- Only mechanical content fixes are needed; use the host agent's copy-editing workflow. +- Only writing is needed; use the host agent's writing workflow. + +## Portability + +This skill is intentionally host-neutral. Use your agent's normal mechanisms to load the references, templates, and scripts listed here. Do not assume a particular profile system, task orchestrator, memory service, or response-handoff format. diff --git a/seo-audit/assets/audit-report-template.md b/seo-audit/assets/audit-report-template.md new file mode 100644 index 0000000..80cf795 --- /dev/null +++ b/seo-audit/assets/audit-report-template.md @@ -0,0 +1,76 @@ +# SEO Audit Report Template + +Scaffold for new SEO audit projects. Copy this into your pyramid root. + +```markdown +# SEO Audit: [Site/Page URL] + +**Audit date:** YYYY-MM-DD +**Auditor:** seo-specialist profile +**Scope:** [Full site / Single page / Content strategy] + +--- + +## L1 Summary + +### Overall Health: [Good / Fair / Poor] +### Score: [N/100] + +### Priority Findings +1. [Critical] → [Action] +2. [Critical] → [Action] + +### Moderate Findings +1. [Important] → [Action] + +### Quick Wins +1. [Low effort, high impact] → [Action] + +--- + +## L2 Analysis Files + +### Technical SEO +- Crawlability and indexability +- Page speed / Core Web Vitals +- Mobile-friendliness +- HTTPS and security +- Canonical URLs and hreflang +- Sitemap and robots.txt + +### On-Page SEO +- Title tags and meta descriptions +- Heading structure +- Keyword usage +- Content quality and length +- Internal linking +- Image optimization +- URL structure + +### Schema Validation +- JSON-LD structure +- Schema.org types used +- Rich result eligibility +- Validation results + +### Content Gap Analysis +- Target keywords +- Current rankings +- Competitor analysis +- Gap identification +- Priority recommendations + +--- + +## L3 Dossiers + +### Raw Data +- Full crawl results +- Schema validation output +- Keyword research data +- Competitor SERP data + +### Methodology Notes +- Tools used +- Assumptions and limitations +- Data collection dates diff --git a/seo-audit/references/aeo-methodology.md b/seo-audit/references/aeo-methodology.md new file mode 100644 index 0000000..85e5d71 --- /dev/null +++ b/seo-audit/references/aeo-methodology.md @@ -0,0 +1,177 @@ +# Answer Engine Optimization (AEO) Methodology + +AEO (also called GEO — Generative Engine Optimization) is the practice of structuring content so AI-powered answer engines (ChatGPT, Perplexity, Gemini, Claude, Google AI Overviews) extract, cite, and surface it in their generated responses. + +**Core insight:** ChatGPT traffic converts 6× better than Google search (Ethan Smith, Graphite). Content that ranks in Google is 3× more likely to appear in LLM citations. SEO and AEO are complementary — the SEO foundation feeds AEO performance. + +## How LLMs Surface Content + +Modern LLMs with web access use Retrieval-Augmented Generation (RAG): + +1. **Query expansion** — User prompt is expanded into related sub-queries +2. **Retrieval** — Web search or vector DB finds candidate pages +3. **Re-ranking** — Chunks scored by relevance to query +4. **Synthesis** — LLM generates answer grounded in top chunks +5. **Citation** — Sources appended as footnotes or inline links + +### Key Signals for Citation Selection + +**Semantic relevance** — content must match semantic meaning, not just keywords. Named entities (people, products, brands, places) boost relevance scoring. + +**Answer placement** — First 1-2 sentences of a section are the most extractable. Pages with clean heading hierarchy earn 2.8× higher citation rates (AirOps 2026). + +**Authority** — 96% of AI Overview citations come from sources Google already trusts (Ziptie.dev). E-E-A-T functions as a binary gatekeeper, not just a ranking signal. + +**Freshness** — Pages accessible to GPTBot, ClaudeBot, PerplexityBot. AI Overviews favors recently crawled content. + +**FAQPage schema** — Pages with FAQPage schema appear in AI Overviews 3.2× more often (SearchAtlas data). + +## Content Structure for AEO + +### Answer-First Architecture + +Every section should follow the inverted pyramid: + +``` +┌──────────────────────────────────┐ +│ Direct answer (first 1-2 sentences) │ ← Most extractable +├──────────────────────────────────┤ +│ Supporting details / evidence │ ← Reinforces citation confidence +├──────────────────────────────────┤ +│ Background / context │ ← For human readers +└──────────────────────────────────┘ +``` + +### Structural Requirements + +- **One clear H1** aligned with the primary topic +- **Question-based H2s** — Write headings as standalone user questions ("How does X work?") +- **Answer in the opening sentence** — Every section's first sentence directly answers the heading +- **Short paragraphs** — 2-4 sentences max +- **Consistent terminology** — One term per concept; don't rotate synonyms (helps entity recognition) +- **TL;DR / Summary block** — Quick-extractable answer at the top of the article +- **FAQ sections** — Self-contained Q&A pairs matching how users query AI assistants +- **Lists and tables** — LLMs efficiently extract structured data from ordered/unordered lists +- **Quote-worthy claims** — Key numbers in the first sentence of their paragraph; specific, confident, unhedged language + +### What NOT to Do + +- Long intros / historical context before the answer +- Delaying the answer to increase time-on-page (penalized by LLMs) +- Creative/metaphorical headings ("The Dance of Algorithms") +- Redundant restatements of the same point +- Relying solely on schema to compensate for vague content + +## AEO-Specific Structured Data + +| Schema Type | AEO Impact | Priority | +|-------------|-----------|----------| +| **FAQPage** | 3.2× more citations in AI Overviews. LLMs directly extract Q&A pairs. | Highest | +| **HowTo** | Step-by-step instructions extracted for procedural queries | High | +| **Article / TechArticle** | Signals content type, authorship, publication date | Required | +| **Organization** | Establishes publisher identity and authority | Required | +| **Person** | Author credentials and authority signals | High | +| **BreadcrumbList** | Helps LLMs understand site hierarchy | Medium | + +**Key rules:** +- JSON-LD is the preferred format +- Schema must match visible content exactly (misleading schema damages trust) +- Pages using 3+ relevant schema types show ~13% higher citation likelihood (AirOps) +- FAQPage schema provides compounding benefits when paired with FAQ formatting in visible content + +## Ethan Smith / Graphite's AEO Framework + +### The 5% Principle +Only ~5% of SEO/AEO strategies drive outsized results. Process: Generate Ideas → Test & Evaluate → Reproduce Results. + +### High-Impact AEO Tactics (the 5%) +1. **New AEO landing pages** — Create pages for topics you don't cover +2. **Content enhancement** — Fill answer gaps on existing pages +3. **Citation optimization** — Get mentioned on the most-cited URLs for target topics + +### Biggest Waste of Time +Technical AEO (page speed, crawl errors) is low-impact. Priorities: content quality > question coverage > authority > technical tweaks. + +### AEO Topics (Not Keywords) +An AEO topic = a cluster of questions targeting a single page. Questions have head, mid-tail, and long-tail varieties. Focus on "Product Questions" — those where answers suggest products or brands. + +### Owned vs. Earned +- **Owned** (SEO-like): Directly ranking your page — more effective for specific, product-oriented questions +- **Earned**: Being cited as a source within the LLM's answer — more critical for general, high-level questions + +### The 7-Step AEO Playbook +1. Identify target AEO topics (question clusters) +2. Audit current content for answer gaps +3. Create or enhance pages with answer-first structure +4. Add structured data (FAQPage, Article, etc.) +5. Build off-site authority (Reddit, YouTube, guest content) +6. Measure citation rate and iterate +7. Scale what works, kill what doesn't + +## LLM-Friendly Content Formats + +### llms.txt +A markdown file at the site root providing LLMs with background, guidance, and links. Functions as a foundational AEO element — provides curated context for LLMs, reduces hallucinations, and controls how your site is understood. + +**Structure:** +```markdown +# Site Name +> Brief description + +## Pages +- [Page Title](URL) + +## Optional +- [Full content](llms-full.txt) +``` + +### Content Negotiation (Accept: text/markdown) +Serve Markdown to LLM agents and HTML to browsers. The agent sends `Accept: text/markdown` in the HTTP header; the server returns clean Markdown. Standards-compliant — no separate URL needed. + +**Hugo:** Already implemented on example.com — custom output format renders pages as Markdown. Serve via Hugo's built-in output format routing. + +**Ghost:** Needs a reverse proxy (Nginx/Cloudflare Worker) or Ghost API-based solution. Ghost doesn't natively support content negotiation. + +### Robots.txt for AI Crawlers +Allow GPTBot, ClaudeBot, PerplexityBot, Google-Extended, Applebot-Extended: +```txt +User-agent: GPTBot +Allow: / + +User-agent: ClaudeBot +Allow: / + +User-agent: PerplexityBot +Allow: / + +User-agent: Google-Extended +Allow: / + +User-agent: Applebot-Extended +Allow: / +``` + +## Measurement + +### Core AEO Metrics +| Metric | What It Measures | How | +|--------|-----------------|-----| +| Citation Rate | How often AI cites your content | Manual LLM queries; tools like LLMrefs, AirOps Insights | +| AI Share of Voice | Brand mention frequency vs. competitors | Same prompt set across multiple LLMs | +| Query Coverage | Range of questions where content appears | Expand query into sub-questions; test each | +| AI Referral Traffic | Clicks from ChatGPT, Perplexity, etc. | GA4 source/medium reports | +| AI Overview Appearances | Visibility in Google AI Overviews | GSC → Search Appearance → AI Overviews | +| AEO Readiness Score | Site-level technical AEO readiness | AEOprobe, ansly scanners | + +### Cadence +- **Weekly:** Test 5-10 key prompts per site against major LLMs +- **Monthly:** Citation rate audit, brand mention accuracy check +- **Quarterly:** Full AEO audit (structure, schema, llms.txt, crawlability) + +### Key References +- Ethan Smith / Graphite: graphite.io/five-percent/aeo-is-the-new-seo +- Lenny's Podcast: "The ultimate guide to AEO" (Sept 2025) +- AirOps 2026 State of AI Search +- SearchAtlas: FAQPage schema → 3.2× AI Overview citations +- Ziptie.dev: 96% of AI Overviews cite already-trusted sources +- HubSpot: Page with 85 AI citations had only 1 backlink diff --git a/seo-audit/references/content-strategy-seo.md b/seo-audit/references/content-strategy-seo.md new file mode 100644 index 0000000..04ff24d --- /dev/null +++ b/seo-audit/references/content-strategy-seo.md @@ -0,0 +1,142 @@ +# Content Strategy SEO Reference + +Content strategy SEO ensures that what you write positions you to be discovered for the queries your audience actually searches for. + +## Topic Clusters & Pillar Pages + +The modern SEO content architecture replaces the old model of writing individual articles about individual keywords. Instead, content is organized into **topic clusters** centered on **pillar pages**. + +### How It Works + +- **Pillar page:** A comprehensive, long-form guide to a broad topic (e.g., "The Complete Guide to AI Agent Memory Systems"). It covers the topic broadly and links out to cluster content. +- **Cluster content:** Specific articles that dive deep into sub-topics (e.g., "What is a Vector Database?", "How RAG Works", "GraphRAG vs Vector Search"). Each cluster article links BACK to the pillar page. +- **Internal linking:** Cluster → pillar (always). Pillar → cluster (when relevant). + +### Why It Works + +- **Topical authority:** A group of pages all linking to each other around a common topic signals deep expertise to search engines +- **SERP dominance:** Instead of competing for one keyword, you compete for an entire topic area +- **User experience:** Readers naturally flow from intro content (pillar) to deep dives (clusters) + +### Applying to Platform-specific implementation notes + +**example.com — Example clusters:** +- Pillar: "AI Agent Memory Systems" +- Clusters: "Vector Databases for Agent Memory," "Knowledge Graphs vs Vector Search," "a content inventory Thought-Graph Architecture," "What is GraphRAG?" + +**example.com — Example clusters:** +- Pillar: "Enterprise AI Agent Deployment" +- Clusters: "RAG at Scale: Lessons from Production," "AI Agent Orchestration," "Security Considerations for Enterprise AI," "Cost Optimization for LLM Inference" + +## Keyword Research + +### Process +1. **Identify seed keywords** — the 3-5 core terms that define your site's domain +2. **Expand via SERP analysis** — search each seed keyword and analyze the "People also ask" box, related searches at page bottom, and the top-ranking pages' headlines +3. **Identify question-based queries** — "how does X work", "what is Y", "why Z matters" — these are excellent for featured snippet opportunities +4. **Analyze search intent** — is the query informational (learning), navigational (finding a specific site), commercial (comparing options), or transactional (buying)? Match your content type to intent. +5. **Assess competition** — are the top 10 results thin blog posts or deep authoritative guides? If the top results are weak, there's an opportunity. + +### Keyword Mapping + +Map each article to 1 primary keyword and 2-5 secondary/related keywords: + +``` +Article: "The Artifact Pyramid: Progressive Disclosure for Agent Outputs" +Primary: "artifact pyramid" +Secondary: "progressive disclosure AI", "multi-agent output structure", + "agent collaboration format", "research output pyramid" +``` + +### Tools +- Google Search Console (what queries your site already ranks for) +- Google "People also ask" / related searches (free, authoritative) +- AnswerThePublic (question-based query discovery) +- Ahrefs / Semrush (paid — comprehensive keyword data) + +## SERP Feature Targeting + +Target specific SERP features by structuring content appropriately: + +| SERP Feature | Best for | Content Structure | +|-------------|----------|-------------------| +| **Featured Snippet (Paragraph)** | "What is X" questions | Direct answer in first paragraph after H2. 40-50 words. | +| **Featured Snippet (List)** | "Steps to X", "Types of X" | Numbered or bulleted list in the content. | +| **Featured Snippet (Table)** | Comparisons, specifications | HTML table with clear headers and data. | +| **FAQ Rich Result** | Multiple related questions | FAQPage schema with 2+ Q&A pairs visible in content. | +| **HowTo Rich Result** | Tutorials, guides | HowTo schema with numbered steps. | +| **People Also Ask** | Question-based queries | Address each question in its own H2 section. | +| **Knowledge Panel** | Brand/organization queries | Organization schema, Wikipedia entry, verified social profiles. | + +## Content Gap Analysis + +### Process +1. **Identify your target keywords** (the terms you WANT to rank for) +2. **Check your current rankings** (do you already have content for these?) +3. **Analyze top 10 results** for each keyword: + - What content format are they using? (listicle, guide, video, tool) + - How long is the content? + - What angle do they take? + - What's missing from their coverage? +4. **Identify gaps:** Topics where your site has no content, or where your content is weaker than competitors' +5. **Prioritize:** Volume × difficulty × relevance — focus on high-volume gaps that you can credibly fill + +### Gap Types +- **Missing topic:** No content exists on your site for a search-worthy topic +- **Thin content:** Content exists but is significantly weaker than competitors' +- **Outdated content:** Content exists but is no longer accurate or current +- **Format gap:** Competitors rank with a format you haven't used (e.g., video, interactive tool, data study) + +## Topical Authority + +Topical authority is built over time by publishing a breadth and depth of content on a subject. It's the most defensible SEO strategy because it can't be replicated quickly. + +### Building Topical Authority +1. **Publish the pillar page first** — broad, comprehensive, definitive +2. **Publish cluster content regularly** — 2-3 sub-topic articles per month +3. **Interlink systematically** — every cluster article links to the pillar; the pillar links to clusters +4. **Refresh content** — update pillar pages annually, cluster content as needed +5. **Expand scope** — once you've covered the core topic, expand to adjacent topics + +### Signals of Topical Authority +- Your content ranks for multiple related keywords +- Your content appears in "People also ask" for the topic +- Other sites link to your content as a reference +- Your content is cited in academic or industry publications + +## Platform-specific implementation notes — SEO Opportunity Assessment + +| Site | Domain Authority | Primary Keyword Focus | Largest Gap | +|------|-----------------|----------------------|-------------| +| example.com | Low (newer personal blog) | AI philosophy, neurodiversity, engineering | Few internal links between related posts; no topic cluster structure | +| example.com | Low (newer enterprise AI blog) | Enterprise AI strategy, agentic AI | Very new — needs pillar pages and cluster strategy from the start | +| example.org | Very low (community site) | Mesh networking, MeshCore, RDUMesh | Local SEO for Raleigh/Durham; community resource queries | +| example.net | Minimal | Southeast mesh networking | Mostly informational — just needs proper on-page SEO | + +### Recommended Actions by Site + +**example.com:** +- Implement topic clusters retroactively (group existing posts into 3-4 clusters with pillar pages) +- Ensure every post links to 2-3 other posts +- Add FAQPage schema to posts that answer multiple questions +- Optimize for "People also ask" by structuring content around questions + +**example.com:** +- Plan pillar pages first before creating more isolated content +- Target question-based keywords for featured snippet opportunities +- Implement TechArticle schema on all technical posts +- Focus on long-tail, low-competition keywords in the short term + +**example.org:** +- Local SEO: "mesh network Raleigh," "MeshCore North Carolina" +- Community-Q&A content for FAQ rich results +- Event pages for meetup/community gathering SEO + +## Content Calendar + +SEO content strategy produces a **ranked list** of content opportunities, not a dated calendar. Editorial schedules vary; prioritize by evidence rather than a fixed calendar. Prioritize by: + +1. **Search volume × relevance** — How many searches × how well it fits the site +2. **Competition gap** — How much better can we be than the current top results? +3. **Ease of creation** — Does the research already exist in the vault or is it a new domain? +4. **Pillar dependency** — Should this be created before or after the pillar page? diff --git a/seo-audit/references/ghost-metadata.md b/seo-audit/references/ghost-metadata.md new file mode 100644 index 0000000..0100b6d --- /dev/null +++ b/seo-audit/references/ghost-metadata.md @@ -0,0 +1,204 @@ +# Ghost CMS Metadata & Schema Completion + +For Ghost CMS sites (example.com, example.org, example.net), the SEO specialist is responsible for completing all metadata on every published or draft article. This covers three distinct layers: Ghost CMS metadata fields, social media cards, and code-injected structured data. + +## Layer 1: Ghost CMS Metadata Fields + +Every Ghost post and page has a set of metadata fields in the post settings panel (or settable via the Ghost Admin API / ghost-cli). These must be filled for every article. + +### Fields + +| Field | Required | Purpose | Best Practice | +|-------|----------|---------|---------------| +| **Meta Title** | Always | Overrides the post title for SEO. Controls the `` tag. | 50-60 chars, primary keyword front-loaded. If not set, Ghost uses the post title (which may be too long or lack keyword focus). | +| **Meta Description** | Always | Overrides excerpt for SEO. Controls the meta description tag. | 150-160 chars, includes primary keyword + CTA, reads naturally. | +| **Custom Excerpt** | Always | Used in card previews, RSS feeds, and as fallback for meta description. | 1-2 sentences capturing the article's core argument. Shorter than meta description (~120 chars). NOT the same as meta description — serves different contexts (card previews, not SERPs). | +| **OG Title** | Recommended | Overrides the title for social sharing (Facebook, LinkedIn, Discord). | Defaults to meta title. Only needed if the social version should differ. | +| **OG Description** | Recommended | Overrides the description for social sharing. | Defaults to meta description. Only needed if the social version should differ. | +| **OG Image** | Always | The image that appears in social card previews. | Should be the article's feature/cover image. If not set, Ghost uses the feature image from the post. Set explicitly to ensure correct crop and fallback. | +| **Twitter Title** | Recommended | Overrides the title for Twitter/X card previews. | Defaults to OG title. Only needed if the Twitter version should differ. | +| **Twitter Description** | Recommended | Overrides the description for Twitter/X. | Defaults to OG description. | +| **Twitter Image** | Recommended | Overrides the image for Twitter/X. | Defaults to OG image. Twitter's card crop differs from OG — set explicitly if the feature image crop doesn't work well as a square. | +| **Canonical URL** | As needed | Overrides the canonical URL. | Only needed if the post is syndicated or republished from another source. Ghost auto-generates self-referencing canonicals. | +| **Slug** | As needed | URL path. | Set before publish. Never change after publish without a 301 redirect. | + +### Setting via ghost-cli + +The `ghost-cli` tool has a `meta set` command for individual fields: + +```bash +# Set meta title and description +ghost-cli --site example meta set <slug> \ + --meta-title "Primary Keyword Context | Groktopus" \ + --meta-description "150-160 char summary with keyword and call to action." + +# Set OG and Twitter fields +ghost-cli --site example meta set <slug> \ + --og-title "Optional: different from meta title" \ + --og-description "Optional: different from meta description" \ + --twitter-title "Optional: different from OG title" +``` + +### Setting via Ghost Admin API + +For bulk operations or automation, use the Admin API directly. The key fields in the post object are: + +```json +{ + "posts": [{ + "id": "post-id", + "meta_title": "SEO Title", + "meta_description": "SEO Description", + "custom_excerpt": "Brief excerpt for cards", + "og_image": "https://example.com/image.jpg", + "og_title": "Social Title", + "og_description": "Social Description", + "twitter_image": "https://example.com/twitter-image.jpg", + "twitter_title": "Twitter Title", + "twitter_description": "Twitter Description", + "canonical_url": null, + "codeinjection_head": "<script type=\"application/ld+json\">...</script>", + "codeinjection_foot": "" + }] +} +``` + +**Important:** When updating a post via PUT, you must include `updated_at` from the current post data — Ghost uses it for optimistic locking. Always fetch first, modify, then PUT. + +## Layer 2: Social Media Cards + +Social media cards control what appears when an article is shared on Facebook, LinkedIn, Discord, Twitter/X, Slack, and other platforms. + +### How Ghost Generates Cards + +Ghost automatically generates Open Graph and Twitter Card meta tags from the post's metadata fields: + +```html +<meta property="og:site_name" content="Groktopus"> +<meta property="og:type" content="article"> +<meta property="og:title" content="[OG Title or Meta Title or Post Title]"> +<meta property="og:description" content="[OG Description or Meta Description or Excerpt]"> +<meta property="og:image" content="[OG Image or Feature Image]"> +<meta property="og:url" content="[Post URL]"> +<meta name="twitter:card" content="summary_large_image"> +<meta name="twitter:title" content="[Twitter Title or OG Title or Meta Title]"> +<meta name="twitter:description" content="[Twitter Description or OG Description or Meta Description]"> +<meta name="twitter:image" content="[Twitter Image or OG Image or Feature Image]"> +<meta name="twitter:site" content="@example"> +<meta name="twitter:creator" content="@example"> +``` + +### Fallback Chain + +- **OG Title:** OG Title → Meta Title → Post Title +- **OG Description:** OG Description → Meta Description → Custom Excerpt +- **OG Image:** OG Image → Feature Image +- **Twitter Title:** Twitter Title → OG Title → Meta Title → Post Title +- **Twitter Image:** Twitter Image → OG Image → Feature Image + +### Verification + +```bash +# Check what tags are being emitted +curl -s https://example.com/<slug>/ | grep -E 'og:|twitter:' + +# Test with validators +# Facebook: https://developers.facebook.com/tools/debug/ +# Twitter: https://cards-dev.twitter.com/validator +# LinkedIn: https://www.linkedin.com/post-inspector/ +``` + +## Layer 3: Code-Injected Schema + +Ghost CMS auto-generates basic Article/BlogPosting schema, but custom schema types (TechArticle, FAQPage, HowTo, Organization with areaServed) must be code-injected. + +### Injection Points in Ghost + +| Location | Scope | Method | +|----------|-------|--------| +| **Site-wide** (`ghost_head`) | Every page on the site | Settings → Code Injection → Site Header | +| **Per-post** | Single post only | Post Settings → Code Injection → Post Header | +| **Per-page** | Single page only | Page Settings → Code Injection → Post Header | +| **ghost-cli** | Per-post via API | `ghost-cli --site <name> schema inject <slug> --file <path>` | + +### Per-Page Schema via ghost-cli + +The ghost-cli `schema inject` command handles the API call and stores the schema in the post's `codeinjection_head` field: + +```bash +# Validate and inject FAQPage schema +ghost-cli --site example schema validate --json '{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"Q?","acceptedAnswer":{"@type":"Answer","text":"A."}}]}' + +ghost-cli --site example schema inject my-post --file /tmp/faq-schema.json +``` + +### Injecting Multiple Schema Types with @graph + +When a post benefits from multiple schema types (e.g., TechArticle + FAQPage), wrap them in a `@graph` array: + +```json +{ + "@context": "https://schema.org", + "@graph": [ + { + "@type": "TechArticle", + "headline": "Post Title", + "proficiencyLevel": "Advanced", + "about": {"@type": "Thing", "name": "AI Agent Memory"} + }, + { + "@type": "FAQPage", + "mainEntity": [ + {"@type": "Question", "name": "Q1?", "acceptedAnswer": {"@type": "Answer", "text": "A1."}}, + {"@type": "Question", "name": "Q2?", "acceptedAnswer": {"@type": "Answer", "text": "A2."}} + ] + } + ] +} +``` + +### Schema Coverage by Site + +| Site | Required Schema | Injection Method | +|------|----------------|------------------| +| **example.com** | Organization (site-wide), TechArticle (per-post), FAQPage (when applicable) | ghost-cli `schema inject` for per-post; Code Injection → Settings for site-wide | +| **example.org** | Organization + areaServed (site-wide), Article (auto), FAQPage (FAQ content), LocalBusiness if applicable | Same pattern | +| **example.net** | Organization (site-wide), Article (auto) | Same pattern | + +### Validation + +Every schema injection must be validated: + +1. **Google Rich Results Test:** https://search.google.com/test/rich-results +2. **Schema.org Validator:** https://validator.schema.org/ +3. **Manual check:** View page source → search for `application/ld+json` + +## Completion Checklist + +For every article publish: + +- [ ] **Meta Title** set (50-60 chars, keyword front-loaded) +- [ ] **Meta Description** set (150-160 chars, includes keyword + CTA) +- [ ] **Custom Excerpt** set (1-2 sentence summary for cards) +- [ ] **OG Image** set (article feature image or explicit OG image) +- [ ] **OG Title** verified (at minimum, confirm it defaults acceptably) +- [ ] **OG Description** verified (at minimum, confirm it defaults acceptably) +- [ ] **Twitter card** type confirmed (summary_large_image) +- [ ] **Canonical URL** confirmed (self-referencing unless syndicated) +- [ ] **Schema injected** (TechArticle for example.com, FAQPage if applicable) +- [ ] **Schema validated** (Google Rich Results Test passes) +- [ ] **Feature image** has alt text and caption +- [ ] **Slug** is optimized (30-45 chars, primary keyword, stable) + +## Post-Publish Verification + +```bash +# 1. Check meta tags render +curl -s https://<site>/<slug>/ | grep -E '<title|name="description"|property="og:|name="twitter:' + +# 2. Check schema renders +curl -s https://<site>/<slug>/ | grep 'application/ld+json' + +# 3. Validate schema (requires the JSON block) +# Pipe the extracted JSON-LD to the Rich Results Test API +``` diff --git a/seo-audit/references/onpage-seo.md b/seo-audit/references/onpage-seo.md new file mode 100644 index 0000000..47670dc --- /dev/null +++ b/seo-audit/references/onpage-seo.md @@ -0,0 +1,154 @@ +# On-Page SEO Reference + +On-page optimization ensures each piece of content is structured and written to communicate relevance to search engines while serving the reader. + +## Title Tags + +The title tag is the single most important on-page SEO element. It appears in SERPs as the clickable headline. + +### Best Practices +- **Length:** 50-60 characters (Google typically displays the first 50-60 chars; titles longer than ~580px get truncated) +- **Keyword placement:** Primary keyword near the beginning (front-loaded) +- **Uniqueness:** Every page has a unique title tag — no duplicates +- **Branding:** Include site/brand name at the end (separated by `—` or `|` in SERPs, but per the publication style rule, NO emdashes in prose — for title tags, use `|` as separator) + - Example: `"SEO Audit for Ghost CMS Sites | Groktopus"` + - Example: `"The Artifact Pyramid: Progressive Disclosure for Agent Outputs | Example Author"` +- **Compelling:** Includes a value proposition or hook that earns the click +- **No keyword stuffing:** Sounds natural, not like a list of keywords + +### Platform-specific implementation notes — Patterns + +**example.com (Hugo, PaperMod theme):** +- Title set in frontmatter: `title: "..."` +- Hugo auto-generates `<title>` from the title field +- Verify: `title` in frontmatter is 50-60 chars +- Site name appended automatically by PaperMod: `"Title | Example Author"` + +**example.com (Ghost Pro):** +- Meta title set in Ghost post settings → Meta Data → Custom Meta Title +- Default: Post title (which may be too long — always set a custom meta title) +- Ghost appends site name automatically in the `<title>` tag +- Verify: custom meta title under 60 chars + +**example.org / example.net (Ghost, self-hosted):** +- Same as example.com — custom meta title in Ghost post settings + +## Meta Descriptions + +Not a direct ranking factor, but the second most important element for click-through rate from SERPs. + +### Best Practices +- **Length:** 150-160 characters (longer descriptions may be truncated) +- **Includes primary keyword + secondary keyword naturally** +- **Includes a call to action** ("Learn how...", "Discover why...", "Read the analysis") +- **Unique per page** — no duplicate or auto-generated descriptions +- **Matches search intent** — if someone searches for "progressive disclosure for agents," the description should signal that the page delivers on that query +- **Contractions and natural language** — reads like a person wrote it + +### Platform-specific implementation notes — Patterns + +**example.com (Hugo, PaperMod):** +- Hugo auto-generates meta description from page summary/content if not specified +- Always set a `description:` field in frontmatter that's 150-160 chars +- This is the meta description and also used in card previews + +**example.com (Ghost Pro):** +- Custom Meta Description in post settings → Meta Data +- Ghost also uses this for Open Graph description +- If not set, Ghost uses the post excerpt (which may be longer or shorter than ideal) + +## Heading Structure + +Headings communicate content hierarchy to search engines and provide scanability for readers. + +### Hierarchy Rules +- **H1:** Exactly one per page. Should match the title tag (or be a slightly more readable version). Contains the primary keyword. +- **H2:** Major sections of the content. Each H2 should contain a related keyword or subtopic. Used as navigation anchors. +- **H3-H6:** Subsections under H2s. Deeper hierarchy for complex content. +- **No skipping levels:** Don't jump from H1 to H3. Hierarchically nested. + +### Checklist +- [ ] Exactly one H1 per page +- [ ] H1 matches or closely relates to the title tag +- [ ] H1 contains primary keyword +- [ ] Headings form a logical outline of the page when read alone +- [ ] No empty headings or headings used purely for styling +- [ ] Keywords appear naturally in headings (not stuffed) +- [ ] H2s and H3s are descriptive, not generic ("Introduction" is weak; "Why Progressive Disclosure Matters for AI Agents" is strong) + +## Content Quality + +### Keyword Usage +- **Primary keyword appears in:** H1, first paragraph, at least one H2, URL slug +- **Keyword density:** Natural usage — don't target specific percentages. If the keyword appears naturally 3-5 times in a 1500-word article, that's fine. +- **LSI / related keywords:** Include semantically related terms that help establish topical relevance (e.g., for an article about "artifact pyramids," include terms like "progressive disclosure," "multi-agent pipelines," "agent collaboration") +- **No keyword stuffing:** Don't repeat the same phrase unnaturally + +### Content Length +- **Blog posts:** 1500-2500 words is typical for long-form content. long-form articles often run longer because they're deep analytical pieces. Longer is fine if every word earns its place. +- **Minimum to rank:** 300 words for very simple queries; 1000+ for competitive terms +- **Quality over quantity:** A tight 800-word post that answers the query completely beats a padded 2000-word post that repeats itself + +### Readability +- Short paragraphs (2-4 sentences for web reading) +- Bullet points and numbered lists for scannable information +- Bold key terms for emphasis (sparingly) +- Clear section breaks with descriptive headings + +### Freshness +- Update dates on evergreen content when significantly revised +- Add "Last updated" or "Updated" notation for major content refreshes +- Google favors freshness for certain query types (news, recent events, technology) + +## Internal Linking + +Internal links distribute page authority throughout the site and help crawlers discover content. + +### Best Practices +- **Link to related content:** Every post should link to 2-5 other posts/pages on the same site +- **Descriptive anchor text:** Use the target topic's keyword as the link text (not "click here" or "read more") +- **Link to cornerstone content:** Important pillar pages should receive more internal links +- **Natural placement:** Links should serve the reader — if it genuinely helps to read more about X, link it +- **Avoid:** Links in navigation that aren't needed, links to the same target with different anchor text, links on every instance of a term + +### Platform-specific implementation notes — Patterns + +**example.com:** Magnus uses [[wikilinks]] in draft which Hugo converts to hyperlinks. Check that wikilinks are rendering as live HTML links and pointing to existing pages. + +**example.com (Ghost):** Manual internal links in the editor. Verify that linked posts exist and are published. + +## Image Optimization + +### Alt Text +- **Purpose:** Accessibility for screen readers + context for search engines (Google Images) +- **Every image** must have a descriptive alt attribute +- **Descriptive:** "Close-up of a Portia labiata spider's principal eyes showing the characteristic three-lens system" — not "Portia spider" or "image001.jpg" +- **Keyword-optimized:** Include relevant keywords naturally when they describe the image +- **No keyword stuffing:** Alt text is first for accessibility, second for SEO +- **Decorative images:** alt="" (empty alt) for purely decorative images so screen readers skip them + +### File Names +- Descriptive, hyphenated: `portia-spider-eyes-closeup.jpg` not `IMG_4732.jpg` +- Include target keyword when appropriate +- Use hyphens, not underscores + +### File Size +- Compress images before upload (target < 100KB for standard inline images) +- Use next-gen formats: WebP (with JPEG fallback for older browsers) +- Hugo: Use `.WebP` processing or serve via CDN that auto-converts +- Ghost: Compress before uploading — Ghost does minimal image optimization + +## URL Structure + +### Best Practices +- **Short, descriptive:** `/seo-audit-ghost-cms/` not `/post/12345/` +- **Include primary keyword:** When natural +- **Hyphens, not underscores:** Google treats hyphens as word separators +- **Lowercase:** /seo-audit not /SEO-Audit +- **Stop words:** Remove unnecessary "and", "the", "of", "for" where they don't add meaning +- **Stable:** Once published, never change a URL (breaks all inbound links) + +### Platform-specific implementation notes — Patterns +- **example.com:** Hugo uses the post slug from frontmatter or filename. Verify slug is short and contains primary keyword. +- **example.com:** Ghost auto-generates slug from title. Set a custom slug in post settings if the auto-generated one is too long or doesn't contain the keyword. +- **Never change published slugs** without explicit approval from the site owner. diff --git a/seo-audit/references/schema-markup.md b/seo-audit/references/schema-markup.md new file mode 100644 index 0000000..42e104b --- /dev/null +++ b/seo-audit/references/schema-markup.md @@ -0,0 +1,244 @@ +# Schema Markup / Structured Data Reference + +Structured data helps search engines understand the content of a page and enables rich results in SERPs (FAQ snippets, HowTo steps, breadcrumbs, article previews). + +## JSON-LD Format + +Google's preferred format. Structured data is typically JSON-LD injected through the CMS, application templates, or a supported code-injection mechanism. + +### Basic Structure + +```json +{ + "@context": "https://schema.org", + "@type": "Article", + "headline": "Title of the Article", + "description": "150-160 char meta description", + "author": { + "@type": "Person", + "name": "Example Author" + }, + "datePublished": "2026-05-01", + "dateModified": "2026-05-15", + "image": "https://example.com/image.jpg", + "publisher": { + "@type": "Organization", + "name": "Groktopus", + "logo": { + "@type": "ImageObject", + "url": "https://www.example.com/favicon.png" + } + } +} +``` + +## Schema Types for Platform-specific implementation notes + +### TechArticle (example.com) +Use for technical/analytical content about AI, enterprise technology, and engineering. + +```json +{ + "@context": "https://schema.org", + "@type": "TechArticle", + "headline": "Article Title", + "description": "Description", + "author": { + "@type": "Person", + "name": "Example Author" + }, + "datePublished": "2026-05-01", + "dateModified": "2026-05-15", + "proficiencyLevel": "Advanced", + "about": { + "@type": "Thing", + "name": "Topic area" + } +} +``` + +### Article / BlogPosting (example.com) +Use for personal blog and analytical long-form content. + +```json +{ + "@context": "https://schema.org", + "@type": "BlogPosting", + "headline": "Title", + "description": "Description", + "author": { + "@type": "Person", + "name": "Example Author" + }, + "datePublished": "2026-05-01", + "dateModified": "2026-05-15" +} +``` + +For articles authored by Jasper: + +```json +{ + "@context": "https://schema.org", + "@type": "BlogPosting", + "headline": "Title", + "description": "Description", + "author": { + "@type": "Person", + "name": "Jasper" + }, + "datePublished": "2026-05-01", + "dateModified": "2026-05-15" +} +``` + +### FAQPage (All Sites) +Use when the article answers multiple distinct questions. Enables FAQ rich results in SERPs. + +```json +{ + "@context": "https://schema.org", + "@type": "FAQPage", + "mainEntity": [ + { + "@type": "Question", + "name": "Question 1?", + "acceptedAnswer": { + "@type": "Answer", + "text": "Answer text here." + } + }, + { + "@type": "Question", + "name": "Question 2?", + "acceptedAnswer": { + "@type": "Answer", + "text": "Answer text here." + } + } + ] +} +``` + +**Requirements for Google rich result eligibility:** +- Minimum 2 questions +- Questions must be visible text on the page (not hidden) +- Each Question must match visible content +- Answers must be clearly visible to the user (not just in schema) +- Google may show up to 4 FAQ entries in the SERP + +### HowTo (Tutorials, Technical Guides) +Use for step-by-step guides and tutorials on any site. + +```json +{ + "@context": "https://schema.org", + "@type": "HowTo", + "name": "How to Title", + "description": "Description of the tutorial", + "step": [ + { + "@type": "HowToStep", + "position": 1, + "name": "Step 1", + "text": "Description of step 1." + }, + { + "@type": "HowToStep", + "position": 2, + "name": "Step 2", + "text": "Description of step 2." + } + ] +} +``` + +### BreadcrumbList (Site Navigation) +Use on all sites to enable breadcrumb rich results in SERPs. + +```json +{ + "@context": "https://schema.org", + "@type": "BreadcrumbList", + "itemListElement": [ + { + "@type": "ListItem", + "position": 1, + "name": "Home", + "item": "https://www.example.com/" + }, + { + "@type": "ListItem", + "position": 2, + "name": "Category", + "item": "https://www.example.com/category/" + }, + { + "@type": "ListItem", + "position": 3, + "name": "Article Title", + "item": "https://www.example.com/article-slug/" + } + ] +} +``` + +### Organization (Site-level) +Use on all sites for site-level schema (injected globally, not per-page). + +```json +{ + "@context": "https://schema.org", + "@type": "Organization", + "name": "Site Name", + "url": "https://www.example.com/", + "logo": "https://www.example.com/favicon.png", + "sameAs": [ + "https://twitter.com/username", + "https://github.com/username" + ] +} +``` + +## Platform-Specific Implementation + +### Ghost CMS (example.com, example.org, example.net) + +**Per-page schema:** +- Ghost injects basic JSON-LD automatically (Article type with headline, dates, author) +- Custom schema (FAQPage, HowTo, TechArticle) goes in: + - Post-level: Settings → Code Injection → Post Header (`<script type="application/ld+json">...</script>`) + - Site-level: Settings → Code Injection → Site Header (BreadcrumbList, Organization) + +**Verification:** +- View source → search for `application/ld+json` +- Test with Google Rich Results Test: https://search.google.com/test/rich-results +- Test with Schema.org Validator: https://validator.schema.org/ + +**Ghost auto-generated schema limitations:** +- Ghost only generates Article/BlogPosting schema by default +- FAQPage, HowTo, TechArticle, BreadcrumbList, Product all require custom injection +- Author info in Ghost's default schema may need enrichment (add author URL, sameAs) + +### Hugo (example.com) + +**Per-page schema:** +- Add JSON-LD via Hugo template in `layouts/partials/head.html` or `layouts/_default/single.html` +- Use Hugo's `.Params` to inject article-specific values +- Conditional schema: `{{ if .Params.faq }}` for FAQPage, `{{ if .Params.howto }}` for HowTo + +**Site-level schema:** +- Organization and BreadcrumbList in the base template (`baseof.html`) + +## Validation Checklist + +- [ ] JSON is valid (no trailing commas, properly closed braces) +- [ ] Required fields present for each @type +- [ ] URLs are absolute (including https://) +- [ ] Dates are in ISO 8601 format (YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ) +- [ ] Author names match the byline +- [ ] @context is set to "https://schema.org" +- [ ] No conflicting or duplicate schema on the page +- [ ] FAQPage content matches visible page content (no hidden answers) +- [ ] Google Rich Results Test passes without errors +- [ ] Schema content is visible to users where required (FAQPage, HowTo) diff --git a/seo-audit/references/source-index.md b/seo-audit/references/source-index.md new file mode 100644 index 0000000..eea38f7 --- /dev/null +++ b/seo-audit/references/source-index.md @@ -0,0 +1,6 @@ +# Source index + +- **Source repository:** https://github.com/magnus919/hermes-profiles +- **Inspected commit:** `867a555` +- **Imported source directory:** `seo-audit` +- **Porting boundary:** Retained portable methodology, templates, scripts, and references. Removed or generalized Hermes profile, task-orchestration, memory, and rigid response-handoff assumptions. diff --git a/seo-audit/references/technical-seo.md b/seo-audit/references/technical-seo.md new file mode 100644 index 0000000..013252c --- /dev/null +++ b/seo-audit/references/technical-seo.md @@ -0,0 +1,99 @@ +# Technical SEO Reference + +Technical SEO ensures search engines can find, crawl, interpret, and index your content. If the technical foundation is broken, nothing else matters. + +## Crawlability & Indexability + +### Robots.txt +- **Purpose:** Directs crawlers which URLs to avoid +- **Check:** Does the site have a robots.txt at `/robots.txt`? +- **Check:** Are important pages accidentally disallowed? `Disallow: /` blocks ALL crawlers +- **Check:** Is the sitemap referenced? `Sitemap: https://example.com/sitemap.xml` +- **Best practice:** Allow CSS/JS files (modern crawlers need them for rendering) +- **Hosted CMS sites:** Ghost CMS auto-generates robots.txt; verify after any config change + +### XML Sitemaps +- **Purpose:** Tells crawlers about all pages and their relative importance +- **Check:** Does the sitemap exist and is it referenced in robots.txt? +- **Check:** Are only canonical URLs included? (No pagination params, sort filters, etc.) +- **Check:** Are noindex pages excluded from the sitemap? +- **Check:** Lastmod dates are accurate (not all the same date) +- **Ghost split sitemaps:** Ghost generates `sitemap-posts.xml`, `sitemap-pages.xml`, `sitemap-tags.xml`, `sitemap-authors.xml`. Verify each is present and valid. +- **Hugo:** Verify sitemap.xml is generated with correct `changefreq` and `priority` settings + +### Canonical URLs +- **Purpose:** Tells search engines which URL is the authoritative version of a page +- **Check:** Every page has a self-referencing canonical or points to the canonical version +- **Check:** No conflicting canonicals (page A canonicals to B, B canonicals to C) +- **Common issues:** HTTP/HTTPS duplication (canonical must use HTTPS if site is HTTPS), www/non-www duplication, trailing slash inconsistency +- **Ghost:** Canonical is auto-generated from the post/page slug. Verify no slug changes break inbound canonical signals. + +### Meta Robots / Noindex +- **Purpose:** Prevents indexing of specific pages +- **Check:** Pages that should be indexed don't have `<meta name="robots" content="noindex">` +- **Check:** Thin pages (tag pages, author pages, pagination) have noindex if they shouldn't rank +- **Check:** Login/admin pages have noindex + +## Page Speed + +### Core Web Vitals (Google's ranking signals) +- **LCP (Largest Contentful Paint):** < 2.5s (good), 2.5-4.0s (needs improvement), > 4.0s (poor) +- **FID (First Input Delay) / INP (Interaction to Next Paint):** < 100ms (good), 100-300ms (needs improvement), > 300ms (poor) +- **CLS (Cumulative Layout Shift):** < 0.1 (good), 0.1-0.25 (needs improvement), > 0.25 (poor) + +### Common Fixes by Platform + +**Ghost CMS:** +- Enable lazy loading for images (Ghost 5+ has built-in) +- Use a CDN for image delivery (Ghost Pro includes; self-hosted needs Cloudflare or similar) +- Limit the number of visible posts on home/tag pages (paginate aggressively) +- Disable unused Ghost integrations and background tasks +- Verify the theme isn't loading unused CSS/JS (many Ghost themes are bloated) + +**Hugo (example.com):** +- Hugo generates static HTML — inherently fast +- Image processing: use Hugo's built-in image processing to serve appropriately sized images (`.Resize`, `.Fill`, `.Fit`) +- Minify HTML output: `minify: true` in config +- Avoid excessive JavaScript (Hugo sites shouldn't need much JS) +- Verify CSS is not render-blocking (inline critical CSS if needed) + +### Tools for Measurement +- Google PageSpeed Insights (lab + field data) +- Lighthouse (Chrome DevTools) +- Web Vitals library (RUM data) +- GTmetrix / Pingdom (third-party) + +## Mobile-Friendliness + +- **Check:** Responsive design — does the site render correctly at all viewport widths? +- **Check:** Viewport meta tag present: `<meta name="viewport" content="width=device-width, initial-scale=1">` +- **Check:** Font sizes are readable on mobile (min 16px body text recommended) +- **Check:** Tap targets are adequately sized (min 48x48px recommended) +- **Check:** Content not hidden behind unplayable media or unsupported formats +- **Test:** Google's Mobile-Friendly Test + +## HTTPS & Security + +- **Check:** Valid SSL certificate (not expired, not self-signed) +- **Check:** All resources load over HTTPS (no mixed content warnings) +- **Check:** HSTS header present for repeat visitors (Strict-Transport-Security) +- **Check:** Redirects HTTP → HTTPS (301 permanent redirect) +- **Check:** No security warnings in browser (mixed content, invalid cert) + +## International SEO (If Applicable) + +- **hreflang tags:** Correctly implemented for multi-language/multi-region sites +- **Check:** Self-referencing hreflang (each page includes its own language tag as well) +- **Check:** No conflicting signals (hreflang says X, redirect says Y) + +## Ghost-Specific Technical SEO + +| Check | Where to look | Action | +|-------|---------------|--------| +| Canonical URLs | Post settings → canonical URL | Verify self-referencing or correct canonical | +| Meta robots | Code injection → per-page | No thin pages indexed | +| Sitemap | `/sitemap.xml` | Verify split sitemaps present | +| Robots.txt | `/robots.txt` | Verify sitemaps referenced, no accidental disallows | +| Structured data | Source HTML → JSON-LD | Verify Ghost's built-in JSON-LD is correct + any custom | +| AMP | Ghost settings | Verify AMP is enabled/disabled intentionally (Ghost defaults to disabled in v5+) | +| Open Graph / Twitter Cards | Post social settings | Verify Facebook and Twitter card previews |