How OpenSEO Performs Competitor Analysis Using SERP Data: A Technical Deep Dive

OpenSEO performs competitor analysis using SERP data by integrating with the DataForSEO Labs API to fetch real-time search competitors, then filtering, sorting, and formatting results through a modular MCP (Model Context Protocol) tool architecture.

OpenSEO's competitor analysis feature targets the DataForSEO Labs SERP-competitors endpoint to identify domains competing for target keywords. According to the every-app/open-seo source code, the implementation follows a six-step pipeline that handles market resolution, API communication, domain filtering, and result formatting. This technical architecture ensures type-safe, extensible competitor discovery directly from live search engine results.

How OpenSEO Implements SERP-Based Competitor Analysis

The competitor analysis workflow in src/server/mcp/tools/dataforseo-research-tools.ts processes SERP data through distinct phases, each handled by specialized functions to ensure accuracy and performance.

Market Resolution and Validation

Before querying DataForSEO, OpenSEO normalizes user input through resolveMarketSelector. This function handles legacy market objects alongside modern locationCode and languageCode parameters, ensuring a valid geographic and linguistic context for the SERP query.

Located at lines 24-49 in dataforseo-research-tools.ts, this utility validates the market selector and falls back to the project's default market when necessary. This abstraction isolates market handling complexity, allowing the tool to support various input formats while maintaining forward compatibility with DataForSEO's market system.

API Client Initialization and SERP Query Execution

The system instantiates a DataForSEO client using createDataforseoClient from src/server/lib/dataforseo/index.ts, passing the project's billing context for authentication. The client then invokes client.labs.serpCompetitors with the keyword list, resolved market codes, optional result types (organic, local_pack, etc.), and pagination parameters.

This call occurs within the findSerpCompetitorsTool handler (lines 19-24), which acts as the primary interface between the MCP runtime and the external SEO data provider.

Domain Filtering and Exclusion Logic

Once raw competitor data returns, OpenSEO applies hostMatchesDomain utilities from src/server/mcp/tools/local-seo-shared.ts to implement the excludeDomains parameter. This filtering step compares each returned competitor domain against the exclusion list, removing the user's own site or manually specified competitors from the results.

The filtering logic (lines 28-37) ensures that analysis focuses on true market competitors rather than sister sites, subsidiaries, or the user's own properties.

Result Sorting and Ranking

Raw competitor lists undergo numeric-stable sorting via sortCompetitors, which supports multiple metrics:

  • visibility (descending)
  • traffic_estimate (descending)
  • avg_position (ascending, since lower positions indicate better rankings)
  • keyword_count (descending)

This helper function (lines 46-64) applies the appropriate sort direction based on the sortBy parameter, ensuring results prioritize the most relevant competitive threats.

MCP Response Formatting

Finally, formatMcpTable from src/server/mcp/table.ts renders the processed competitors as markdown tables for human readability. The mcpResponse utility in src/server/mcp/formatters.ts wraps these results with meta links to the project's domain view and a structured competitors array, enabling both human analysis and programmatic consumption.

Key Source Files and Architecture

The SERP competitor analysis depends on a cohesive set of utilities distributed across the codebase:

Practical Implementation: Code Examples

Direct MCP Tool Invocation

For programmatic access within the OpenSEO ecosystem, invoke the tool directly with project context:

import { findSerpCompetitorsTool } from "@/server/mcp/tools/dataforseo-research-tools";
import { withMcpProjectAuth } from "@/server/mcp/project-auth";

const result = await findSerpCompetitorsTool.handler(
  {
    projectId: "proj_123",
    keywords: ["open source seo", "keyword research tool"],
    limit: 20,
    sortBy: "visibility",
    excludeDomains: ["mycompany.com"],
  },
  /* MCP runtime context with billing & project data */
);

console.log(result.text); // Human-readable markdown table
console.log(result.structuredContent.competitors); // Array of competitor objects

Using the SAM Agent Interface

When users query competitors through natural language, the SAM (System Automation Module) agent maps requests to the find_serp_competitors tool:

{
  "name": "find_serp_competitors",
  "arguments": {
    "projectId": "proj_456",
    "keywords": ["cloud backup", "online storage"],
    "sortBy": "traffic_estimate"
  }
}

The agent receives markdown-formatted results and can extract insights such as competitor visibility scores and estimated traffic volumes for further analysis.

Combining with Keyword Gap Analysis

Advanced workflows couple SERP competitor discovery with keyword-level intelligence:

// 1. Identify competitors for target keywords
const competitors = await findSerpCompetitorsTool.handler(
  { projectId, keywords: targetKeywords, sortBy: "visibility" },
  context,
);

// 2. Fetch ranking keywords for each competitor
for (const comp of competitors.structuredContent.competitors) {
  const compKeywords = await getCompetitorKeywordsTool.handler(
    { projectId, domain: comp.domain },
    context,
  );
  // Perform gap analysis against your own keyword portfolio
}

This pattern enables identification of keywords where competitors rank but your domain does not, supporting strategic content prioritization.

Summary

  • OpenSEO leverages the DataForSEO Labs SERP-competitors endpoint to fetch real-time competitor data based on keyword overlap.
  • The findSerpCompetitorsTool in dataforseo-research-tools.ts orchestrates a six-step pipeline: market resolution, client creation, API querying, domain filtering, sorting, and MCP formatting.
  • Type-safe schemas using Zod ensure input validation and consistent output contracts across the MCP interface.
  • Domain exclusion logic via hostMatchesDomain filters out owned properties and specified competitors for accurate market analysis.
  • Results support both human-readable markdown tables and structured JSON arrays for integration with automated analysis workflows.

Frequently Asked Questions

How does OpenSEO handle different geographic markets in competitor analysis?

OpenSEO uses resolveMarketSelector to normalize inputs, supporting legacy market objects and modern locationCode/languageCode pairs. This function validates geographic parameters and falls back to project defaults, ensuring SERP data reflects the correct regional search results regardless of input format.

Can I exclude specific domains from the competitor results?

Yes, the excludeDomains parameter accepts an array of domains to filter out. The system uses hostMatchesDomain utilities to compare returned competitors against this exclusion list, removing matches before sorting and formatting. This is essential for excluding your own properties or sister sites from competitive analysis.

What metrics can I use to sort competitor results?

OpenSEO supports sorting by visibility, traffic_estimate, avg_position, and keyword_count. The sortCompetitors helper applies appropriate sort directions automatically—descending for visibility and traffic metrics, ascending for average position (where lower values indicate better rankings).

How does the MCP tool architecture benefit competitor analysis workflows?

The modular MCP tool definition exposes DataForSEO capabilities as discoverable, typed interfaces with Zod schemas. This architecture enables reuse across UI components, the SAM agent, and API clients while maintaining strict input validation and consistent output formatting through looseObjectOutputSchema.

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 →