How OpenSEO Handles Backlink Data Retrieval and Presentation
OpenSEO retrieves backlink data through a layered architecture that validates requests with Zod schemas, fetches from the Data-for-SEO API via a dedicated service layer with caching, and presents filtered results through both a React-based UI and an MCP tool for AI agents.
OpenSEO, an open-source SEO platform maintained in the every-app/open-seo repository, implements a robust pipeline for backlink analysis. The system separates concerns across multiple layers—from API validation to business logic—ensuring type-safe backlink data retrieval and flexible presentation. Understanding how OpenSEO handles backlink data retrieval and presentation reveals a pattern that balances external API dependencies with efficient caching and multi-interface support.
Architecture Overview
OpenSEO organizes its backlink functionality into five distinct layers:
| Layer | Responsibility | Key File |
|---|---|---|
| API Layer | Validates input and exposes server-side entry points | src/serverFunctions/backlinks.ts |
| Business Layer | Communicates with Data-for-SEO API, handles caching and pagination | src/server/features/backlinks/services/BacklinksService.ts |
| Schema Layer | Defines Zod schemas for request validation and response shaping | src/types/schemas/backlinks.ts |
| MCP Layer | Provides AI-agent tools for programmatic access | src/server/mcp/tools/get-backlinks-overview.ts |
| UI Layer | Renders tables, filters, and export functionality | web/src/lib/feature-pages.ts |
This separation ensures that the core backlink retrieval logic remains isolated from presentation concerns, allowing the same service to power both the web interface and AI integrations.
The Retrieval Flow
The backlink data retrieval process follows a strict validation pipeline before reaching external APIs.
Request Validation
Every incoming request first passes through Zod schema validation. In src/serverFunctions/backlinks.ts, the server functions use backlinksOverviewInputSchema and backlinksRowsPageRequestSchema to validate parameters:
// src/serverFunctions/backlinks.ts
import { BacklinksService } from "@/server/features/backlinks/services/BacklinksService";
import { backlinksRowsPageRequestSchema } from "@/types/schemas/backlinks";
export const getBacklinks = createServerFunction()
.inputValidator((data) => backlinksRowsPageRequestSchema.parse(data))
.handler(async (req, ctx) => {
// req contains: target, tab, page, pageSize, sortField, sortOrder, filters, mode
return BacklinksService.profileBacklinksPage(req, ctx, /* options */);
});
The validation wrapper ensures that all inputs conform to the expected shape before processing continues.
Service Layer Execution
Once validated, requests forward to BacklinksService, which orchestrates four main operations:
profileOverview: Gathers summary statistics (total backlinks, referring domains, top pages)profileBacklinksPage: Retrieves paginated backlink rowsprofileReferringDomainsPage: Fetches domain-level aggregatesprofileTopPagesPage: Returns the most linked-to pages
The service maintains a default cache in backlinksServiceData.ts to minimize external API calls and respects pagination parameters (page, pageSize) to handle large datasets efficiently.
External API Communication
BacklinksService communicates directly with the Data-for-SEO API. The service implements caching layers to store results and reduce latency for repeated queries. All pagination, filtering, and sorting logic occurs after retrieval but before the response returns to the client.
Data Processing and Filtering
After retrieving raw data from the external API, OpenSEO applies business logic to refine results.
Filtering Logic
The system supports complex filtering through backlinksApiFilters.ts, which processes boolean flags for:
- Spam: Identifies low-quality links
- Broken: Detects non-responsive backlinks
- Lost: Flags removed backlinks
- Nofollow: Identifies non-passing links
Sorting Capabilities
Results sort according to backlinksRowsSortFieldSchema, supporting fields like rank DESC to prioritize high-authority domains. The service constructs the final payload to match the Zod output schema defined in src/types/schemas/backlinks.ts, ensuring type consistency between server and client.
Presentation Layer
The backlink data presentation layer transforms JSON payloads into interactive tables. The Backlink Checker page, registered in web/src/routeTree.gen.ts and configured in web/src/lib/feature-pages.ts (lines 184-214), renders:
| Column | Data Source |
|---|---|
| Backlink | URL of the linking page |
| Rank | Domain authority estimate |
| Signal Flags | Boolean values for spam, broken, lost, nofollow |
| Referring Domain | Grouped view when mode = "one_per_domain" |
UI Features
The interface includes pagination controls driven by the page and pageSize values returned by the service. Users can toggle dynamic filters through checkboxes that modify the backlinksRowsFiltersSchema values, triggering instant re-requests. An export function serializes current rows—including all filter flags—to CSV format for offline analysis.
// Front-end usage (React hook)
import { useQuery } from "@tanstack/react-query";
function useBacklinkRows(domain: string, page = 1) {
return useQuery(
["backlinks", domain, page],
async () => {
const res = await fetch(`/api/backlinks/rows?target=${domain}&page=${page}`);
if (!res.ok) throw new Error("Failed to load backlinks");
return res.json(); // matches the Zod output schema
},
{ keepPreviousData: true }
);
}
MCP Integration for AI Agents
OpenSEO exposes backlink functionality to AI agents through the Model Context Protocol (MCP). The tool defined in src/server/mcp/tools/get-backlinks-overview.ts provides a concise interface:
// src/server/mcp/tools/get-backlinks-overview.ts
import { BacklinksService } from "@/server/features/backlinks/services/BacklinksService";
export async function get_backlinks_overview(input: { target: string }) {
// Returns: { backlinks: number | null, referringDomains: number | null, topPages: number | null }
return BacklinksService.profileOverview(input, { billing: /* current user billing */ });
}
This allows AI agents to fetch backlink overviews without rendering the full UI, returning only essential metrics for automated analysis.
Summary
- OpenSEO implements a five-layer architecture separating validation, business logic, and presentation concerns for backlink data.
- The
BacklinksServiceinsrc/server/features/backlinks/services/BacklinksService.tshandles all Data-for-SEO API communication with built-in caching. - Zod schemas in
src/types/schemas/backlinks.tsenforce type safety across API boundaries. - The system supports multi-modal presentation through both a React-based web interface and an MCP tool for AI agents.
- Advanced filtering (spam, broken, lost, nofollow) and sorting occur at the service layer before data reaches the client.
Frequently Asked Questions
How does OpenSEO validate backlink requests?
OpenSEO uses Zod schemas defined in src/types/schemas/backlinks.ts to validate all incoming requests. The server functions in src/serverFunctions/backlinks.ts wrap validation through an .inputValidator() method that parses inputs against schemas like backlinksRowsPageRequestSchema before passing them to the business layer.
What external API does OpenSEO use for backlink data?
The platform integrates with the Data-for-SEO API through the BacklinksService class. This service handles authentication, request construction, caching of results in backlinksServiceData.ts, and error handling for all external backlink queries.
Can AI agents access OpenSEO backlink data without the web interface?
Yes. OpenSEO exposes a dedicated MCP tool in src/server/mcp/tools/get-backlinks-overview.ts that allows AI agents to call BacklinksService.profileOverview() directly. This returns a concise JSON object containing backlink counts, referring domains, and top pages without requiring HTML rendering.
How does the UI handle large backlink datasets?
The presentation layer implements server-side pagination controlled by page and pageSize parameters. The service returns paginated subsets of data, and the React frontend maintains state through TanStack Query with keepPreviousData enabled to prevent UI flickering during navigation.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →