()
| 40 | |
| 41 | |
| 42 | def main(): |
| 43 | print("=" * 80) |
| 44 | print("COMPETITOR CONTENT GAP ANALYSIS") |
| 45 | print("=" * 80) |
| 46 | print(f"Date: {datetime.now().strftime('%Y-%m-%d %H:%M')}") |
| 47 | print(f"Strategy: Find keywords competitors rank for that we don't") |
| 48 | print("=" * 80) |
| 49 | |
| 50 | # Initialize clients |
| 51 | print("\n1. Initializing data sources...") |
| 52 | try: |
| 53 | gsc = GoogleSearchConsole() |
| 54 | print(" ✓ Google Search Console connected") |
| 55 | except Exception as e: |
| 56 | print(f" ✗ GSC Error: {e}") |
| 57 | return |
| 58 | |
| 59 | try: |
| 60 | dfs = DataForSEO() |
| 61 | print(" ✓ DataForSEO connected") |
| 62 | except Exception as e: |
| 63 | print(f" ✗ DataForSEO Error: {e}") |
| 64 | print(" DataForSEO is required for competitor analysis") |
| 65 | return |
| 66 | |
| 67 | # Initialize scoring modules |
| 68 | scorer = OpportunityScorer() |
| 69 | intent_analyzer = SearchIntentAnalyzer() |
| 70 | print(" ✓ Analysis modules loaded") |
| 71 | |
| 72 | # Get our current ranking keywords |
| 73 | print("\n2. Fetching your current rankings from GSC...") |
| 74 | our_keywords = gsc.get_keyword_positions(days=90) |
| 75 | # Filter by minimum impressions |
| 76 | our_keywords = [kw for kw in our_keywords if kw.get('impressions', 0) >= 10] |
| 77 | our_keyword_set = {kw['keyword'].lower().strip() for kw in our_keywords} |
| 78 | print(f" ✓ Found {len(our_keyword_set)} keywords you're ranking for") |
| 79 | |
| 80 | # Analyze competitors |
| 81 | all_competitors = DIRECT_COMPETITORS + CONTENT_COMPETITORS |
| 82 | print(f"\n3. Analyzing {len(all_competitors)} competitors...") |
| 83 | |
| 84 | competitor_gaps = [] |
| 85 | seen_keywords = set() # To deduplicate |
| 86 | |
| 87 | for i, competitor in enumerate(all_competitors, 1): |
| 88 | comp_type = "Direct" if competitor in DIRECT_COMPETITORS else "Content" |
| 89 | print(f"\n [{i}/{len(all_competitors)}] Analyzing {competitor} ({comp_type})...") |
| 90 | |
| 91 | try: |
| 92 | # Get competitor's top ranking keywords |
| 93 | comp_keywords = dfs.get_domain_keywords( |
| 94 | domain=competitor, |
| 95 | position_max=20, # Top 20 only |
| 96 | limit=300 # Reasonable limit to manage API costs |
| 97 | ) |
| 98 | |
| 99 | if not comp_keywords: |
no test coverage detected