---
name: seo-geo-blog-writer
description: Create blog posts optimized for traditional search engines (SEO) and generative AI citations (GEO). Supports two modes - keyword-driven (user provides target keyword) or topic expansion (automated keyword research). Complete workflow from keyword research through schema markup generation.
---

# SEO-GEO Blog Writer

## Purpose
Create high-performing blog posts optimized for both traditional search engines (SEO) and generative AI citations (GEO) through a structured four-phase workflow: Research → Outline → Draft → Optimize.

## When to Use This Skill

Activate when user requests blog content creation. Two modes supported:

**Mode A - Keyword-Driven:**
- "Write a blog post targeting 'best CRM for small business'"
- "Create an article optimized for 'React hooks tutorial'"
- "I need a post ranking for 'email marketing automation tools'"

**Mode B - Topic Expansion:**
- "Write a blog post about email marketing"
- "Create an article on React development"
- "I need content about CRM systems"

Both modes follow the same four-phase workflow after keyword selection.

## Workflow Overview

Execute in seven phases:

1. **Research**: Gather requirements, conduct keyword research, analyze search intent, identify citation-worthy sources
2. **Outline**: Select content pattern, create structured outline with SEO-optimized headers and GEO-friendly sections
3. **Draft**: Write comprehensive content following E-E-A-T principles with proper keyword placement
4. **Optimize**: Initial content optimization and refinement
5. **Auto Internal Linking** (NEW v2.2): Discover and insert high-confidence internal links from Sanity/local content
6. **Image Generation** (Coming Week 3): Auto-generate and insert images using AI
7. **Final Validation**: Iterative validation with auto-fix for FAQ, author bio, schema, title

## Example Usage

### Example 1: Mode B (Topic Expansion with Keyword Research)

**User Request:**
"Write a blog post about empath boundaries"

**Execution Flow:**
1. **Detect Mode B** (general topic, no specific keyword)
2. **Execute keyword research:**
   ```bash
   python scripts/keyword_research.py "empath boundaries" --limit 5 --format markdown
   ```
3. **Present options to user:**
   ```
   Top keywords researched:
   1. healthy boundaries for empaths (Vol: 2,400, Diff: 45, Score: 95)
   2. how to set boundaries as an empath (Vol: 3,100, Diff: 52, Score: 92)
   3. empath boundary setting tips (Vol: 1,200, Diff: 38, Score: 88)
   
   Which would you like to target? (or 'auto' for best match)
   ```
4. **User selects:** "Let's use #1" → Keyword confirmed: "healthy boundaries for empaths"
5. **Gather remaining requirements:** audience, author details, word count (2,000 words recommended for Diff: 45)
6. Load `references/content-patterns.md` → Select "How-To Guide" pattern
7. Create outline with keyword optimization
8. Write draft following E-E-A-T guidelines
9. Execute validation and deliver complete package

**Output:** 2,000-word how-to guide optimized for "healthy boundaries for empaths" with FAQ schema, validation report, and meta tags

### Example 2: Mode A (Keyword-Driven)

**User Request:**
"Write a blog post about best email marketing tools for Shopify stores"

**Execution Flow:**
1. **Detect Mode A** (specific long-tail keyword provided)
2. **Confirm keyword:** "I'll optimize for 'best email marketing tools for Shopify stores'. Confirm?"
3. **Gather requirements:** audience (Shopify store owners), word count (2,500), author details
4. Load `references/content-patterns.md` → Select "Comparison Article" pattern
5. Load `references/seo-checklist.md` → Extract keyword strategy
6. Generate outline using `assets/blog-template.md` structure
7. Write draft following E-E-A-T guidelines from `references/eeat-guidelines.md`
8. Execute `scripts/validate_structure.py` on draft
9. Generate schema markup using `assets/structured-data-examples.json`
10. Deliver: blog post + schema markup + SEO checklist

**Output:** 2,500-word comparison article with FAQ schema, meta tags, and validation report

