Keyword research methodology, on-page SEO checklist, content cluster strategy, meta description templates, internal linking, SERP analysis, and E-E-A-T signals
Use this skill when the user asks to:
MANDATORY: Before generating ANY SEO content, load the brand voice configuration.
from brand_voice.config import load_brand_voice
brand = load_brand_voice()
SEO content must:
anti_slop validation — search engines increasingly penalize generic AI contentbrand.tone — consistency across all content builds brand authorityStart with the business, not the tool. Extract seed keywords from:
Template for seed extraction:
seed_keywords:
from_product:
- "[feature] + [use case]" # e.g., "content calendar automation"
from_customer_language:
- "[how customers describe the problem]" # e.g., "spending too much time on social media"
from_competitors:
- "[terms competitors rank for]"
from_communities:
- "[questions people ask]" # e.g., "how to plan content for LinkedIn"
For each seed keyword, expand using these methods:
| Method | What It Finds | Example | |--------|--------------|---------| | Google Autocomplete | Real user queries | Type seed → note suggestions | | People Also Ask (PAA) | Question-form queries | Search seed → extract PAA boxes | | Related Searches | Semantic variations | Bottom of SERP → related queries | | Forum Mining | Long-tail, problem-aware queries | Reddit/Quora → actual questions | | Competitor Gap | Keywords competitors rank for that you don't | Tools: Ahrefs, SEMrush content gap |
Every keyword has a search intent. Mismatching intent = wasted content.
| Intent | Searcher Wants | Content Format | Funnel Stage | |--------|---------------|----------------|-------------| | Informational | Learn or understand | Blog post, guide, video, infographic | TOFU | | Navigational | Find a specific site/page | Brand page, login page | N/A | | Commercial Investigation | Compare options | Comparison post, review, "best X" list | MOFU | | Transactional | Buy or take action | Landing page, pricing page, product page | BOFU |
How to determine intent:
Score each keyword opportunity:
keyword_score:
keyword: "[term]"
monthly_volume: "[number]"
keyword_difficulty: "[0-100]"
search_intent: "[informational | commercial | transactional]"
business_relevance: "[1-5, how close to your product's value]"
current_ranking: "[position or 'not ranking']"
content_exists: "[yes/no — do you already have content for this?]"
priority_score: "[calculated: relevance × (volume / difficulty)]"
Prioritization rules:
Map keywords to content and URLs:
keyword_map:
- primary_keyword: "[main target]"
secondary_keywords:
- "[variation 1]"
- "[variation 2]"
target_url: "[/path/to/content]"
content_type: "[blog | landing | guide | comparison]"
status: "[planned | draft | published | needs-update]"
cluster: "[which content cluster this belongs to]"
Use this checklist for every piece of content before publishing.
Title tag formulas:
[Number] + [Adjective] + [Keyword] + [Promise]
→ "7 Proven Content Calendar Templates That Save 10 Hours/Week"
How to + [Keyword] + [Without Objection]
→ "How to Build a Content Strategy Without a Full Marketing Team"
[Keyword]: [Specific Benefit or Framework]
→ "Content Clusters: The Hub-and-Spoke Model for Topical Authority"
Meta description templates:
[Benefit statement]. [Specific detail]. [CTA].
→ "Build your content calendar in 10 minutes. Includes templates for
LinkedIn, Twitter, and email. Get the free guide."
[Question that matches search intent]? [Answer preview]. [CTA].
→ "Struggling with consistent content? Here's the 3-pillar framework
used by 500+ marketing teams. Start planning today."
[Problem] → [Solution]. [Proof]. [CTA].
→ "Spending 15 hours/week on social content? Automate your workflow
with . ."
✅ /content-calendar-templates
❌ /blog/2025/03/15/content-calendar-templates-for-marketing-teams-2025
content-calendar-template.png not IMG_4521.pngContent clusters (also called topic clusters) are the foundation of modern SEO architecture. They build topical authority and help Google understand your expertise.
Structure:
┌── Spoke: "How to Write LinkedIn Posts"
│
Pillar (Hub): ──────┼── Spoke: "Content Calendar Templates"
"Content Marketing │
Strategy Guide" ├── Spoke: "B2B vs B2C Content Strategy"
│
├── Spoke: "Content Distribution Channels"
│
└── Spoke: "Measuring Content ROI"
Step 1: Choose the pillar topic
Step 2: Map spoke topics
content_cluster:
pillar:
topic: "[Broad topic]"
target_keyword: "[High-volume head term]"
url: "/[topic-slug]"
format: "comprehensive guide (3,000-5,000 words)"
intent: "informational"
spokes:
- topic: "[Sub-topic 1]"
target_keyword: "[Long-tail keyword]"
url: "/[topic-slug]/[sub-topic-slug]"
format: "[blog post | how-to | comparison | template]"
intent: "[informational | commercial]"
links_to_pillar: true
internal_links:
- "[other spoke URL that's related]"
Step 3: Internal linking rules
Step 4: Content creation order
| Metric | Target | Why | |--------|--------|-----| | Spokes per cluster | 8-15 | Enough for authority, not so many you're thin | | Internal links per spoke | 3-5 | Distributes authority without over-linking | | Cluster traffic growth | 20%+ QoQ | Proves topical authority is building | | Pillar page ranking | Top 10 for head term | The goal of the whole cluster | | Spoke conversion rate | > site average | Spokes should drive qualified traffic |
Before creating content for any keyword, study what's already ranking:
Step 1: Search the primary keyword Note:
Step 2: Analyze top 3 results
serp_analysis:
keyword: "[target keyword]"
serp_features:
featured_snippet: "[yes/no — type if yes]"
people_also_ask: "[list top 4 PAA questions]"
video_carousel: "[yes/no]"
local_pack: "[yes/no]"
knowledge_panel: "[yes/no]"
top_results:
- position: 1
url: "[URL]"
title: "[Title tag]"
content_type: "[blog | guide | tool | landing]"
word_count: "[approximate]"
strengths: "[what they do well]"
gaps: "[what they miss that we can cover]"
- position: 2
# ...same structure
- position: 3
# ...same structure
content_strategy:
format: "[what format to use based on SERP]"
angle: "[unique angle that fills gaps]"
target_length: "[word count based on competitors]"
featured_snippet_opportunity: "[yes/no — and how to target it]"
Step 3: Identify the content gap The gap is what makes your content worth ranking over what already exists:
If a featured snippet exists for your keyword, optimize for it:
| Snippet Type | How to Target | |-------------|--------------| | Paragraph | Answer the question in 40-50 words directly under an H2 that matches the query | | List | Use an ordered or unordered list with H2 matching the query | | Table | Use an HTML table with clear headers | | Video | Create a video with the keyword in title, timestamped chapters |
E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness) is Google's framework for evaluating content quality. It's not a direct ranking factor but influences how quality raters evaluate your site.
| Signal | Definition | How to Demonstrate | |--------|-----------|-------------------| | Experience | First-hand experience with the topic | Share personal/company results, case studies, screenshots, original data | | Expertise | Deep knowledge in the subject area | Author bios, credentials, detailed technical content, cite primary sources | | Authoritativeness | Recognized authority in the field | Backlinks from authoritative sites, mentions, industry recognition, original research | | Trustworthiness | Accurate, honest, and transparent | HTTPS, clear author identity, sources cited, corrections policy, no misleading claims |
Google's stance: AI-generated content is fine IF it demonstrates E-E-A-T. The key is:
Internal links are the most underrated SEO lever — they're free, you control them, and they directly influence crawl behavior and authority distribution.
Core rules:
`` 50% — Exact or partial keyword match 30% — Descriptive / contextual phrase 20% — Branded or generic ("this guide", "our analysis") ``
internal_linking_plan:
target_page:
url: "[new page URL]"
primary_keyword: "[target keyword]"
inbound_links:
- source_url: "[page linking TO the new page]"
anchor_text: "[text used for the link]"
context: "[paragraph where link is placed]"
type: "[contextual | navigational | footer]"
outbound_links:
- target_url: "[page the new page links TO]"
anchor_text: "[text used]"
relevance: "[why this link makes sense for the reader]"
| Metric | Target | What It Measures | |--------|--------|-----------------| | LCP (Largest Contentful Paint) | < 2.5s | Loading performance | | INP (Interaction to Next Paint) | < 200ms | Interactivity | | CLS (Cumulative Layout Shift) | < 0.1 | Visual stability |
| Schema Type | When to Use | Impact | |------------|-------------|--------| | Article | Blog posts, guides | Rich results, author display | | FAQ | Pages with Q&A sections | FAQ rich results, more SERP real estate | | HowTo | Tutorial/process content | Step-by-step rich results | | Product | Product pages | Price, availability, reviews in SERPs | | Organization | Homepage | Knowledge panel data | | BreadcrumbList | All pages | Better SERP display, navigation context |
seo_content_calendar:
month: "YYYY-MM"
cluster: "[content cluster name]"
items:
- week: 1
keyword: "[target keyword]"
title: "[working title]"
format: "[blog | guide | comparison | template]"
intent: "[informational | commercial | transactional]"
word_count_target: "[based on SERP analysis]"
author: "[who writes]"
status: "[planned | writing | review | published]"
target_url: "[planned URL]"
internal_links_from: ["[list of pages that will link to this]"]
notes: "[any special considerations]"
output_contract:
format: markdown
required_sections:
- frontmatter:
type: string # "seo-content"
subtype: string # "keyword-research" | "content-brief" | "on-page-audit" | "cluster-plan" | "serp-analysis"
status: string # "draft" | "review" | "approved"
date: string # ISO 8601
author: string # "seo-growth"
target_keyword: string # primary keyword
search_intent: string # "informational" | "commercial" | "transactional"
- seo_metadata:
title_tag: string # 50-60 chars
meta_description: string # 150-160 chars
url_slug: string # short, keyword-rich
primary_keyword: string
secondary_keywords: list
target_word_count: integer
- content:
format: string # matches SERP intent
sections: list # H2 outline with keywords mapped
internal_links: list # planned internal links
schema_markup: string # recommended schema type
- competitive_context:
serp_analysis: object # top 3 competitors analyzed
content_gap: string # what unique angle we take
featured_snippet_target: boolean
- quality_gates:
on_page_checklist_passed: boolean
eeat_signals_present: boolean
anti_slop_passed: boolean
brand_voice_aligned: boolean
validation:
anti_slop: true
brand_voice: true
title_length: "50-60 chars"
meta_description_length: "150-160 chars"
min_internal_links: 3
schema_markup_required: true