# How Backlink Analysis Endpoints Filter and Return Domain Data in Open SEO

> Discover how Open SEO's backlink analysis endpoints filter and return domain data, processing requests via Zod validation and DataForSEO API for cached, normalized results.

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

---

**The Open SEO repository processes backlink analysis requests through a pipeline that validates inputs with Zod schemas, translates user filters into DataForSEO API clauses via BacklinksService, and returns cached, normalized domain records with a six-hour retention policy.**

The Open SEO project provides server-side endpoints for analyzing backlink profiles, specifically handling the filtering and retrieval of referring domain data. Understanding how these backlink analysis endpoints filter and return domain data requires examining the interaction between server functions, service-layer business logic, and external API integration. The architecture emphasizes type safety through schema validation, efficient caching, and precise filter construction to minimize external API costs while delivering accurate SEO metrics.

## Server Function Entry Points and Validation

HTTP POST endpoints in [`src/serverFunctions/backlinks.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/backlinks.ts) serve as the primary interface for backlink analysis requests. The `getBacklinksReferringDomains` function handles requests specifically for the referring-domains tab, validating incoming payloads against the `referringDomainsPageRequestSchema` Zod schema before processing.

This validation layer ensures that parameters such as `target`, `scope`, `filters`, and pagination settings meet strict type requirements. Only after successful validation does the endpoint delegate execution to the service layer, preventing malformed requests from reaching the external DataForSEO API.

## Service Layer Orchestration

The `BacklinksService` class in [`src/server/features/backlinks/services/BacklinksService.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/backlinks/services/BacklinksService.ts) centralizes all backlink data operations. For referring domain requests, the method `profileReferringDomainsPage` manages the complete data retrieval workflow.

This service method first normalizes the target using `normalizeBacklinksTarget` to standardize domain or page formats. It then generates a cache key based on the normalized parameters and checks for existing cached results with a **six-hour TTL** (time-to-live). When cache misses occur, the service instantiates a DataForSEO client and prepares to fetch fresh data.

## Constructing DataForSEO Filters

The filtering logic resides in [`src/server/features/backlinks/services/backlinksApiFilters.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/backlinks/services/backlinksApiFilters.ts), specifically within the `buildReferringDomainsApiFilters` function. This module translates the user-supplied `ReferringDomainsFilters` object into an array of DataForSEO-compatible filter clauses.

The construction process involves several specialized helpers:

- **`collectExcludeConditions`** – Handles exclusion patterns such as domain suffixes or substrings
- **`collectNumericRange`** – Processes minimum and maximum thresholds for metrics like `backlinks`, `referringPages`, and `spamScore`
- **`finishFilters`** – Assembles include/exclude conditions, enforces filter budget constraints, and joins clauses with `AND` operators

These functions support complex filtering scenarios including string pattern matching (e.g., including domains containing "blog" while excluding ".ru" domains), numeric range constraints, and boolean flags like `hideLost`.

## Response Mapping and Caching

After receiving raw data from the DataForSEO API via `dataforseo.backlinks.referringDomains`, the service transforms the response through `mapReferringDomainsRows`. This mapping function trims the API payload to essential fields including `domain`, `backlinks`, `referringPages`, and `spamScore`.

The service then stores the processed result in the cache and returns a standardized paginated payload containing:

- `rows` – The filtered array of domain records
- `totalCount` – The total number of matching records (when available)
- `hasMore` – Boolean indicating additional pages exist
- `page`, `pageSize`, and `fetchedAt` – Metadata for client-side state management

## Practical Implementation Examples

The following example demonstrates requesting filtered referring domains for a specific target:

```typescript
// Request referring domains with complex filters
fetch('/api/backlinks/referring-domains', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    target: 'example.com',
    scope: 'domain',
    page: 1,
    pageSize: 20,
    sortField: 'backlinks',
    sortOrder: 'desc',
    filters: {
      include: 'blog',
      exclude: '.ru',
      minBacklinks: 10,
      maxBacklinks: 500,
      minSpamScore: 0,
      maxSpamScore: 20,
      hideLost: true,
    },
  }),
})
  .then(r => r.json())
  .then(data => {
    console.log('Referring domains:', data.rows);
    // Output: [{ domain: 'myblog.com', backlinks: 123, ... }, ...]
  });

```

For server-side or testing scenarios, invoke the service directly:

```typescript
import { BacklinksService } from '@/server/features/backlinks/services/BacklinksService';
import { createMockBillingContext } from '@/test/helpers';

const ctx = createMockBillingContext();

BacklinksService.profileReferringDomainsPage(
  {
    target: 'example.com',
    scope: 'domain',
    page: 1,
    pageSize: 20,
    sortField: 'backlinks',
    sortOrder: 'desc',
    filters: {
      include: 'blog',
      exclude: '.ru',
      minBacklinks: 10,
    },
  },
  ctx,
  { hideSpam: false }
).then(result => console.log(result.rows));

```

## Summary

- **Validation Layer**: Zod schemas in [`src/serverFunctions/backlinks.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/backlinks.ts) enforce type safety before processing begins.
- **Filter Translation**: The `buildReferringDomainsApiFilters` function converts user parameters into DataForSEO query syntax using helpers like `collectNumericRange` and `collectExcludeConditions`.
- **Caching Strategy**: Results are cached for six hours via `BacklinksService`, reducing redundant external API calls.
- **Data Normalization**: `normalizeBacklinksTarget` standardizes inputs while `mapReferringDomainsRows` trims API responses to essential domain metrics.
- **Architecture**: The separation between server functions, service logic, and filter construction maintains clean separation of concerns while supporting complex filtering scenarios.

## Frequently Asked Questions

### How does Open SEO validate incoming backlink analysis requests?

Open SEO uses Zod schemas defined in [`src/types/schemas/backlinks.ts`](https://github.com/every-app/open-seo/blob/main/src/types/schemas/backlinks.ts) to validate all incoming payloads. The `referringDomainsPageRequestSchema` specifically ensures that filter parameters, pagination settings, and target specifications meet strict TypeScript types before the `BacklinksService` processes the request.

### What filtering capabilities are supported for referring domains?

The system supports string pattern filtering (include/exclude substrings), numeric range filtering for metrics like backlinks and spam score, and boolean flags such as `hideLost`. These filters are assembled in [`src/server/features/backlinks/services/backlinksApiFilters.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/backlinks/services/backlinksApiFilters.ts) using `buildReferringDomainsApiFilters` and joined with `AND` operators to create precise DataForSEO API queries.

### How long are backlink analysis results cached?

Results are cached for **six hours** (TTL = 6 hours) by the `BacklinksService` in [`src/server/features/backlinks/services/BacklinksService.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/backlinks/services/BacklinksService.ts). The service generates unique cache keys based on normalized target parameters and filter combinations to ensure cache hits only return relevant, context-specific data.

### Can I use the backlink service directly without the HTTP endpoints?

Yes, you can import `BacklinksService` directly from `@/server/features/backlinks/services/BacklinksService` and call `profileReferringDomainsPage` with a valid context object. This approach is particularly useful for unit testing or internal server-side processing where HTTP overhead is unnecessary.