## Implementation Instructions

### Phase 1: Gather Requirements & Keyword Research

This skill supports two modes based on user input:

**Mode A: Keyword-Driven** (User provides specific target keyword)
**Mode B: Topic Expansion** (User provides general topic, needs keyword research)

#### Step 1: Detect Mode

Analyze user request to determine mode:

```
IF request contains specific keyword phrase in quotes → Mode A
   Example: "Write post targeting 'healthy boundaries for empaths'"
   
ELSE IF request mentions specific long-tail keyword → Mode A
   Example: "Write about best email marketing tools for Shopify stores"
   
ELSE IF request is general topic → Mode B
   Example: "Write post about empath boundaries"
   Example: "Create article on email marketing"
```

#### Step 2: Execute Mode-Specific Workflow

**MODE A: Keyword-Driven Workflow**

User has already identified target keyword. Proceed directly to validation:

1. Confirm keyword with user: "I'll optimize this post for '[keyword]'. Confirm?"
2. Collect remaining requirements:
   - Target Audience
   - Content Goal  
   - Author Details (name, credentials, bio, photo URL - critical for E-E-A-T)
   - Word Count Target (1,500-3,000 words)
3. Continue to Phase 2 (Research & Pattern Selection)

**MODE B: Topic Expansion Workflow**

User needs keyword research assistance. Execute keyword research:

1. **Run keyword research script (with credential handling):**

   The script automatically tries multiple credential methods in order:
   1. Command line argument (`--api-key`)
   2. Environment variable (`DATAFORSEO_API_KEY`)
   3. Config file (`~/.dataforseo-skill/config.json`)
   4. Fallback to heuristic mode (no API needed)

   **IMPORTANT FOR CLAUDE CODE ENVIRONMENT:**

   **Option A: Ask user for API key (if they want real data):**
   ```
   Claude: "Would you like to use the DataForSEO API for real keyword data?
           If yes, please provide your API key in format: login:password
           If no, I'll use fallback mode with intelligent estimates."

   IF user provides key:
     python scripts/keyword_research.py "user topic" --limit 5 --format markdown --api-key "user_provided_key"
   ELSE:
     python scripts/keyword_research.py "user topic" --limit 5 --format markdown
   ```

   **Option B: Use fallback mode directly (faster, no credentials needed):**
   ```bash
   # Fallback mode works without any credentials
   python scripts/keyword_research.py "user topic" --limit 5 --format markdown
   ```

   **DO NOT use `--interactive` flag** - it doesn't work in Claude Code's non-TTY environment.

   **Note:** The script automatically falls back to heuristic mode if:
   - No credentials found
   - API call fails (invalid credentials, rate limit, etc.)
   - Script provides intelligent keyword suggestions without API

3. **Present options to user:**
   
   Display top 3-5 keywords with metrics:
   - Search volume (monthly searches)
   - Keyword difficulty (0-100, lower = easier to rank)
   - Relevance score (0-100, higher = better match)
   
   Example output:
   ```
   I've researched keywords for "empath boundaries". Top options:
   
   1. healthy boundaries for empaths (Vol: 2,400, Diff: 45, Score: 95)
   2. empath boundary setting tips (Vol: 1,200, Diff: 38, Score: 88)  
   3. how to set boundaries as an empath (Vol: 3,100, Diff: 52, Score: 92)
   
   Which keyword would you like to target? (or type 'auto' for best match)
   ```

4. **Handle user selection:**

   **Option 1: User selects specific keyword**
   ```
   User: "Let's use #2"
   → Proceed with selected keyword
   ```
   
   **Option 2: User requests auto-selection**
   ```
   User: "auto" or "pick the best one"
   → Select highest relevance score
   → Inform user: "Auto-selected: [keyword] (best relevance score)"
   ```

5. **Collect remaining requirements** (same as Mode A)

6. **Continue to Phase 2**

#### Step 3: Validation & Optimization Notes

For **Mode B** keywords (researched via script):
- Note search volume in outline planning (high volume = more comprehensive content needed)
- Adjust word count based on keyword difficulty:
  - Difficulty 0-30: 1,500-2,000 words sufficient
  - Difficulty 31-60: 2,000-2,500 words recommended
  - Difficulty 61-100: 2,500-3,000+ words required

#### Fallback Handling

If `scripts/keyword_research.py` fails or is unavailable:

1. Inform user: "Keyword research tool unavailable. Using heuristic analysis."
2. Generate 3-5 variations manually using common patterns:
   - "best [topic]"
   - "how to [topic]"  
   - "[topic] guide"
   - "[topic] tips"
   - "[topic] for beginners"
3. Present options with estimated competitiveness
4. Continue workflow normally

### Phase 2: Research and Pattern Selection

**Research Steps:**
1. Identify search intent: Informational, commercial, transactional, or navigational
2. Load `references/seo-checklist.md` → Extract keyword strategy and meta optimization tactics
3. Analyze top-ranking content patterns
4. Gather citation-worthy sources: statistics, studies, expert quotes

**Pattern Selection:**
Load `references/content-patterns.md` and select appropriate structure:
- **Ultimate Guide**: Comprehensive topics (2,000+ words)
- **How-To Guide**: Process-oriented content (1,500-2,500 words)
- **Comparison/Review**: Product comparisons (2,000-3,000 words)
- **Listicle**: Roundups and curated lists (1,000-2,500 words)
- **Data-Driven Research**: Original research posts (2,000-4,000 words)

### Phase 3: Create Outline

Generate structure including:
- SEO-optimized title (primary keyword within first 60 characters)
- Introduction with hook and primary keyword in first 100 words
- 4-8 H2 sections with keyword variations
- FAQ section (4-8 questions minimum)
- Conclusion with clear CTA
- Author bio section

Use `assets/blog-template.md` as structural reference.

### Phase 4: Write Draft

Load `references/eeat-guidelines.md` and apply E-E-A-T principles:

**Experience signals:**
- Include first-hand experiences, testing results, or case studies
- Use specific examples and real scenarios
- Add screenshots, data, or proof when applicable

**Expertise signals:**
- Cite authoritative sources with proper attribution
- Include expert quotes or interviews
- Reference recent studies and statistics (with dates)
- Use precise, accurate terminology

**Authoritativeness signals:**
- Link to authoritative external sources (2-4 per article)
- Build topical clusters with internal links (3-5 per article)
- Demonstrate comprehensive topic coverage

**Trustworthiness signals:**
- Add author bio with credentials
- Include last updated date
- Provide accurate, verifiable information
- Add disclosures where relevant (affiliate links, sponsorships)

**GEO Optimization:**
Load `references/geo-optimization.md` for AI citation formatting:
- Start sections with clear, quotable statements
- Use "According to [Source]" attribution format
- Include statistics with sources and dates
- Structure data in easily extractable formats (tables, lists)
- Provide direct, concise answers in FAQ (40-60 word paragraphs)
- Include "what, why, how" question variations

### Phase 5: Auto Internal Linking (NEW v2.2)

**Automated internal link discovery and insertion:**

1. **Discover existing content from configured sources:**
   ```bash
   # Test content discovery first
   python scripts/content_sources.py \
     --sanity-project-id $SANITY_PROJECT_ID \
     --local-content ./blog-posts
   ```

   **Content source priority:**
   1. Sanity CMS API (if `SANITY_PROJECT_ID` configured)
   2. Local markdown directory (if `--local-content` provided)
   3. Fallback to empty (no links inserted)

2. **Auto-insert internal links into draft:**
   ```bash
   python scripts/auto_internal_linking.py /tmp/blog_draft.md \
     --sanity-project-id $SANITY_PROJECT_ID \
     --min-confidence 90 \
     --max-links 5 \
     --output /tmp/blog_draft_linked.md
   ```

