How OpenSEO Backlink Analysis Endpoints Work with DataForSEO: A Complete Technical Guide

OpenSEO's backlink analysis endpoints are thin server-side wrappers around DataForSEO's REST API that add input validation, R2 caching, spam-filter handling, and billing integration while delegating all data retrieval to the external provider.

OpenSEO provides a suite of backlink analysis features—overview metrics, detailed row data, referring domains, and top pages—that rely entirely on DataForSEO as the underlying data source. Rather than storing backlink data itself, the application implements a sophisticated service layer that optimizes API usage through intelligent caching and request normalization.

Architecture Overview: From UI to DataForSEO

The backlink analysis flow follows a clear 10-step pipeline that keeps the frontend simple while maximizing performance and cost efficiency.

Step 1: Request Entry via TanStack Server Functions

Frontend requests enter through TanStack createServerFn endpoints defined in src/serverFunctions/backlinks.ts. Four main endpoints are exposed:

  • getBacklinksOverview — summary metrics and historical data
  • getBacklinksRows — paginated backlink details
  • getBacklinksReferringDomains — aggregated domain-level view
  • getBacklinksTopPages — most-linked pages for a target
// Calling the overview endpoint from the frontend
import { getBacklinksOverview } from "@/serverFunctions/backlinks";

async function loadOverview(target: string, scope: "domain" | "page") {
  const { data } = await getBacklinksOverview({
    target,
    scope,
  });
  return data; // { rank, backlinks, referringDomains, ... }
}

Step 2: Validation and Project Context

Each endpoint validates incoming requests against Zod schemas (backlinksOverviewInputSchema, backlinksRowsPageRequestSchema, etc.) and injects project context via requireProjectContext. This ensures type safety and attaches organization and billing information (lines 15-35 in src/serverFunctions/backlinks.ts).

Step 3: Service Layer Abstraction

Validated payloads are forwarded to BacklinksService, a façade located in src/server/features/backlinks/services/BacklinksService.ts. This service knows how to:

  • Build deterministic cache keys
  • Interface with the DataForSEO client
  • Handle pagination parameters

Caching Strategy and Cache Key Construction

Deterministic caching is critical for controlling DataForSEO API costs. In BacklinksService.ts (lines 48-51, 65-71), cache keys incorporate:

  • Organization ID
  • Target domain/page
  • Pagination details (page, pageSize, sortField, sortOrder)
  • Spam-filter options
// Cache key example structure
`backlinks:overview:${orgId}:${target}:${scope}:${spamFilterHash}`

The service uses R2 cache via getCached and setCached utilities. Cache hits return instantly; misses trigger DataForSEO API calls.

DataForSEO Client Initialization and API Calls

When cache misses occur, the service creates an authenticated DataForSEO client through createDataforseoClient(billingCustomer), which embeds the user's API key and billing context (see backlinksServiceData.ts lines 89-91).

The service maps each backlink analysis type to its corresponding DataForSEO endpoint:

OpenSEO Feature DataForSEO Endpoint Lines in backlinksServiceData.ts
Overview dataforseo.backlinks.summary 97-102
Rows dataforseo.backlinks.rows 145-152
Referring Domains dataforseo.backlinks.referringDomains 182-190
Top Pages dataforseo.backlinks.domainPages 213-221

Spam Filter Handling in OpenSEO

OpenSEO provides flexible spam-filter control depending on the caller:

  • Web UI requests: Use WEB_SPAM_OPTIONS = { hideSpam: false } (lines 11-14 in src/serverFunctions/backlinks.ts), forcing DataForSEO to return all links and letting the client apply filtering
  • API/tool callers: Can pass custom BacklinksSpamFilterOptions for server-side filtering

This design allows the web interface to show spam indicators without missing data, while automated tools can request pre-filtered results.

Result Mapping and Normalization

Raw DataForSEO JSON is transformed into frontend-compatible shapes through dedicated mapping functions in backlinksServiceData.ts:

  • mapBacklinksRows (lines 43-62)
  • mapReferringDomainsRows (lines 64-74)
  • mapTopPagesRows (lines 76-85)

These functions normalize field names, inject defaults (null for missing values), and ensure consistent typing across the application.

The rows endpoint supports sophisticated pagination and sorting:

import { getBacklinksRows } from "@/serverFunctions/backlinks";

async function loadRowsPage(
  target: string,
  page = 1,
  pageSize = 15,
  sortField = "domainFrom",
  sortOrder = "desc",
) {
  const { data } = await getBacklinksRows({
    target,
    scope: "domain",
    page,
    pageSize,
    sortField,
    sortOrder,
    filters: {},          // optional filter map
    mode: "default",      // optional grouping mode
  });
  return data; // { rows: [...], hasMore, totalCount, fetchedAt }
}

Cache Persistence and TTL

Transformed results are stored with 6-hour TTL for overview and tab data (lines 117-124, 159-162, 194-197, 228-232 in backlinksServiceData.ts). This balances data freshness with API cost control.

Direct Service Usage for Custom Tools

For server-side scripts or internal tools, you can bypass the HTTP layer and use BacklinksService directly:

import { BacklinksService } from "@/server/features/backlinks/services/BacklinksService";
import { createBillingContext } from "@/server/billing/subscription";

async function customOverview(domain: string) {
  const billing = await createBillingContext(); // resolves org-id & API key
  const result = await BacklinksService.profileOverview(
    { target: domain, scope: "domain" },
    billing,
  );
  console.log(result.overview);
}

Key Implementation Files

File Purpose
src/serverFunctions/backlinks.ts TanStack server function definitions
src/server/features/backlinks/services/BacklinksService.ts Service factory and cache key builder
src/server/features/backlinks/services/backlinksServiceData.ts DataForSEO API calls, caching, pagination, mapping
src/server/lib/dataforseo/client.ts Low-level authenticated HTTP client
src/types/schemas/backlinks.ts Zod validation schemas
src/server/lib/r2-cache.ts R2 caching utilities

Summary

OpenSEO's DataForSEO backlink integration follows a clean architectural pattern:

  • Thin endpoints in src/serverFunctions/backlinks.ts handle HTTP concerns
  • Zod validation ensures type safety at the boundary
  • BacklinksService abstracts caching and DataForSEO coordination
  • Deterministic R2 caching with 6-hour TTL minimizes API costs
  • Flexible spam filtering supports both UI and programmatic use cases
  • Consistent result mapping isolates frontend from external API changes

This design lets OpenSEO offer rich backlink analysis without maintaining its own backlink index, while ensuring responsive, cost-effective delivery through aggressive caching.

Frequently Asked Questions

How does OpenSEO handle DataForSEO API rate limits?

OpenSEO primarily manages rate limits through aggressive caching rather than explicit throttling. The R2 cache layer absorbs identical requests within the 6-hour TTL window, preventing duplicate API calls. For high-volume scenarios, the billing context in createDataforseoClient may enforce organization-level quotas, though specific rate-limit headers from DataForSEO are not shown in the source.

The current implementation uses hardcoded 6-hour TTL values in backlinksServiceData.ts. To modify this, you would need to fork and adjust the cacheValue calls at lines 117-124, 159-162, 194-197, and 228-232. There is no configuration-based cache control exposed in the public API.

What happens when DataForSEO returns an error?

The source code shows that API calls are wrapped in the service layer, though explicit error handling patterns are not detailed in the analyzed files. Typically, DataForSEO client errors would propagate up from createDataforseoClient and be caught by TanStack's server function error handling, returning appropriate HTTP status codes to the frontend.

Is workspace-level or project-level isolation enforced for cached data?

Yes—cache keys explicitly include the organization ID (orgId) as part of the buildCacheKey logic in BacklinksService.ts. This ensures that cached backlink data for one customer cannot be served to another, even when querying identical targets.

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 →