
Content Seo Optimizer
- 38 installs
- 5 repo stars
- Updated June 18, 2026
- drshailesh88/integrated_content_os
Audit published content against SERP competitors and generate a prioritized P0/P1/P2 optimization report to improve organic reach.
About
A three-agent SEO pipeline that scrapes content, analyzes SERP competitors, and produces a prioritized optimization report. A developer uses it before and after publishing to diagnose low traffic and maximize discoverability.
- Scrapes content, analyzes SERP competitors, and outputs P0/P1/P2 recommendations
- Covers blog posts, YouTube titles/tags, and newsletter landing pages
Content Seo Optimizer by the numbers
- 38 all-time installs (skills.sh)
- Ranked #1,372 of 1,879 Marketing & SEO skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/drshailesh88/integrated_content_os --skill content-seo-optimizerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 38 |
|---|---|
| repo stars | ★ 5 |
| Last updated | June 18, 2026 |
| Repository | drshailesh88/integrated_content_os ↗ |
What it does
Audit published content against SERP competitors and generate a prioritized P0/P1/P2 optimization report to improve organic reach.
Files
Content SEO Optimizer
Your content, discovered. This skill audits your published content against SERP competitors and generates a prioritized optimization roadmap.
---
When to Use
| Scenario | Use This Skill? |
|---|---|
| Before publishing a blog post | Yes - optimize before going live |
| After publishing, low traffic | Yes - diagnose and fix |
| YouTube video optimization | Yes - title, description, tags |
| Newsletter landing page | Yes - improve discoverability |
| Academic/medical content | Yes - with medical keyword focus |
---
How It Works
YOUR CONTENT URL
│
▼
┌─────────────────────────────────────────────────────────────┐
│ AGENT 1: PAGE AUDITOR │
│ │
│ • Scrapes your page (Firecrawl/WebFetch) │
│ • Extracts: title, meta, headings, word count, links │
│ • Identifies: primary keyword, secondary keywords │
│ • Flags: technical issues, content gaps │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ AGENT 2: SERP ANALYST │
│ │
│ • Searches Google/Perplexity for your primary keyword │
│ • Analyzes top 10 competitors │
│ • Extracts: title patterns, content formats, themes │
│ • Identifies: differentiation opportunities │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ AGENT 3: OPTIMIZATION ADVISOR │
│ │
│ • Synthesizes audit + SERP data │
│ • Generates McKinsey-style recommendations │
│ • Prioritizes: P0 (critical), P1 (important), P2 (nice) │
│ • Outputs: actionable report with expected impact │
└─────────────────────────────────────────────────────────────┘
│
▼
SEO AUDIT REPORT (Markdown)---
Usage
In Claude Code (Recommended)
Audit SEO for https://yoursite.com/article-about-statinsor
Use content-seo-optimizer for my blog post: [URL]For YouTube Content
Optimize SEO for my YouTube video: https://youtube.com/watch?v=xxxxxClaude will: 1. Fetch the video page 2. Analyze title, description, tags 3. Research competing videos 4. Suggest optimizations
CLI Mode
python skills/cardiology/content-seo-optimizer/scripts/seo_audit.py \
--url "https://yoursite.com/article" \
--keyword "statins cardiovascular risk" # Optional override---
Output: SEO Audit Report
# SEO Audit Report
**URL:** https://yoursite.com/statin-myths-debunked
**Audit Date:** 2026-01-01
**Primary Keyword:** statin myths
---
## Executive Summary
Your article targets "statin myths" with moderate optimization.
The title is strong but meta description is missing key terms.
Competitors are using listicle formats (5 myths, 7 facts) which
you should consider adopting. Word count (1,200) is below
competitor average (2,100).
**Overall Score:** 65/100
**Quick Wins Available:** 3 changes could boost score to 80+
---
## Technical & On-Page Findings
### Title Tag
**Current:** "Debunking Statin Myths - Dr. Singh"
**Length:** 38 characters (optimal: 50-60)
**Recommendation:** "7 Statin Myths Exposed: Cardiologist Reveals Truth [2026]"
**Rationale:** Add number, year, and authority signal
### Meta Description
**Current:** [MISSING]
**Recommendation:** "Interventional cardiologist debunks the 7 most
dangerous statin myths. Evidence-based analysis of side effects,
muscle pain, and who really needs statins."
**Length:** 158 characters (optimal)
### Heading Structure
- H1: ✅ Present ("Debunking Statin Myths")
- H2s: ⚠️ Only 2 (competitors average 7)
- H3s: ❌ None (add for each myth)
### Content Depth
- **Your word count:** 1,200
- **Competitor average:** 2,100
- **Gap:** 900 words
- **Recommendation:** Expand with clinical evidence, patient stories
### Link Profile
- Internal links: 3 (low - aim for 8-10)
- External links: 2 (good - both to journals)
- Suggested internal links:
- Your article on LDL targets
- Your cholesterol video
- Your cardiovascular risk calculator
---
## Keyword Analysis
### Primary Keyword
**Target:** "statin myths"
**Search Volume:** ~2,400/month
**Competition:** Medium
**Your Current Ranking:** Not in top 100
### Secondary Keywords (add to content)
- statin side effects myths (1,200/mo)
- do statins cause muscle pain (800/mo)
- statin benefits vs risks (600/mo)
- should I take statins (1,500/mo)
### Search Intent
**Dominant:** Informational
**User Need:** Reassurance, evidence-based answers
**Content Angle:** Counter misinformation with authority
---
## Competitive SERP Analysis
### Top 5 Competitors
| Rank | Title | Word Count | Format |
|------|-------|------------|--------|
| 1 | "5 Statin Myths That Could Kill You" | 2,400 | Listicle |
| 2 | "The Truth About Statins: What You Need to Know" | 1,800 | Guide |
| 3 | "Statin Myths and Facts - Harvard Health" | 2,100 | FAQ |
| 4 | "7 Common Statin Myths Exposed" | 1,900 | Listicle |
| 5 | "Statins: Benefits, Risks, and Myths" | 2,500 | Comprehensive |
### Patterns in Top Results
- **Titles:** Numbers (5, 7), emotional words (truth, exposed, kill)
- **Formats:** Listicles dominate (4 of 5)
- **Authority:** Medical credentials mentioned (Harvard, MD)
- **Length:** All 1,800+ words
### People Also Ask
- Are statin side effects exaggerated?
- What are the real risks of statins?
- Do statins cause memory loss?
- Should everyone over 50 take statins?
### Your Differentiation Opportunity
- **Angle:** Active interventional cardiologist perspective
- **Unique:** Real cath lab stories, patient outcomes
- **Voice:** Hinglish content not available in English SERP
---
## Prioritized Recommendations
### P0 - Critical (Do This Week)
| Action | Rationale | Impact | Effort |
|--------|-----------|--------|--------|
| Add meta description | Missing entirely - major SEO gap | High | Low |
| Restructure as listicle (7 myths) | Top 4 competitors use this format | High | Medium |
| Add year to title [2026] | Freshness signal, higher CTR | Medium | Low |
### P1 - Important (Do This Month)
| Action | Rationale | Impact | Effort |
|--------|-----------|--------|--------|
| Expand to 2,000+ words | Below competitor average by 900 | High | Medium |
| Add FAQ schema | Capture People Also Ask | Medium | Low |
| Add 5+ internal links | Low link density hurting authority | Medium | Low |
| Include patient stories | Differentiation + engagement | Medium | Medium |
### P2 - Nice to Have
| Action | Rationale | Impact | Effort |
|--------|-----------|--------|--------|
| Add video embed | Mixed media boosts dwell time | Low | Low |
| Create infographic | Shareable, backlink potential | Medium | High |
| Hindi/Hinglish version | Capture India market gap | Medium | High |
---
## Next Steps
1. **Immediate:** Add meta description (5 minutes)
2. **This week:** Restructure as "7 Statin Myths" listicle
3. **This month:** Expand content with evidence + FAQ schema
4. **Measure:** Check ranking in 2-4 weeks
5. **Iterate:** Re-audit after changes
---
## Measurement Plan
| Metric | Current | Target | Timeline |
|--------|---------|--------|----------|
| Google ranking (primary KW) | 100+ | Top 20 | 4 weeks |
| Organic traffic | 0/month | 200/month | 8 weeks |
| CTR from search | N/A | 5%+ | 4 weeks |
| Avg. time on page | Unknown | 3+ min | 4 weeks |---
Medical Content Specific Features
Pre-configured Medical Keywords
The skill understands medical/cardiology context:
| Your Topic | Suggested Keywords |
|---|---|
| Statins | statin myths, statin side effects, cholesterol medication |
| SGLT2 | SGLT2 inhibitors, diabetes heart medication, Jardiance benefits |
| Heart failure | heart failure treatment, ejection fraction, HFpEF |
| CAC scoring | coronary calcium score, heart scan, cardiac CT |
| Blood pressure | hypertension treatment, high blood pressure medication |
Medical Authority Signals
Recommendations include:
- Adding MD/cardiologist credentials to title/bio
- Citing PubMed studies (with PMIDs)
- Referencing guidelines (ACC/AHA/ESC)
- Medical schema markup
---
Integration with Other Skills
Pre-Publish Workflow
1. Write content with cardiology-newsletter-writer
2. Research with quick-topic-researcher (PMIDs)
3. Check with viral-content-predictor (engagement score)
4. Audit with content-seo-optimizer (SEO score) ← This skill
5. Refine based on recommendations
6. PublishPost-Publish Workflow
1. Publish content
2. Wait 2-4 weeks for indexing
3. Audit with content-seo-optimizer
4. Implement P0/P1 recommendations
5. Re-audit in 4 weeks---
Technical Architecture
Tools Used
| Tool | Purpose | Fallback |
|---|---|---|
| Firecrawl MCP | Page scraping | WebFetch |
| Perplexity MCP | SERP research | WebSearch |
| Claude | Analysis & report | - |
Dependencies
# Optional - for CLI mode with Firecrawl
pip install firecrawl-py
# For Google ADK version (advanced)
pip install google-adk pydantic>=2.7.0API Keys
| Key | Purpose | Required? |
|---|---|---|
| FIRECRAWL_API_KEY | Page scraping | Optional (use WebFetch fallback) |
| GOOGLE_API_KEY | SERP research | Already have |
| PERPLEXITY_API_KEY | Alternative SERP | Already have |
---
Comparison with Paid Tools
| Feature | This Skill | Ahrefs ($99/mo) | Semrush ($119/mo) |
|---|---|---|---|
| Page audit | ✅ | ✅ | ✅ |
| SERP analysis | ✅ | ✅ | ✅ |
| Keyword suggestions | ✅ | ✅ | ✅ |
| Competitor analysis | ✅ | ✅ | ✅ |
| Medical context | ✅ | ❌ | ❌ |
| Integrated with your content system | ✅ | ❌ | ❌ |
| Cost | $0 | $99/mo | $119/mo |
---
Example Session
User: Audit SEO for https://drshailesh.com/statin-myths
Claude:
I'll perform a comprehensive SEO audit using the 3-agent pipeline.
Agent 1: Page Auditor [Fetches page, extracts structure, identifies keywords]
Agent 2: SERP Analyst [Researches "statin myths", analyzes top 10 competitors]
Agent 3: Optimization Advisor [Synthesizes findings into prioritized report]
---
SEO Audit Report
[Full report as shown above]
---
Quick Wins You Can Do Right Now: 1. Add meta description (copy from report) 2. Add [2026] to title 3. Change H1 to "7 Statin Myths..."
Would you like me to help implement any of these changes?
---
This skill turns your great content into discoverable content.
# Content SEO Optimizer dependencies
# Core
anthropic>=0.18.0
python-dotenv>=1.0.0
rich>=13.0.0
# Web scraping
requests>=2.31.0
beautifulsoup4>=4.12.0
# Optional - for advanced scraping
# firecrawl-py>=0.0.1
# Optional - for Google ADK version
# google-adk
# pydantic>=2.7.0
#!/usr/bin/env python3
"""
Content SEO Optimizer - Three-agent SEO audit pipeline.
Scrapes your content → analyzes SERP competitors → generates prioritized
optimization report with P0/P1/P2 recommendations.
Usage:
python seo_audit.py --url "https://yoursite.com/article"
python seo_audit.py -u "https://yoursite.com/article" --keyword "statins"
Requirements:
pip install anthropic python-dotenv rich requests beautifulsoup4
Optional (for better scraping):
pip install firecrawl-py
"""
import os
import sys
import re
import json
import argparse
from datetime import datetime
from pathlib import Path
from urllib.parse import urlparse
from dotenv import load_dotenv
try:
import requests
from bs4 import BeautifulSoup
SCRAPING_AVAILABLE = True
except ImportError:
SCRAPING_AVAILABLE = False
try:
from rich.console import Console
from rich.markdown import Markdown
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn
RICH_AVAILABLE = True
except ImportError:
RICH_AVAILABLE = False
# Load environment variables
load_dotenv()
console = Console() if RICH_AVAILABLE else None
def print_output(text, style=None):
"""Print with or without rich formatting."""
if RICH_AVAILABLE and console:
if style:
console.print(text, style=style)
else:
console.print(text)
else:
print(text)
def print_markdown(md_text):
"""Print markdown with or without rich formatting."""
if RICH_AVAILABLE and console:
console.print(Markdown(md_text))
else:
print(md_text)
def scrape_page(url: str) -> dict:
"""
Scrape a webpage and extract SEO-relevant elements.
Returns a dict with title, meta_description, headings, word_count, links, etc.
"""
if not SCRAPING_AVAILABLE:
return {
"error": "requests/beautifulsoup4 not installed",
"url": url,
"title": "[Could not scrape - install requests beautifulsoup4]",
"meta_description": "",
"h1": "",
"headings": [],
"word_count": 0,
"internal_links": 0,
"external_links": 0,
"content_preview": ""
}
try:
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36'
}
response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# Extract title
title_tag = soup.find('title')
title = title_tag.get_text().strip() if title_tag else ""
# Extract meta description
meta_desc = soup.find('meta', attrs={'name': 'description'})
meta_description = meta_desc.get('content', '').strip() if meta_desc else ""
# Extract H1
h1_tag = soup.find('h1')
h1 = h1_tag.get_text().strip() if h1_tag else ""
# Extract all headings
headings = []
for tag in ['h1', 'h2', 'h3', 'h4']:
for heading in soup.find_all(tag):
headings.append({
"tag": tag,
"text": heading.get_text().strip()[:100]
})
# Count words in main content
# Remove script and style elements
for script in soup(["script", "style", "nav", "footer", "header"]):
script.decompose()
text = soup.get_text()
words = text.split()
word_count = len(words)
# Count links
parsed_url = urlparse(url)
base_domain = parsed_url.netloc
internal_links = 0
external_links = 0
for link in soup.find_all('a', href=True):
href = link['href']
if href.startswith('http'):
link_domain = urlparse(href).netloc
if base_domain in link_domain:
internal_links += 1
else:
external_links += 1
elif href.startswith('/'):
internal_links += 1
# Content preview (first 500 chars)
content_preview = ' '.join(words[:100])
return {
"url": url,
"title": title,
"title_length": len(title),
"meta_description": meta_description,
"meta_description_length": len(meta_description),
"h1": h1,
"headings": headings,
"heading_count": {
"h1": len([h for h in headings if h["tag"] == "h1"]),
"h2": len([h for h in headings if h["tag"] == "h2"]),
"h3": len([h for h in headings if h["tag"] == "h3"]),
"h4": len([h for h in headings if h["tag"] == "h4"]),
},
"word_count": word_count,
"internal_links": internal_links,
"external_links": external_links,
"content_preview": content_preview
}
except Exception as e:
return {
"error": str(e),
"url": url,
"title": "",
"meta_description": "",
"h1": "",
"headings": [],
"word_count": 0,
"internal_links": 0,
"external_links": 0,
"content_preview": ""
}
def infer_primary_keyword(page_data: dict) -> str:
"""Infer the primary keyword from page data."""
# Combine title, h1, and meta for keyword inference
text = f"{page_data.get('title', '')} {page_data.get('h1', '')} {page_data.get('meta_description', '')}"
# Simple keyword extraction - in production, use TF-IDF or Claude
words = text.lower().split()
# Filter common words
stop_words = {'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been',
'being', 'have', 'has', 'had', 'do', 'does', 'did', 'will',
'would', 'could', 'should', 'may', 'might', 'must', 'shall',
'can', 'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by',
'from', 'as', 'into', 'through', 'during', 'before', 'after',
'above', 'below', 'between', 'under', 'again', 'further',
'then', 'once', 'here', 'there', 'when', 'where', 'why',
'how', 'all', 'each', 'few', 'more', 'most', 'other', 'some',
'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so',
'than', 'too', 'very', 'just', 'and', 'but', 'if', 'or',
'because', 'until', 'while', 'about', 'against', 'what',
'which', 'who', 'whom', 'this', 'that', 'these', 'those',
'am', 'your', 'you', 'my', 'me', 'we', 'our', 'us', 'it',
'its', 'they', 'them', 'their', '-', '|', '–', '—'}
filtered = [w for w in words if w not in stop_words and len(w) > 2]
# Get most common 2-3 word phrase
if len(filtered) >= 2:
return ' '.join(filtered[:3])
elif filtered:
return filtered[0]
else:
return "content optimization"
def generate_audit_prompt(page_data: dict, primary_keyword: str) -> str:
"""Generate the prompt for Claude to create the SEO audit report."""
headings_text = "\n".join([f" - {h['tag'].upper()}: {h['text']}" for h in page_data.get('headings', [])[:15]])
prompt = f"""You are an expert SEO consultant creating an audit report for medical/cardiology content.
PAGE DATA:
- URL: {page_data.get('url', 'Unknown')}
- Title: {page_data.get('title', 'Missing')} ({page_data.get('title_length', 0)} chars)
- Meta Description: {page_data.get('meta_description', 'MISSING')} ({page_data.get('meta_description_length', 0)} chars)
- H1: {page_data.get('h1', 'Missing')}
- Headings Structure:
{headings_text}
- Word Count: {page_data.get('word_count', 0)}
- Internal Links: {page_data.get('internal_links', 0)}
- External Links: {page_data.get('external_links', 0)}
INFERRED PRIMARY KEYWORD: {primary_keyword}
TASK: Generate a comprehensive SEO audit report with:
1. **Executive Summary** (2-3 paragraphs)
- Overall assessment
- Key strengths and weaknesses
- Quick wins available
2. **Technical & On-Page Findings**
- Title tag analysis + recommendation
- Meta description analysis + recommendation
- Heading structure analysis
- Word count vs competitor benchmarks (medical content: 1,500-2,500 words)
- Link profile assessment
3. **Keyword Analysis**
- Primary keyword assessment
- Secondary keyword suggestions (medical/cardiology focused)
- Search intent analysis
4. **Competitive Insights**
- What top-ranking medical content typically includes
- Common patterns in successful health content
- Differentiation opportunities for a cardiologist
5. **Prioritized Recommendations**
- P0 (Critical - do this week): 2-3 items
- P1 (Important - do this month): 3-4 items
- P2 (Nice to have): 2-3 items
For each recommendation include:
- Specific action
- Rationale (reference the data)
- Expected impact (High/Medium/Low)
- Effort required (Low/Medium/High)
6. **Next Steps**
- Measurement plan
- Timeline suggestions
FORMAT: Return as clean Markdown, starting with "# SEO Audit Report"
MEDICAL CONTENT CONTEXT:
- This is for a cardiologist's content
- Authority signals (MD, cardiologist) are important
- Citing medical studies (PMIDs) adds credibility
- Accuracy trumps virality for medical content
- Consider E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness)
"""
return prompt
def run_seo_audit_with_claude(page_data: dict, primary_keyword: str) -> str:
"""Execute the SEO audit using Claude API."""
try:
import anthropic
client = anthropic.Anthropic()
prompt = generate_audit_prompt(page_data, primary_keyword)
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
messages=[
{
"role": "user",
"content": prompt
}
]
)
return message.content[0].text
except ImportError:
return generate_manual_audit_template(page_data, primary_keyword)
except Exception as e:
print_output(f"Error calling Claude API: {e}", style="red")
return generate_manual_audit_template(page_data, primary_keyword)
def generate_manual_audit_template(page_data: dict, primary_keyword: str) -> str:
"""Generate a template when API is not available."""
template = f"""# SEO Audit Report
**URL:** {page_data.get('url', 'Unknown')}
**Audit Date:** {datetime.now().strftime("%Y-%m-%d")}
**Primary Keyword:** {primary_keyword}
---
## Page Analysis (Raw Data)
### Title Tag
- **Current:** {page_data.get('title', 'MISSING')}
- **Length:** {page_data.get('title_length', 0)} characters
- **Optimal:** 50-60 characters
- **Status:** {"✅ Good length" if 50 <= page_data.get('title_length', 0) <= 60 else "⚠️ Needs adjustment"}
### Meta Description
- **Current:** {page_data.get('meta_description', 'MISSING') or 'MISSING'}
- **Length:** {page_data.get('meta_description_length', 0)} characters
- **Optimal:** 150-160 characters
- **Status:** {"✅ Present" if page_data.get('meta_description') else "❌ MISSING - Critical issue"}
### Heading Structure
- H1 count: {page_data.get('heading_count', {}).get('h1', 0)} {"✅" if page_data.get('heading_count', {}).get('h1', 0) == 1 else "⚠️"}
- H2 count: {page_data.get('heading_count', {}).get('h2', 0)} {"✅" if page_data.get('heading_count', {}).get('h2', 0) >= 3 else "⚠️ Add more H2s"}
- H3 count: {page_data.get('heading_count', {}).get('h3', 0)}
### Content Depth
- **Word count:** {page_data.get('word_count', 0)}
- **Medical content benchmark:** 1,500-2,500 words
- **Status:** {"✅ Good depth" if page_data.get('word_count', 0) >= 1500 else "⚠️ Consider expanding"}
### Link Profile
- **Internal links:** {page_data.get('internal_links', 0)} {"✅" if page_data.get('internal_links', 0) >= 5 else "⚠️ Add more internal links"}
- **External links:** {page_data.get('external_links', 0)} {"✅" if page_data.get('external_links', 0) >= 2 else "⚠️ Add authoritative sources"}
---
## Quick Wins (P0)
1. {"Add meta description" if not page_data.get('meta_description') else "Optimize meta description"}
2. {"Add more H2 headings" if page_data.get('heading_count', {}).get('h2', 0) < 3 else "Review heading structure"}
3. {"Expand content to 1,500+ words" if page_data.get('word_count', 0) < 1500 else "Optimize for primary keyword"}
---
## Next Steps
For a complete audit with competitor analysis and detailed recommendations:
1. Open Claude Code with web access
2. Run: "Audit SEO for {page_data.get('url', 'your-url')}"
3. Claude will perform SERP analysis and generate full report
---
*Template generated by content-seo-optimizer CLI*
*For full analysis, run in Claude Code with Perplexity/WebSearch access*
"""
return template
def save_report(report: str, url: str, output_dir: str = None) -> str:
"""Save the SEO audit report to a file."""
if output_dir is None:
output_dir = os.path.expanduser("~/seo_audits")
Path(output_dir).mkdir(parents=True, exist_ok=True)
# Clean URL for filename
parsed = urlparse(url)
safe_name = f"{parsed.netloc}_{parsed.path}".replace('/', '_').replace('.', '_')[:50]
timestamp = datetime.now().strftime("%Y%m%d_%H%M")
filename = f"seo_audit_{safe_name}_{timestamp}.md"
filepath = os.path.join(output_dir, filename)
with open(filepath, 'w') as f:
f.write(report)
return filepath
def main():
parser = argparse.ArgumentParser(
description="Content SEO Optimizer - Audit your content for search optimization"
)
parser.add_argument(
"-u", "--url",
required=True,
help="URL to audit (e.g., https://yoursite.com/article)"
)
parser.add_argument(
"-k", "--keyword",
help="Primary keyword (optional - will be inferred if not provided)"
)
parser.add_argument(
"-o", "--output",
help="Output directory for saving the report (default: ~/seo_audits/)"
)
parser.add_argument(
"--no-save",
action="store_true",
help="Don't save the report to a file"
)
parser.add_argument(
"--scrape-only",
action="store_true",
help="Only scrape the page, don't generate full report"
)
args = parser.parse_args()
# Header
print_output("\n" + "="*60, style="blue")
print_output("CONTENT SEO OPTIMIZER", style="bold blue")
print_output("="*60 + "\n", style="blue")
print_output(f"URL: {args.url}", style="cyan")
# Step 1: Scrape page
print_output("\nStep 1: Scraping page...", style="yellow")
page_data = scrape_page(args.url)
if page_data.get("error"):
print_output(f"Warning: {page_data['error']}", style="red")
print_output(f" Title: {page_data.get('title', 'N/A')[:60]}...", style="dim")
print_output(f" Word count: {page_data.get('word_count', 0)}", style="dim")
print_output(f" Headings: H1={page_data.get('heading_count', {}).get('h1', 0)}, "
f"H2={page_data.get('heading_count', {}).get('h2', 0)}, "
f"H3={page_data.get('heading_count', {}).get('h3', 0)}", style="dim")
if args.scrape_only:
print_output("\n" + json.dumps(page_data, indent=2))
return
# Step 2: Infer keyword
primary_keyword = args.keyword or infer_primary_keyword(page_data)
print_output(f"\nStep 2: Primary keyword: {primary_keyword}", style="yellow")
# Step 3: Generate report
print_output("\nStep 3: Generating SEO audit report...", style="yellow")
print_output("(This may take 30-60 seconds)\n", style="dim")
report = run_seo_audit_with_claude(page_data, primary_keyword)
# Step 4: Display results
print_output("\n" + "="*60, style="green")
print_output("SEO AUDIT REPORT", style="bold green")
print_output("="*60 + "\n", style="green")
print_markdown(report)
# Step 5: Save if requested
if not args.no_save:
filepath = save_report(report, args.url, args.output)
print_output(f"\nReport saved to: {filepath}", style="green")
print_output("\n" + "="*60, style="blue")
print_output("Audit complete!", style="bold blue")
print_output("="*60 + "\n", style="blue")
if __name__ == "__main__":
main()