3. **Link insertion process:**
   The script automatically:
   - Discovers existing blog posts from configured sources
   - Analyzes relevance between draft and existing content
   - Identifies high-confidence linking opportunities (≥90 relevance)
   - Inserts markdown links for first keyword occurrence
   - Avoids over-linking (max 5 links by default)

   **Example output:**
   ```
   ✓ Found 50 existing pages for internal linking
   ✓ Found 8 total suggestions
     → 5 high-confidence (≥90)

   ✓ Successfully inserted 5 links:

   1. Email marketing → /blog/email-marketing-guide (95)
   2. Marketing automation → /blog/automation-best-practices (92)
   3. Customer segmentation → /blog/segmentation-strategies (91)
   4. Email campaigns → /blog/campaign-optimization (90)
   5. ROI tracking → /blog/marketing-metrics (90)
   ```

4. **Configuration options:**

   **Via command line:**
   ```bash
   # Sanity CMS (recommended)
   python scripts/auto_internal_linking.py draft.md \
     --sanity-project-id your-project-id \
     --sanity-dataset production

   # Local markdown files
   python scripts/auto_internal_linking.py draft.md \
     --local-content ./blog-posts

   # Adjust confidence threshold
   python scripts/auto_internal_linking.py draft.md \
     --local-content ./posts \
     --min-confidence 85  # Lower threshold for more links
   ```

   **Via environment variables:**
   ```bash
   export SANITY_PROJECT_ID=your-project-id
   export SANITY_DATASET=production
   python scripts/auto_internal_linking.py draft.md
   ```

   **Via config file:** `.seo-geo-config.json`
   ```json
   {
     "sanity": {
       "project_id": "your-project-id",
       "dataset": "production"
     },
     "internal_linking": {
       "min_confidence_auto_insert": 90,
       "max_links_per_post": 5
     }
   }
   ```

5. **Continue to Phase 6** (Image Generation) or **Phase 7** (Final Validation)

### Phase 6: Image Generation (NEW v2.2)

**Automated image generation and insertion using AI APIs:**

Generate professional blog post images automatically using Google Imagen or OpenAI DALL-E 3. The system extracts image placeholders, classifies image types, generates appropriate images, and inserts them into your draft.

**1. Add image placeholders to your draft (optional):**

   During Phase 4 (drafting), add placeholders where you want images:
   ```markdown
   ![Email marketing dashboard showing analytics](placeholder)
   ![Workflow diagram showing email automation steps](placeholder)
   ```

   **Note:** Featured/hero image is auto-generated if not present.

**2. Generate images:**

   **Option A - OpenAI DALL-E 3 (easiest setup):**
   ```bash
   export OPENAI_API_KEY=sk-...

   python scripts/image_generation.py /tmp/blog_draft.md \
     --output /tmp/blog_draft_with_images.md \
     --max-images 5
   ```

   **Option B - Google Imagen (requires Google Cloud):**
   ```bash
   export GOOGLE_API_KEY=...
   export GOOGLE_PROJECT_ID=my-project

   python scripts/image_generation.py /tmp/blog_draft.md \
     --output /tmp/blog_draft_with_images.md \
     --max-images 5
   ```

   **Option C - Use configuration file:**
   ```bash
   # Configure in .seo-geo-config.json:
   {
     "image_generation": {
       "enabled": true,
       "google_api_key": "...",
       "google_project_id": "...",
       "openai_api_key": "sk-...",
       "max_images_per_post": 5,
       "output_dir": "./generated_images"
     }
   }

   python scripts/image_generation.py /tmp/blog_draft.md \
     --output /tmp/blog_draft_with_images.md
   ```

**3. Test extraction without API keys (dry-run):**
   ```bash
   python scripts/image_generation.py /tmp/blog_draft.md --dry-run

   # Output shows:
   # - Number of images that would be generated
   # - Image type and style classification
   # - Alt text and context for each image
   ```

