--- name: seo-data description: Connect to analytics services (GA4, GSC, DataForSEO, Umami) for performance data. Optional per-project configuration. Services are skipped if not configured. --- # 📊 SEO Data - Analytics Integrations **Skill Name:** `seo-data` **Category:** `quick` **Load Skills:** `[]` --- ## 🚀 Purpose Connect to analytics services for content performance data: - ✅ **Google Analytics 4** - Traffic, engagement, conversions - ✅ **Google Search Console** - Rankings, impressions, CTR - ✅ **DataForSEO** - Competitor analysis, SERP data, keyword research - ✅ **Umami Analytics** - Privacy-first analytics (if self-hosted) **Key Feature:** All services are **optional**. Skill skips unconfigured services silently. **Use Cases:** 1. Get page performance from all configured services 2. Find quick-win keywords (ranking 11-20) 3. Analyze competitor gaps 4. Track content performance over time 5. Identify declining content --- ## 📋 Per-Project Configuration Each website project has its own data service config in `context/data-services.json`: ```json { "ga4": { "enabled": true, "property_id": "G-XXXXXXXXXX", "credentials_path": "./ga4-credentials.json" }, "gsc": { "enabled": true, "site_url": "https://yoursite.com", "credentials_path": "./gsc-credentials.json" }, "dataforseo": { "enabled": false, "login": "your_login", "password": "your_password" }, "umami": { "enabled": true, "api_url": "https://analytics.yoursite.com", "api_key": "your_api_key" } } ``` --- ## 🔄 Workflows ### **Workflow 1: Get Page Performance** ```python Input: Page URL + project context Process: 1. Load data-services.json 2. Initialize enabled services only 3. Fetch data from each service (in parallel) 4. Aggregate results 5. Skip failed services silently Output: - GA4: Page views, engagement time, bounce rate - GSC: Impressions, clicks, avg position, CTR - DataForSEO: Keyword rankings, SERP features - Umami: Page views, unique visitors ``` ### **Workflow 2: Find Quick Wins** ```python Input: Project context Process: 1. Fetch GSC keyword data 2. Filter keywords ranking 11-20 3. Sort by search volume 4. Return top opportunities Output: - List of keywords with current position, search volume, URL - Priority score (based on traffic potential) ``` ### **Workflow 3: Competitor Analysis** ```python Input: Your domain + competitor domain + keywords Process: 1. Fetch DataForSEO SERP data 2. Compare rankings 3. Identify gaps (they rank, you don't) 4. Calculate difficulty Output: - Competitor ranking keywords - Gap opportunities - Difficulty scores ``` --- ## 🔧 Technical Implementation ### **Service Manager Pattern:** ```python class DataServiceManager: """Manage optional analytics connections""" def __init__(self, context_path: str): self.config = self._load_config(context_path) self.services = {} # Initialize only configured services if self.config.get('ga4', {}).get('enabled'): from ga4_connector import GA4Connector self.services['ga4'] = GA4Connector( self.config['ga4']['property_id'], self.config['ga4']['credentials_path'] ) if self.config.get('gsc', {}).get('enabled'): from gsc_connector import GSCConnector self.services['gsc'] = GSCConnector( self.config['gsc']['site_url'], self.config['gsc']['credentials_path'] ) if self.config.get('dataforseo', {}).get('enabled'): from dataforseo_client import DataForSEOClient self.services['dataforseo'] = DataForSEOClient( self.config['dataforseo']['login'], self.config['dataforseo']['password'] ) if self.config.get('umami', {}).get('enabled'): from umami_connector import UmamiConnector self.services['umami'] = UmamiConnector( self.config['umami']['api_url'], self.config['umami']['api_key'] ) def get_page_performance(self, url: str, days: int = 30) -> Dict: """Aggregate data from all available services""" results = {} for name, service in self.services.items(): try: results[name] = service.get_page_data(url, days) except Exception as e: # Skip failed services silently print(f"Warning: {name} failed: {e}") results[name] = {'error': str(e)} return results def get_quick_wins(self, min_position: int = 11, max_position: int = 20) -> List[Dict]: """Find keywords ranking 11-20 (page 2, ready to push to page 1)""" if 'gsc' not in self.services: return [] try: return self.services['gsc'].get_quick_wins(min_position, max_position) except Exception as e: print(f"Warning: GSC quick wins failed: {e}") return [] ``` --- ## 📁 Commands ### **Get Page Performance:** ```bash python3 skills/seo-data/scripts/data_aggregator.py \ --url "https://yoursite.com/blog/article" \ --context "./website/context/" \ --days 30 ``` ### **Find Quick Wins:** ```bash python3 skills/seo-data/scripts/gsc_connector.py \ --context "./website/context/" \ --action quick-wins \ --min-position 11 \ --max-position 20 ``` ### **Competitor Analysis:** ```bash python3 skills/seo-data/scripts/dataforseo_client.py \ --context "./website/context/" \ --action competitor-gap \ --your-domain "yoursite.com" \ --competitor "competitor.com" \ --keywords "keyword1,keyword2" ``` --- ## ⚙️ Environment Variables **Optional (in unified .env or project .env):** ```bash # Google Analytics 4 GA4_PROPERTY_ID=G-XXXXXXXXXX GA4_CREDENTIALS_PATH=path/to/ga4-credentials.json # Google Search Console GSC_SITE_URL=https://yoursite.com GSC_CREDENTIALS_PATH=path/to/gsc-credentials.json # DataForSEO DATAFORSEO_LOGIN=your_login DATAFORSEO_PASSWORD=your_password DATAFORSEO_BASE_URL=https://api.dataforseo.com # Umami Analytics UMAMI_API_URL=https://analytics.yoursite.com UMAMI_API_KEY=your_api_key ``` --- ## 📊 Output Examples ### **Page Performance Output:** ```json { "url": "https://yoursite.com/blog/podcast-hosting", "period": "last_30_days", "ga4": { "pageviews": 12500, "sessions": 9800, "avg_engagement_time": 245, "bounce_rate": 0.42, "conversions": 125 }, "gsc": { "impressions": 45000, "clicks": 3200, "avg_position": 8.5, "ctr": 0.071, "top_keywords": [ {"keyword": "podcast hosting", "position": 8, "clicks": 1200}, {"keyword": "best podcast platform", "position": 12, "clicks": 800} ] }, "dataforseo": { "rankings": [ {"keyword": "podcast hosting", "position": 8, "search_volume": 2900}, {"keyword": "podcast platform", "position": 15, "search_volume": 1500} ] }, "umami": { "pageviews": 11800, "unique_visitors": 8500, "bounce_rate": 0.38 } } ``` ### **Quick Wins Output:** ```json { "quick_wins": [ { "keyword": "podcast hosting comparison", "current_position": 12, "search_volume": 1200, "clicks": 45, "impressions": 2500, "ctr": 0.018, "url": "/blog/podcast-hosting-comparison", "priority_score": 85, "recommendation": "Add more comparison data, update for 2026" } ], "total_opportunities": 15, "estimated_traffic_gain": "+2500 visits/month if all reach top 10" } ``` --- ## ⚠️ Important Notes 1. **All Services Optional:** Skill works even with zero services configured 2. **Silent Failures:** Failed services are skipped, not blocking 3. **Per-Project Config:** Each website has its own data-services.json 4. **Caching:** API responses cached for 24 hours to reduce costs 5. **Rate Limits:** Respects API rate limits, queues requests if needed --- ## 🔌 Service Setup Guides ### **Google Analytics 4:** 1. Go to Google Cloud Console 2. Create service account 3. Download JSON credentials 4. Add service account to GA4 property (Viewer role) 5. Update context/data-services.json ### **Google Search Console:** 1. Same service account as GA4 (or create new) 2. Add to Search Console property (Owner or Full access) 3. Update context/data-services.json ### **DataForSEO:** 1. Sign up at dataforseo.com 2. Get API login and password 3. Add to context/data-services.json 4. Set budget limits ### **Umami:** 1. Self-host Umami or use cloud 2. Create website in Umami 3. Generate API key 4. Update context/data-services.json --- ## 🔄 Integration with Other Skills - **seo-multi-channel:** Fetches performance data to inform content strategy - **seo-analyzers:** Uses GSC data for keyword optimization scoring - **seo-context:** Reads data-services.json from context folder --- **Use this skill when you need performance data from analytics services to inform content decisions or track results.** **All services are optional - the skill gracefully skips unconfigured services.**