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

> Discover how OpenSEO performs competitor analysis using SERP data by integrating with DataForSEO API. Learn about its modular architecture for filtering, sorting, and formatting results.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: deep-dive
- Published: 2026-08-19

---

**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`](https://github.com/every-app/open-seo/blob/main/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`](https://github.com/every-app/open-seo/blob/main/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`](https://github.com/every-app/open-seo/blob/main/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`](https://github.com/every-app/open-seo/blob/main/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`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/table.ts) renders the processed competitors as markdown tables for human readability. The **`mcpResponse`** utility in [`src/server/mcp/formatters.ts`](https://github.com/every-app/open-seo/blob/main/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:

- **[`src/server/mcp/tools/dataforseo-research-tools.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/dataforseo-research-tools.ts)** – Core implementation containing `findSerpCompetitorsTool`, market resolution logic, domain filtering, and the sorting pipeline.

- **[`src/server/mcp/tools/local-seo-shared.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/local-seo-shared.ts)** – Reusable utilities including `hostMatchesDomain` and `resolveBusinessIdentifier` for domain comparison and business entity resolution.

- **[`src/server/mcp/tools/output-schemas.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/output-schemas.ts)** – Defines `looseObjectOutputSchema` for type-safe output validation, ensuring consistent data contracts without leaking internal provider fields.

- **[`src/server/mcp/table.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/table.ts)** – Provides `formatMcpTable` for converting competitor arrays into readable markdown tables.

- **[`src/server/lib/dataforseo/index.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/dataforseo/index.ts)** – Factory for the DataForSEO client with billing context integration.

- **[`src/server/mcp/formatters.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/formatters.ts)** – Wraps tool outputs into standardized MCP responses with meta links and structured content arrays.

## Practical Implementation: Code Examples

### Direct MCP Tool Invocation

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

```typescript
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:

```json
{
  "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:

```typescript
// 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`](https://github.com/every-app/open-seo/blob/main/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`.