**How it works:**

1. **Extract Image Needs:**
   - Finds all `![alt text](placeholder)` patterns
   - Auto-adds featured/hero image if none exists
   - Classifies image type (featured, section, diagram)
   - Determines appropriate style (photorealistic, illustration, diagram)

2. **Generate Images:**
   - Priority 1: Google Imagen ($0.02/image, $2000 startup credit)
   - Priority 2: OpenAI DALL-E 3 ($0.04-$0.08/image, Microsoft credits)
   - Optimized prompts for each style and image type
   - Downloads and saves images locally

3. **Insert Into Draft:**
   - Replaces `(placeholder)` with actual image paths
   - Updates alt text for SEO
   - Preserves markdown formatting

**Image Classification:**

- **Featured/Hero Images:** Photorealistic style, 1792x1024px
  - Trigger: First image or auto-generated from title
  - Example: "Professional email marketing dashboard"

- **Section Images:** Illustration style, 1024x1024px
  - Trigger: Images within content sections
  - Example: "Email list building strategy"

- **Diagrams/Infographics:** Technical diagram style, 1024x1024px
  - Trigger: Keywords like "diagram", "flowchart", "workflow", "infographic"
  - Example: "Email automation workflow diagram"

**Cost tracking:**
The script shows total generation cost and per-image pricing for budget management.

**Generated output structure:**
```
/tmp/blog_draft_with_images.md    ← Updated draft with images
./generated_images/                ← Image directory
  ├── image_abc123.png             ← Featured image
  ├── image_def456.png             ← Section image 1
  └── image_ghi789.png             ← Diagram
```

### Phase 7: Final Validation and Auto-Fix

**Validation Protocol (ALWAYS EXECUTE):**

1. **Write draft to temporary file:**
   ```bash
   # Save draft to /tmp/blog_draft.md
   ```

2. **Execute iterative validation with auto-fix:**
   ```bash
   python scripts/iterative_validation.py /tmp/blog_draft.md \
     --max-iterations 3 \
     --target-score 80 \
     --output /tmp/blog_draft_final.md
   ```

3. **Iterative validation process:**
   The script automatically:
   - Validates current draft state
   - Auto-fixes common issues (FAQ, author bio, schema templates, title length)
   - Re-validates after fixes
   - Stops when: score ≥80 OR max 3 iterations OR no more auto-fixable issues

   **Auto-fixable items:**
   - Missing FAQ section → Generates 4-6 questions from H2 headings
   - Missing author bio → Adds template (user fills details later)
   - Short title (<50 chars) → Expands with year or descriptive phrases
   - Missing schema → Adds BlogPosting and FAQPage templates

   **Non-auto-fixable items** (require manual attention):
   - Low word count → Note thin sections for expansion
   - Missing internal/external links → Needs content research
   - Missing images → Needs image sourcing or generation
   - Low readability score → Needs content restructuring

4. **Interpret results:**
   ```
   Final Score: 88/100

   Fixes Applied (4):
     ✓ Added FAQ section with 6 questions
     ✓ Added author bio template (requires user completion)
     ✓ Expanded title: 'Tips' → 'Complete Tips Guide 2025'
     ✓ Added schema markup templates (requires completion)

   ✓ PASSED (8 checks): Title optimal, Word count good, FAQ present...
   ⚠ WARNINGS (3 items): Internal links low, Images needed...
   ```

   - Score ≥80: Excellent, proceed to delivery
   - Score 60-79: Review warnings, address critical ones
   - Score <60: Fix FAILED checks manually, re-run validation

5. **Complete placeholders in auto-generated content:**
   - **Author bio**: Replace `[Author Name]`, `[job title]`, `[X years]` with real details
   - **Schema markup**: Fill in `[YYYY-MM-DD]`, `[Meta description]`, `[Featured image URL]`
   - **FAQ answers**: Expand auto-generated summaries if needed

6. **Handle script failure:**
   If script unavailable, use manual validation with `references/seo-checklist.md`:
   - Primary keyword in title, H1, first 100 words, URL slug, meta description
   - 2-3 H2 headings with keyword variations
   - Internal links (3-5) and external authority links (2-4)
   - Images with optimized alt text
   - FAQ section with schema markup
   - Author bio with credentials
   - Meta title (50-60 chars) and description (145-155 chars)

7. **Deliver final package:**
   - Complete blog post with auto-fixes applied (`/tmp/blog_draft_final.md`)
   - Validation report showing score and fixes applied
   - Schema markup code blocks (with placeholders to complete)
   - SEO checklist with verification status
   - Image suggestions with alt text
   - Internal linking recommendations

## Resource Loading Strategy

### When to Load Each Reference

**Requirements Phase (Load if needed):**
- Execute `scripts/keyword_research.py` → When Mode B detected (topic expansion needs keyword research)

**Planning Phase (Always load):**
- Read `references/content-patterns.md` → Select appropriate pattern based on topic and search intent

**Research Phase (Load if needed):**
- Read `references/seo-checklist.md` → When conducting keyword research or meta optimization
- Read `references/geo-optimization.md` → When planning citation-worthy formatting

**Draft Phase (Load selectively):**
- Read `references/eeat-guidelines.md` → When writing sections requiring credibility signals
- Use `assets/blog-template.md` → As structural reference for section organization

**Validation Phase (Always execute):**
- Execute `scripts/validate_structure.py` → After completing draft
- Read `assets/structured-data-examples.json` → When generating schema markup

### Token Efficiency for Large Files

`references/content-patterns.md` is 758 lines. For targeted reading:
```bash
# Read only specific pattern instead of entire file
grep -A 100 "## Pattern 2: How-To Guide" references/content-patterns.md
```
This approach: ~400 tokens vs ~3,000 tokens for full file.

## Output Deliverables

Provide complete package:
1. Blog post in markdown (using `assets/blog-template.md` structure)
2. SEO checklist with verification status for each item
3. Schema markup code blocks (BlogPosting + FAQPage)
4. Image suggestions with optimized alt text
5. Internal linking recommendations with anchor text
6. Validation report from script execution

## Critical Requirements (What NOT to Do)

Avoid these quality-damaging practices:
- Thin content (<1,000 words for competitive topics)
- Keyword stuffing (maintain natural readability)
- Unverifiable claims or missing citations
- Missing author credibility (E-E-A-T critical for rankings)
- Poor mobile readability (short paragraphs required)
- Clickbait tactics (damages trustworthiness signals)
- Copying competitor content (use as pattern inspiration only)
- Skipping FAQ section (critical for GEO optimization)
- Missing schema markup (required for rich results)
- No author bio (damages E-E-A-T scoring)

## Quality Targets

Target these metrics for optimal performance:
- Readability score: 60-70 (Flesch Reading Ease)
- Keyword density: 1-2% for primary keyword
- Heading hierarchy: Proper H1 → H2 → H3 structure
- FAQ section: 4-8 questions with schema markup
- Internal links: 3-5 with descriptive anchor text
- External links: 2-4 to authoritative sources
- Images: 5-8 with optimized alt text
- Word count: 1,500-3,000 (adjust for competition)
- E-E-A-T signals: Author bio, citations, first-hand experience
- Schema markup: BlogPosting + FAQPage minimum

## Optimization Factors for Best Results

**Input Quality:**
- Specific topic details improve output precision
- Real author credentials significantly improve E-E-A-T scoring
- Existing case studies or data enhance content quality
- Clear target audience definition enables better targeting

**Process Optimization:**
- Request outline approval before full draft to ensure direction alignment
- Execute validation script to catch structural issues early
- Plan content refresh every 6-12 months for freshness signals

## Related Skills

- **blog-optimizer**: Improve existing posts (different workflow from creation)
- **content-repurposer**: Convert blog posts to other formats (separate use case)