TrackSERPs
Log in

Cursor Pagination

TrackSERPs uses opaque cursor pagination across all list endpoints to deliver fast, stable, and deterministic results even as rankings fluctuate.

How Cursor Pagination Works

Endpoints supporting pagination accept two optional query parameters:

  • limit: The maximum number of records to return per page (default: 50, maximum: 500).
  • cursor: An opaque string token representing the pointer to the next page of results.

Responses include a next_cursor field. When next_cursor is a string, more items remain. When next_cursor is null, you have reached the final page.

Paginated Response with next_cursor
{
  "projects": [
    { "id": "proj_1", "name": "E-Commerce US" },
    { "id": "proj_2", "name": "B2B SaaS UK" }
  ],
  "next_cursor": "cur_eyJpZCI6InByb2pfMiJ9"
}

Automated Pagination with the TypeScript SDK

The official @trackserps/sdk client includes built-in async iterators for automatic pagination. You do not need to manually parse or pass cursors:

SDK Async Pagination
import { TrackSERPs } from "@trackserps/sdk";

const client = new TrackSERPs({ apiKey: "ts_live_..." });

// Method 1: Async iterator (iterates across all pages automatically)
for await (const keyword of client.keywords.list("proj_abc123")) {
  console.log(keyword.phrase, keyword.devices);
}

// Method 2: Fetch all items directly with .all()
const allProjects = await client.projects.list().all();
console.log(`Loaded ${allProjects.length} total projects across all pages`);

// Method 3: Page-by-page iteration
for await (const page of client.projects.list().pages()) {
  console.log(`Page returned ${page.projects.length} projects. Next cursor: ${page.next_cursor}`);
}

Manual Pagination Example (Vanilla Fetch)

If you are consuming the raw REST API directly, pass next_cursor into subsequent requests as ?cursor=:

Manual Cursor Loop
async function fetchAllKeywords(projectId, apiKey) {
  let cursor = null;
  const allKeywords = [];

  do {
    const url = new URL(`https://api.trackserps.com/v1/projects/${projectId}/keywords`);
    url.searchParams.set("limit", "100");
    if (cursor) {
      url.searchParams.set("cursor", cursor);
    }

    const response = await fetch(url.toString(), {
      headers: {
        Authorization: `Bearer ${apiKey}`,
        Accept: "application/json",
      },
    });

    if (!response.ok) {
      throw new Error(`Failed to fetch keywords: ${response.statusText}`);
    }

    const data = await response.json();
    allKeywords.push(...data.keywords);
    cursor = data.next_cursor; // null on the final page
  } while (cursor);

  return allKeywords;
}
Cursor Pagination · TrackSERPs API Docs