Overview
The OpportunityScorer class provides a comprehensive scoring system for prioritizing SEO opportunities. It considers 8 weighted factors to calculate opportunity scores and identify the highest-value content optimization tasks.
Installation
from data_sources.modules.opportunity_scorer import OpportunityScorer, OpportunityType
Scoring Methodology
The scorer uses 8 weighted factors:
- Volume Score (25%): Search demand/impressions
- Position Score (20%): Proximity to target position
- Intent Score (20%): Commercial value
- Competition Score (15%): Ranking difficulty
- Cluster Score (10%): Strategic topic value
- CTR Score (5%): Improvement potential
- Freshness Score (5%): Content update requirements
- Trend Score (5%): Rising/declining interest
Opportunity Types
from data_sources.modules.opportunity_scorer import OpportunityType
OpportunityType.QUICK_WIN # Position 11-20, close to page 1
OpportunityType.IMPROVEMENT # Position 1-10, can reach #1-3
OpportunityType.MEDIUM_TERM # Position 21-50, needs significant work
OpportunityType.NEW_CONTENT # Not ranking, competitor gap
OpportunityType.DECLINING # Was good, now dropping
OpportunityType.UNDERPERFORMER # High ranking, low CTR
Initialization
scorer = OpportunityScorer()
Methods
calculate_score
Calculate comprehensive opportunity score.
result = scorer.calculate_score(
keyword_data={
'keyword': 'podcast hosting',
'position': 12.3,
'impressions': 1500,
'clicks': 15,
'ctr': 0.01,
'commercial_intent': 2.5
},
opportunity_type=OpportunityType.QUICK_WIN,
search_volume=2000,
difficulty=45,
serp_features=['featured_snippet', 'people_also_ask'],
cluster_value=75,
trend_direction='rising',
trend_percent=25
)
GSC data with position, impressions, clicks, ctrCommercial intent score (0.1-3.0)
opportunity_type
OpportunityType
default:"QUICK_WIN"
Type of opportunity being scored
Monthly search volume (from DataForSEO)
SEO difficulty 0-100 (from DataForSEO)
Strategic value of topic cluster (0-100)
‘rising’, ‘stable’, or ‘declining’
Percent change in search volume
Final weighted score (0-100)
Individual scores for each factor
CRITICAL, HIGH, MEDIUM, LOW, or SKIP
Primary factor driving the score
Human-readable explanation
calculate_potential_traffic
Calculate potential traffic increase from ranking improvement.
traffic = scorer.calculate_potential_traffic(
current_position=12.3,
target_position=7,
impressions=1500,
current_clicks=15
)
Expected CTR for current position
Expected CTR at target position
Projected clicks at target position
Expected CTR by Position
The scorer uses industry-average CTR by position:
| Position | Expected CTR |
|---|
| 1 | 31.6% |
| 2 | 15.7% |
| 3 | 10.5% |
| 4 | 7.5% |
| 5 | 5.9% |
| 6 | 4.8% |
| 7 | 4.1% |
| 8 | 3.5% |
| 9 | 3.1% |
| 10 | 2.7% |
| 11-20 | 1.8% - 0.7% |
Priority Levels
- CRITICAL: Score >= 80 OR (Quick win + high intent + very close to page 1)
- HIGH: Score >= 65
- MEDIUM: Score >= 45
- LOW: Score >= 25
- SKIP: Score < 25 (not worth pursuing)
Volume Score Tiers
if volume >= 5000: return 100
elif volume >= 2000: return 90
elif volume >= 1000: return 80
elif volume >= 500: return 65
elif volume >= 250: return 50
elif volume >= 100: return 35
elif volume >= 50: return 20
else: return 10
Competition Score (Difficulty Inverted)
if difficulty <= 20: return 100 # Very easy
elif difficulty <= 35: return 85 # Easy
elif difficulty <= 50: return 70 # Moderate
elif difficulty <= 65: return 50 # Difficult
elif difficulty <= 80: return 30 # Very difficult
else: return 10 # Extremely difficult
Example Usage
from data_sources.modules.opportunity_scorer import OpportunityScorer, OpportunityType
scorer = OpportunityScorer()
# Score a quick win opportunity
keyword_data = {
'keyword': 'podcast hosting software',
'position': 12.3,
'impressions': 1500,
'clicks': 15,
'ctr': 0.01,
'commercial_intent': 2.5 # High commercial intent
}
result = scorer.calculate_score(
keyword_data=keyword_data,
opportunity_type=OpportunityType.QUICK_WIN,
search_volume=2000,
difficulty=45,
serp_features=['featured_snippet', 'people_also_ask'],
cluster_value=75,
trend_direction='rising',
trend_percent=25
)
print("Opportunity Score Analysis")
print("=" * 60)
print(f"Keyword: {keyword_data['keyword']}")
print(f"Final Score: {result['final_score']}/100")
print(f"Priority: {result['priority']}")
print(f"Primary Factor: {result['primary_factor']}")
print(f"\nScore Breakdown:")
for factor, score in result['score_breakdown'].items():
print(f" {factor}: {score}/100")
print(f"\nExplanation: {result['score_explanation']}")
# Calculate traffic potential
traffic = scorer.calculate_potential_traffic(
current_position=keyword_data['position'],
target_position=7,
impressions=keyword_data['impressions'],
current_clicks=keyword_data['clicks']
)
print(f"\nTraffic Potential:")
print(f" Current: {traffic['current_clicks']} clicks/month (position {traffic['current_position']})")
print(f" Potential: {traffic['potential_clicks']} clicks/month (position {traffic['target_position']})")
print(f" Gain: +{traffic['additional_clicks']} clicks (+{traffic['percent_increase']}%)")
Example Output
Opportunity Score Analysis
============================================================
Keyword: podcast hosting software
Final Score: 78.5/100
Priority: HIGH
Primary Factor: volume
Score Breakdown:
volume_score: 90.0/100
position_score: 85.0/100
intent_score: 83.3/100
competition_score: 70.0/100
cluster_score: 75.0/100
ctr_score: 85.0/100
freshness_score: 50.0/100
trend_score: 70.0/100
Explanation: Strong volume, position, intent. Weak freshness
Traffic Potential:
Current: 15 clicks/month (position 12.3)
Potential: 62 clicks/month (position 7)
Gain: +47 clicks (+313.3%)
Integration with GSC
Use with Google Search Console data:
from data_sources.modules.google_search_console import GoogleSearchConsole
from data_sources.modules.opportunity_scorer import OpportunityScorer, OpportunityType
gsc = GoogleSearchConsole()
scorer = OpportunityScorer()
# Get quick wins from GSC
quick_wins = gsc.get_quick_wins(days=30)
# Score each opportunity
for kw in quick_wins[:10]:
result = scorer.calculate_score(
keyword_data=kw,
opportunity_type=OpportunityType.QUICK_WIN,
cluster_value=50 # Default cluster value
)
print(f"\n{kw['keyword']}")
print(f" Score: {result['final_score']}/100 ({result['priority']})")
print(f" Position: {kw['position']}")
print(f" Impressions: {kw['impressions']:,}")
Source Code Reference
Location: data_sources/modules/opportunity_scorer.py:23
See also: