> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rankraft.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Citation rank by domain, with change

> The domains AI answers cite most, who owns each, and how each one's share moved against the previous period.

A citation leaderboard: every domain cited in answers to your prompts, ranked, with its owner and its change in share against the previous window. Two calls, joined on `domain`.

## How this example works

1. **Current window:** the citations report with `entity: "domain"`. Rows arrive ranked by `answers` (how many answers cited the domain), which is the most robust order. Take the top N.
2. **Previous window:** the same call over the same number of days before, **all pages**, so a domain that ranked lower last time still has a previous share.
3. **Join on `domain`** and subtract shares. A domain missing last time was 0 then: it's new.

> [!NOTE]
>
> `answers` and `citations` rank slightly differently. `answers` counts distinct answers citing a domain; `citations` counts every link, so a domain linked five times in one answer has 1 answer and 5 citations. `citation_share` follows `citations`. Pick the one that matches your question and sort on it.

```js JavaScript theme={"system"}
import { RankRaft } from "rankraft-js";

const rr = new RankRaft();
const base = { site_id: process.env.RANKRAFT_SITE_ID, entity: "domain", metrics: ["answers", "citations", "citation_share"] };

const [current, previous] = await Promise.all([
  rr.reports.citations({ ...base, start_date: "2026-09-01", end_date: "2026-09-30", limit: 25 }), // first page = top 25
  rr.reports.citations({ ...base, start_date: "2026-08-02", end_date: "2026-08-31", limit: 100 }).all(),
]);

const before = new Map(previous.map((r) => [r.domain, r]));

for (const r of current.data) {
  const p = before.get(r.domain);
  const delta = p ? `${((r.citation_share - p.citation_share) * 100).toFixed(1)} pp` : "new";
  const move = p ? p.rank - r.rank : null;
  console.log(
    `${String(r.rank).padStart(2)}. ${r.domain.padEnd(28)} ${r.owner.padEnd(11)} ${r.source_kind.padEnd(11)} ` +
      `${String(r.answers).padStart(4)} answers  ${(r.citation_share * 100).toFixed(1)}%  ${delta}` +
      (move ? `  (${move > 0 ? "↑" : "↓"}${Math.abs(move)})` : ""),
  );
}
```

```python Python theme={"system"}
import os
from rankraft import RankRaft

base = dict(site_id=os.environ["RANKRAFT_SITE_ID"], entity="domain",
            metrics=["answers", "citations", "citation_share"])

with RankRaft() as rr:
    current = rr.reports.citations(**base, start_date="2026-09-01", end_date="2026-09-30", limit=25)  # top 25
    previous = rr.reports.citations(**base, start_date="2026-08-02", end_date="2026-08-31", limit=100).all()

before = {r["domain"]: r for r in previous}

for r in current:
    p = before.get(r["domain"])
    delta = f"{(r['citation_share'] - p['citation_share']) * 100:+.1f} pp" if p else "new"
    move = p["rank"] - r["rank"] if p else 0
    arrow = f"  ({'↑' if move > 0 else '↓'}{abs(move)})" if move else ""
    print(f"{r['rank']:>2}. {r['domain']:<28} {r['owner']:<11} {r['source_kind']:<11} "
          f"{r['answers']:>4} answers  {r['citation_share']:.1%}  {delta}{arrow}")
```

```bash curl theme={"system"}
curl https://api.rankraft.ai/v1/reports/citations \
  -H "X-API-Key: $RANKRAFT_API_KEY" -H "Content-Type: application/json" \
  -d '{"site_id":"'$RANKRAFT_SITE_ID'","start_date":"2026-09-01","end_date":"2026-09-30",
       "entity":"domain","metrics":["answers","citations","citation_share"],"limit":25}'
# Repeat for 2026-08-02..2026-08-31 (all pages) and join on domain.
```

## What each row tells you

| Field | Meaning |
| - | - |
| `rank` | Position by `answers`, 1 = cited in the most answers. |
| `owner` | `own` (your site), `competitor` (a domain on a competitor entry), `third_party` (everyone else). |
| `source_kind` | `forum`, `video`, `review`, `roundup`, `editorial`, `marketplace`, `reference`, `social`, `publishing`, `recipe`, `brand` or `unknown`. |
| `answers` | Distinct answers citing the domain. |
| `citations` | Every link to it. |
| `citation_share` | `citations` ÷ all citations in the range, 0–1. |

## Variations

* **Only third-party sources** (the ones you can try to get onto): add `filter: owner is third_party`. The shares then add up to 1 among third-party domains; see [Where AI gets its answers](/cookbook/citation-sources).
* **Per engine:** `group_by: ["platform"]`. `rank` restarts within each engine, and rows arrive grouped by engine.
* **Pages instead of domains:** `entity: "page"`, joined on `page`.
* **Cited pages churn quickly.** A large share of cited pages changes from month to month, so a single month's move for a small domain is rarely meaningful. Look at the top of the list and at changes of more than a point or two.

## Common follow-ups

> **[Where AI gets its answers](/cookbook/citation-sources)**
>
> Third-party sources by kind.

> **[Owned citation share](/cookbook/owned-citation-share)**
>
> Your total share and its change.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.