Refactor SEO automation into unified CLI application
Major refactoring to create a clean, integrated CLI application: ### New Features: - Unified CLI executable (./seo) with simple command structure - All commands accept optional CSV file arguments - Auto-detection of latest files when no arguments provided - Simplified output directory structure (output/ instead of output/reports/) - Cleaner export filename format (all_posts_YYYY-MM-DD.csv) ### Commands: - export: Export all posts from WordPress sites - analyze [csv]: Analyze posts with AI (optional CSV input) - recategorize [csv]: Recategorize posts with AI - seo_check: Check SEO quality - categories: Manage categories across sites - approve [files]: Review and approve recommendations - full_pipeline: Run complete workflow - analytics, gaps, opportunities, report, status ### Changes: - Moved all scripts to scripts/ directory - Created config.yaml for configuration - Updated all scripts to use output/ directory - Deprecated old seo-cli.py in favor of new ./seo - Added AGENTS.md and CHANGELOG.md documentation - Consolidated README.md with updated usage ### Technical: - Added PyYAML dependency - Removed hardcoded configuration values - All scripts now properly integrated - Better error handling and user feedback Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
443
guides/SEO_ANALYZER_GUIDE.md
Normal file
443
guides/SEO_ANALYZER_GUIDE.md
Normal file
@@ -0,0 +1,443 @@
|
||||
# Multi-Site SEO Analyzer Guide
|
||||
|
||||
**Purpose:** Fetch posts from all 3 WordPress sites, analyze titles and meta descriptions, and provide AI-powered optimization recommendations.
|
||||
|
||||
**Output:** CSV with detailed analysis + Markdown summary report
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The Multi-Site SEO Analyzer does the following:
|
||||
|
||||
1. **Fetches** all published posts from your 3 WordPress sites (mistergeek.net, webscroll.fr, hellogeek.net)
|
||||
2. **Analyzes** each post's:
|
||||
- Title (length, power words, numbers, readability)
|
||||
- Meta description (presence, length, call-to-action)
|
||||
3. **Scores** posts on SEO best practices (0-100)
|
||||
4. **Generates** AI recommendations for your top priority posts
|
||||
5. **Exports** results to CSV for action
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### Step 1: Configure WordPress Access
|
||||
|
||||
Update your `.env` file with credentials for all 3 sites:
|
||||
|
||||
```bash
|
||||
# Primary site (fallback for others if not specified)
|
||||
WORDPRESS_URL=https://www.mistergeek.net
|
||||
WORDPRESS_USERNAME=your_username
|
||||
WORDPRESS_APP_PASSWORD=your_app_password
|
||||
|
||||
# Site 1: mistergeek.net (uses primary credentials if not specified)
|
||||
WORDPRESS_MISTERGEEK_URL=https://www.mistergeek.net
|
||||
WORDPRESS_MISTERGEEK_USERNAME=your_username
|
||||
WORDPRESS_MISTERGEEK_PASSWORD=your_app_password
|
||||
|
||||
# Site 2: webscroll.fr
|
||||
WORDPRESS_WEBSCROLL_URL=https://www.webscroll.fr
|
||||
WORDPRESS_WEBSCROLL_USERNAME=your_username
|
||||
WORDPRESS_WEBSCROLL_PASSWORD=your_app_password
|
||||
|
||||
# Site 3: hellogeek.net
|
||||
WORDPRESS_HELLOGEEK_URL=https://www.hellogeek.net
|
||||
WORDPRESS_HELLOGEEK_USERNAME=your_username
|
||||
WORDPRESS_HELLOGEEK_PASSWORD=your_app_password
|
||||
|
||||
# OpenRouter API (for AI recommendations)
|
||||
OPENROUTER_API_KEY=your_key
|
||||
```
|
||||
|
||||
**Note:** If a site's credentials are not specified, the script uses the primary site credentials.
|
||||
|
||||
### Step 2: Verify Your .env
|
||||
|
||||
```bash
|
||||
cat .env | grep -E "WORDPRESS|OPENROUTER"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage (with AI recommendations)
|
||||
|
||||
```bash
|
||||
python scripts/multi_site_seo_analyzer.py
|
||||
```
|
||||
|
||||
This will:
|
||||
- Fetch all posts from 3 sites
|
||||
- Analyze each post
|
||||
- Generate AI recommendations for top 10 worst-scoring posts
|
||||
- Export results to CSV and Markdown
|
||||
|
||||
### Include Draft Posts
|
||||
|
||||
```bash
|
||||
python scripts/multi_site_seo_analyzer.py --include-drafts
|
||||
```
|
||||
|
||||
Analyzes both published and draft posts. Useful for:
|
||||
- Optimizing posts before publishing
|
||||
- Recovering removed content saved as drafts
|
||||
- Getting full picture of all content
|
||||
- CSV will show `status` column (publish/draft)
|
||||
|
||||
### Skip AI (Save Cost)
|
||||
|
||||
```bash
|
||||
python scripts/multi_site_seo_analyzer.py --no-ai
|
||||
```
|
||||
|
||||
Analyzes posts without AI recommendations. Good for:
|
||||
- Quick overview
|
||||
- Sites with >500 posts (AI costs add up)
|
||||
- Budget testing
|
||||
|
||||
### Generate AI for Top 20 Posts
|
||||
|
||||
```bash
|
||||
python scripts/multi_site_seo_analyzer.py --top-n 20
|
||||
```
|
||||
|
||||
AI recommendations for 20 worst-scoring posts instead of 10.
|
||||
|
||||
### Combine Options
|
||||
|
||||
```bash
|
||||
# Analyze published + drafts with AI for top 20
|
||||
python scripts/multi_site_seo_analyzer.py --include-drafts --top-n 20
|
||||
|
||||
# Analyze drafts only (then filter in Excel to status=draft)
|
||||
python scripts/multi_site_seo_analyzer.py --include-drafts --no-ai
|
||||
```
|
||||
|
||||
### Custom Output File
|
||||
|
||||
```bash
|
||||
python scripts/multi_site_seo_analyzer.py --output output/custom_report.csv
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output Files
|
||||
|
||||
### 1. CSV Report: `seo_analysis_TIMESTAMP.csv`
|
||||
|
||||
Contains all analyzed posts with columns:
|
||||
|
||||
| Column | Description |
|
||||
|--------|-------------|
|
||||
| `site` | Website (mistergeek.net, webscroll.fr, hellogeek.net) |
|
||||
| `post_id` | WordPress post ID |
|
||||
| `title` | Post title |
|
||||
| `slug` | Post slug |
|
||||
| `url` | Full post URL |
|
||||
| `meta_description` | Current meta description |
|
||||
| `title_score` | Title SEO score (0-100) |
|
||||
| `title_issues` | Title problems (too short, no power words, etc.) |
|
||||
| `title_recommendations` | How to improve title |
|
||||
| `meta_score` | Meta description SEO score (0-100) |
|
||||
| `meta_issues` | Meta description problems |
|
||||
| `meta_recommendations` | How to improve meta |
|
||||
| `overall_score` | Combined score (40% title + 60% meta) |
|
||||
| `ai_recommendations` | Claude-generated specific recommendations |
|
||||
|
||||
### 2. Summary Report: `seo_analysis_TIMESTAMP_summary.md`
|
||||
|
||||
Human-readable markdown with:
|
||||
- Overall statistics (total posts, average score, cost)
|
||||
- Priority issues (missing meta, weak titles, weak descriptions)
|
||||
- Per-site breakdown
|
||||
- Top 5 posts to optimize on each site
|
||||
- Legend explaining scores
|
||||
|
||||
---
|
||||
|
||||
## Understanding Scores
|
||||
|
||||
### Title Score (0-100)
|
||||
|
||||
**What's analyzed:**
|
||||
- Length (target: 50-70 characters)
|
||||
- Power words (best, complete, guide, ultimate, essential, etc.)
|
||||
- Numbers (top 5, 2025, etc.)
|
||||
- Special characters that might break rendering
|
||||
|
||||
**Optimal title example:**
|
||||
"The Complete 2025 Guide to VPN Services (Updated)"
|
||||
- Length: 57 characters ✓
|
||||
- Power words: "Complete", "Guide" ✓
|
||||
- Numbers: "2025" ✓
|
||||
- Score: 95/100
|
||||
|
||||
### Meta Description Score (0-100)
|
||||
|
||||
**What's analyzed:**
|
||||
- Presence (missing = 0 score)
|
||||
- Length (target: 120-160 characters)
|
||||
- Call-to-action (learn, discover, find, check, etc.)
|
||||
|
||||
**Optimal meta example:**
|
||||
"Discover the best VPN services for 2025. Compare 50+ options, learn about encryption, and find the perfect VPN for your needs. Updated monthly."
|
||||
- Length: 149 characters ✓
|
||||
- CTA: "Discover", "Compare", "learn", "find" ✓
|
||||
- Score: 90/100
|
||||
|
||||
### Overall Score (0-100)
|
||||
|
||||
```
|
||||
Overall = (Title Score × 40%) + (Meta Score × 60%)
|
||||
```
|
||||
|
||||
Meta description weighted heavier because it directly impacts click-through rates from search results.
|
||||
|
||||
---
|
||||
|
||||
## Action Plan
|
||||
|
||||
### 1. Review Results
|
||||
|
||||
```bash
|
||||
# Open the summary report
|
||||
open output/reports/seo_analysis_*.md
|
||||
|
||||
# Or open the detailed CSV
|
||||
open output/reports/seo_analysis_*.csv
|
||||
```
|
||||
|
||||
### 2. Prioritize by Score
|
||||
|
||||
**High Priority (Score < 50):**
|
||||
- Title issues OR missing/weak meta
|
||||
- Implement AI recommendations immediately
|
||||
- Estimated impact: 10-20% CTR improvement
|
||||
|
||||
**Medium Priority (Score 50-75):**
|
||||
- Minor title or meta issues
|
||||
- Apply recommendations when convenient
|
||||
- Estimated impact: 5-10% CTR improvement
|
||||
|
||||
**Low Priority (Score > 75):**
|
||||
- Already optimized
|
||||
- Only update if major content changes
|
||||
|
||||
### 3. Batch Implementation
|
||||
|
||||
**For WordPress:**
|
||||
|
||||
1. Go to WordPress admin
|
||||
2. Edit post
|
||||
3. Update title (if recommended)
|
||||
4. Update meta description in Yoast SEO or All in One SEO:
|
||||
- Yoast: Bottom of editor → "SEO" tab → Meta description
|
||||
- AIOSEO: Right sidebar → "General" → Description
|
||||
|
||||
5. Save post
|
||||
|
||||
**OR use bulk operations** if your SEO plugin supports it.
|
||||
|
||||
### 4. Monitor Impact
|
||||
|
||||
Re-run the analyzer in 30 days:
|
||||
|
||||
```bash
|
||||
python scripts/multi_site_seo_analyzer.py
|
||||
```
|
||||
|
||||
Track improvements:
|
||||
- Average score increase
|
||||
- Fewer posts with score < 50
|
||||
- Posts moved from "Missing meta" to "Strong meta"
|
||||
|
||||
---
|
||||
|
||||
## Cost Estimation
|
||||
|
||||
### AI Recommendation Costs
|
||||
|
||||
Using Claude 3.5 Sonnet via OpenRouter ($3 input / $15 output per 1M tokens):
|
||||
|
||||
**Scenario 1: 10 posts with AI**
|
||||
- ~2,500 input tokens per post × 10 = 25,000 input tokens
|
||||
- ~500 output tokens per post × 10 = 5,000 output tokens
|
||||
- Cost: (25,000 × $3 + 5,000 × $15) / 1,000,000 = **$0.105** (~11¢)
|
||||
|
||||
**Scenario 2: 50 posts with AI**
|
||||
- 125,000 input + 25,000 output tokens
|
||||
- Cost: **$0.525** (~52¢)
|
||||
|
||||
**Scenario 3: No AI (--no-ai flag)**
|
||||
- Cost: **$0.00**
|
||||
|
||||
### Monthly Scenarios
|
||||
|
||||
| Scenario | Frequency | Cost/Month |
|
||||
|----------|-----------|-----------|
|
||||
| No AI | Weekly | $0 |
|
||||
| 10 posts/week | Weekly | ~€0.40 |
|
||||
| 20 posts/week | Weekly | ~€0.80 |
|
||||
| 50 posts/month | Once | ~€0.50 |
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Connection refused" on a site
|
||||
|
||||
**Problem:** WordPress site is down or credentials are wrong.
|
||||
|
||||
**Solutions:**
|
||||
1. Check site URL is correct (https, www vs no-www)
|
||||
2. Verify credentials: Try logging in manually
|
||||
3. Check if site has REST API enabled: `https://yoursite.com/wp-json/`
|
||||
4. Skip that site temporarily (remove from config, re-run)
|
||||
|
||||
### "No posts found"
|
||||
|
||||
**Problem:** API returns 0 posts.
|
||||
|
||||
**Solutions:**
|
||||
1. Verify credentials have permission to read posts
|
||||
2. Check if posts exist on the site
|
||||
3. Try without authentication (remove from config)
|
||||
4. Check if REST API is disabled
|
||||
|
||||
### AI recommendations are empty
|
||||
|
||||
**Problem:** OpenRouter API call failed.
|
||||
|
||||
**Solutions:**
|
||||
1. Verify OPENROUTER_API_KEY is set: `echo $OPENROUTER_API_KEY`
|
||||
2. Check API key is valid (not expired, has credits)
|
||||
3. Try with --no-ai flag to verify the rest works
|
||||
4. Check internet connection
|
||||
|
||||
### Memory issues with 1000+ posts
|
||||
|
||||
**Problem:** Script runs out of memory.
|
||||
|
||||
**Solutions:**
|
||||
1. Run --no-ai version first (lighter)
|
||||
2. Analyze one site at a time (modify config temporarily)
|
||||
3. Increase system memory or close other apps
|
||||
|
||||
---
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Analyze One Site
|
||||
|
||||
Temporarily comment out sites in config.py or create a custom script:
|
||||
|
||||
```python
|
||||
from scripts.multi_site_seo_analyzer import MultiSiteSEOAnalyzer
|
||||
from scripts.config import Config
|
||||
|
||||
analyzer = MultiSiteSEOAnalyzer()
|
||||
|
||||
# Override to just one site
|
||||
analyzer.sites_config = {
|
||||
'mistergeek.net': Config.WORDPRESS_SITES['mistergeek.net']
|
||||
}
|
||||
|
||||
analyzer.run(use_ai=True, top_n=20)
|
||||
```
|
||||
|
||||
### Export to Google Sheets
|
||||
|
||||
1. Download the CSV
|
||||
2. Open Google Sheets
|
||||
3. File → Import → Upload CSV
|
||||
4. Share link with team
|
||||
5. Filter by site or score
|
||||
6. Add "Completed" checkbox column
|
||||
7. Track progress as you optimize
|
||||
|
||||
### Integrate with WordPress via Zapier
|
||||
|
||||
1. Export CSV from analyzer
|
||||
2. Use Zapier to trigger WordPress post updates
|
||||
3. Automatically update meta descriptions for high-priority posts
|
||||
4. (Advanced - requires Zapier Pro)
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Post with Low Title Score
|
||||
|
||||
```
|
||||
Title: "VPN"
|
||||
Title Issues: Too short (3), Missing power word, No number
|
||||
Title Score: 10/100
|
||||
|
||||
Recommendation: Expand title to include benefit and year
|
||||
Better Title: "Best VPN Services 2025: Complete Guide"
|
||||
```
|
||||
|
||||
### Example 2: Post with Missing Meta
|
||||
|
||||
```
|
||||
Meta Description: [MISSING]
|
||||
Meta Score: 0/100
|
||||
|
||||
AI Recommendation:
|
||||
"Write a meta description: 'Learn about the best VPN services for 2025.
|
||||
Compare 50+ providers, understand encryption, and choose the right VPN
|
||||
for your needs. Updated weekly.' (150 characters)"
|
||||
```
|
||||
|
||||
### Example 3: Strong Post (No Changes Needed)
|
||||
|
||||
```
|
||||
Title: "The Complete Guide to NordVPN: Features, Pricing, and Reviews"
|
||||
Title Issues: None
|
||||
Title Score: 95/100
|
||||
|
||||
Meta: "Comprehensive review of NordVPN including speed tests, security features, pricing plans, and user reviews. Find out if NordVPN is right for you."
|
||||
Meta Issues: None
|
||||
Meta Score: 95/100
|
||||
|
||||
Overall Score: 95/100
|
||||
Status: No changes needed ✓
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: How often should I run this?**
|
||||
A: Monthly or after publishing 10+ new posts. More frequent for highly competitive topics.
|
||||
|
||||
**Q: Will changing titles affect SEO?**
|
||||
A: No, titles can be improved without penalty. The URL stays the same, so search rankings are preserved.
|
||||
|
||||
**Q: Should I update all weak meta descriptions?**
|
||||
A: Prioritize posts with traffic. Update high-traffic posts first for maximum impact.
|
||||
|
||||
**Q: Can I use this on a site with 5000+ posts?**
|
||||
A: Yes, but consider:
|
||||
- Using --no-ai on first run (faster)
|
||||
- Running once per month instead of weekly
|
||||
- Focusing AI analysis on high-traffic posts only
|
||||
|
||||
**Q: What if my site uses a different SEO plugin?**
|
||||
A: The script looks for common meta description fields. If it finds nothing, add one manually. Plugin doesn't matter; the meta description HTML is standard.
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Run the analyzer:** `python scripts/multi_site_seo_analyzer.py`
|
||||
2. **Review the report:** Open `output/reports/seo_analysis_*_summary.md`
|
||||
3. **Prioritize:** Identify posts with score < 50
|
||||
4. **Implement:** Update titles and meta descriptions
|
||||
5. **Track:** Re-run in 30 days to measure improvement
|
||||
6. **Monitor:** Watch Google Search Console for CTR improvements
|
||||
|
||||
Ready to optimize? Let's go! 🚀
|
||||
Reference in New Issue
Block a user