How OpportunityScorer Calculates 8-Factor Weighted Scoring for SEO Opportunities

OpportunityScorer calculates SEO opportunity scores by normalizing eight distinct metrics—Search Volume, Current Position, Search Intent, Competition, Cluster Relevance, CTR, Freshness, and Trend—then applying specific weights ranging from 5% to 25% to generate a composite 0-100 score for prioritization.

TheCraigHewitt/seomachine is an open-source SEO analysis platform that uses data-driven algorithms to identify high-value content opportunities. At the core of its prioritization engine lies the 8-factor weighted scoring algorithm implemented in the OpportunityScorer class, which transforms raw search metrics into actionable priority scores.

The 8-Factor Weighted Scoring Methodology

The scoring system implemented in data_sources/modules/opportunity_scorer.py follows a four-step pipeline: raw metric collection, normalization, weight application, and aggregation.

Step 1: Raw Metric Collection

For each keyword or page under evaluation, the system gathers raw data across eight distinct factors:

  • Search Volume (25% weight) – Average monthly search queries for the target keyword.
  • Current Position (20% weight) – Existing SERP ranking of the target URL.
  • Search Intent (20% weight) – Classification as commercial, informational, transactional, or navigational.
  • Competition (15% weight) – SEO difficulty score or density of competing pages.
  • Cluster Relevance (10% weight) – Alignment with existing topic clusters in the content architecture.
  • Click-Through Rate (CTR) (5% weight) – Expected CTR based on current position.
  • Freshness (5% weight) – Recency of top-ranking content in days.
  • Trend (5% weight) – Momentum of search interest over recent weeks or months.

Step 2: Normalization Process

Raw values cannot be combined directly due to differing scales and units. The OpportunityScorer transforms each metric to a 0-1 normalized scale using factor-specific methods:

  • Log-scaling for high-variance metrics like Search Volume.
  • Inverse scaling for competitive factors where lower values indicate better opportunity (e.g., Competition).
  • Linear scaling for bounded metrics like Current Position (where position 1 is best) and Cluster Relevance.

Step 3: Weight Application and Aggregation

After normalization, each factor is multiplied by its predefined weight. The weighted values are summed to produce a final opportunity score ranging from 0 to 100.

The calculation follows this formula:


Score = (
    Volume_norm × 0.25 +
    Position_norm × 0.20 +
    Intent_norm × 0.20 +
    Competition_norm × 0.15 +
    Cluster_norm × 0.10 +
    CTR_norm × 0.05 +
    Freshness_norm × 0.05 +
    Trend_norm × 0.05
) × 100

Implementation in opportunity_scorer.py

The core logic resides in data_sources/modules/opportunity_scorer.py, where the OpportunityScorer class encapsulates the normalization and weighting pipeline. The calculate() method orchestrates the transformation of raw metrics into the final priority score.


# Example: Using the Opportunity Scorer

from data_sources.modules.opportunity_scorer import OpportunityScorer

# Raw metrics collected from the various data sources

metrics = {
    "volume": 12000,          # monthly searches

    "position": 12,           # current SERP rank

    "intent": "commercial",   # classified intent

    "competition": 0.35,      # difficulty score (0-1)

    "cluster_score": 0.8,     # relevance to existing cluster

    "ctr": 0.12,              # expected click-through rate

    "freshness": 30,          # days since newest top result

    "trend": 1.15             # 15% upward trend

}

scorer = OpportunityScorer()
opportunity_score = scorer.calculate(metrics)

print(f"Opportunity score: {opportunity_score:.2f}")

The calculate method internally normalizes each metric, applies the weights listed above, and returns the aggregated score.

Supporting Data Sources

The OpportunityScorer depends on specialized modules to supply raw metrics:

These modules work together to ensure the scorer receives normalized, accurate inputs for the 8-factor calculation.

Summary

  • OpportunityScorer implements an 8-factor weighted algorithm in data_sources/modules/opportunity_scorer.py to prioritize SEO opportunities.
  • The eight factors are Search Volume (25%), Current Position (20%), Search Intent (20%), Competition (15%), Cluster Relevance (10%), CTR (5%), Freshness (5%), and Trend (5%).
  • Raw metrics undergo normalization (log-scaling, inverse scaling, or linear scaling) before weights are applied.
  • The final score ranges from 0 to 100, enabling data-driven prioritization of high-ROI content opportunities.

Frequently Asked Questions

What are the 8 factors used in OpportunityScorer?

The eight factors are Search Volume, Current Position, Search Intent, Competition, Cluster Relevance, Click-Through Rate (CTR), Freshness, and Trend. Each factor contributes a specific percentage to the final score, with Volume carrying the highest weight at 25% and CTR, Freshness, and Trend each contributing 5%.

How does OpportunityScorer normalize metrics?

The scorer uses factor-specific normalization methods to transform raw values onto a 0-1 scale. It applies log-scaling for high-variance metrics like Search Volume, inverse scaling for competitive factors where lower values are better (such as Competition), and linear scaling for bounded metrics like Current Position and Cluster Relevance.

Where is the scoring logic implemented in the codebase?

The core scoring logic resides in data_sources/modules/opportunity_scorer.py, specifically within the OpportunityScorer class and its calculate() method. This module orchestrates the normalization pipeline and applies the weighted aggregation formula to produce the final 0-100 opportunity score.

How can I customize the weights in OpportunityScorer?

To modify the default weights, you would edit the weight constants defined in data_sources/modules/opportunity_scorer.py before the calculation step. The current implementation uses fixed percentages (Volume 25%, Position 20%, Intent 20%, Competition 15%, Cluster 10%, and 5% each for CTR, Freshness, and Trend), but you can adjust these values to align with your specific SEO strategy or market conditions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →