# How OpenSEO Integrates with the DataForSEO Backlinks API for Backlink Analysis

> Discover how OpenSEO integrates with the DataForSEO Backlinks API for seamless backlink analysis. Learn about request validation, caching, billing, and data transformation.

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

---

**OpenSEO integrates with the DataForSEO Backlinks API through a thin server-side service layer that validates requests, manages R2 caching, handles billing context, and transforms raw API responses into normalized UI-ready data.**

The `every-app/open-seo` repository implements a robust **DataForSEO Backlinks API integration** that abstracts complex third-party data fetching into clean, cached server functions. This architecture ensures efficient API usage while providing the frontend with simple, type-safe endpoints for backlink analysis.

## Server-Side Endpoint Architecture

OpenSEO exposes backlink data through TanStack `createServerFn` endpoints defined in [`src/serverFunctions/backlinks.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/backlinks.ts). These server functions act as the entry point for all backlink-related queries, handling four primary operations:

- **Overview**: Domain or page-level backlink summaries
- **Rows**: Individual backlink records with pagination
- **Referring Domains**: Unique domain sources
- **Top Pages**: Most linked-to pages on a domain

Each endpoint validates incoming requests using Zod schemas such as `backlinksOverviewInputSchema` and `backlinksRowsPageRequestSchema`. After validation, the functions inject project context via `requireProjectContext` to ensure proper organization scoping and billing attribution before forwarding requests to the service layer.

## The BacklinksService Layer

The [`BacklinksService.ts`](https://github.com/every-app/open-seo/blob/main/BacklinksService.ts) file implements a façade pattern that orchestrates caching and data retrieval. This service constructs deterministic cache keys using `buildCacheKey`, incorporating:

- Organization ID
- Target domain or URL
- Pagination parameters
- Spam filter options

When a cache miss occurs in the R2 cache (accessed via `getCached` and `setCached`), the service delegates to the data layer in [`backlinksServiceData.ts`](https://github.com/every-app/open-seo/blob/main/backlinksServiceData.ts). Successful responses are stored with a **6-hour TTL** to minimize expensive API calls, ensuring subsequent identical requests return instantly from cache.

## DataForSEO API Integration

The actual DataForSEO Backlinks API integration resides in [`backlinksServiceData.ts`](https://github.com/every-app/open-seo/blob/main/backlinksServiceData.ts). This layer creates an authenticated client using `createDataforseoClient(billingCustomer)`, which injects the user's API credentials and billing context.

The service maps OpenSEO requests to specific DataForSEO endpoints:

- **Overview**: `dataforseo.backlinks.summary`
- **Rows**: `dataforseo.backlinks.rows`
- **Referring Domains**: `dataforseo.backlinks.referringDomains`
- **Top Pages**: `dataforseo.backlinks.domainPages`

Each method—`profileBacklinksOverview`, `profileBacklinksRows`, `profileBacklinksReferringDomains`, and `profileBacklinksTopPages`—handles the HTTP communication, error handling, and initial response validation before passing results to the mapping layer.

## Data Transformation and Spam Filtering

Raw DataForSEO responses undergo normalization through dedicated mapping functions. The service applies `mapBacklinksRows`, `mapReferringDomainsRows`, or `mapTopPagesRows` to convert API-specific field names into the standardized shapes expected by the OpenSEO frontend, injecting `null` defaults for missing values.

Spam filtering behavior is controlled through `BacklinksSpamFilterOptions`. For web UI requests, the constant `WEB_SPAM_OPTIONS = { hideSpam: false }` forces DataForSEO to **return all links regardless of spam score**, delegating filtering to the client side. Other API consumers can pass custom spam filter parameters to pre-filter results at the DataForSEO level.

## Implementation Examples

### Fetching Backlink Overview Data

```typescript
import { getBacklinksOverview } from "@/serverFunctions/backlinks";

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

```

### Retrieving Paginated Backlink Rows

```typescript
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: {},
    mode: "default",
  });
  return data; // { rows: [...], hasMore, totalCount, fetchedAt }
}

```

### Direct Service Usage for Custom Tools

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

async function customOverview(domain: string) {
  const billing = await createBillingContext();
  const result = await BacklinksService.profileOverview(
    { target: domain, scope: "domain" },
    billing,
  );
  console.log(result.overview);
}

```

## Summary

- OpenSEO uses **TanStack server functions** in [`src/serverFunctions/backlinks.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/backlinks.ts) to expose type-safe endpoints for backlink data retrieval.
- The **BacklinksService** implements intelligent R2 caching with deterministic keys to reduce DataForSEO API costs and improve response times.
- **DataForSEO client creation** handles authentication and billing context automatically, ensuring proper API key usage per organization.
- **Result mapping functions** normalize raw API responses into consistent frontend-facing data structures.
- **Spam filter options** can be configured per request, with web UI defaults set to retrieve all links for client-side filtering.

## Frequently Asked Questions

### How does OpenSEO handle caching for DataForSEO backlink data?

OpenSEO implements a two-layer caching strategy using Cloudflare R2 via [`src/server/lib/r2-cache.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/r2-cache.ts). The `BacklinksService` generates deterministic cache keys that include the organization ID, target URL, pagination state, and spam filter settings. All backlink overview and tabular data is cached for **6 hours**, ensuring that repeated queries for the same domain hit the cache rather than incurring additional DataForSEO API charges.

### What specific DataForSEO endpoints does OpenSEO use?

According to the source code in [`backlinksServiceData.ts`](https://github.com/every-app/open-seo/blob/main/backlinksServiceData.ts), OpenSEO integrates with four primary DataForSEO Backlinks API endpoints: `dataforseo.backlinks.summary` for overview metrics, `dataforseo.backlinks.rows` for individual link data, `dataforseo.backlinks.referringDomains` for domain-level aggregation, and `dataforseo.backlinks.domainPages` for identifying top-performing pages. Each endpoint is wrapped in a dedicated service method that handles pagination and response mapping.

### How does OpenSEO manage API authentication and billing with DataForSEO?

Authentication flows through the `createDataforseoClient` function, which accepts a `billingCustomer` context resolved via `requireProjectContext`. This pattern ensures that each API request carries the correct organization-specific API key and tracks usage against the proper billing entity. The integration isolates third-party API costs per project, preventing cross-contamination of API quotas between organizations.

### Can spam filtering be customized when fetching backlink data?

Yes, OpenSEO supports custom spam filtering through the `BacklinksSpamFilterOptions` interface. While the web UI defaults to `WEB_SPAM_OPTIONS = { hideSpam: false }` to retrieve complete datasets for client-side analysis, API consumers can pass custom filter objects to the server functions. When specified, these options are incorporated into the cache key and forwarded to DataForSEO, allowing the external API to pre-filter results based on spam scores before transmission.