Gemini sources
The pages the Gemini app cites for its answer, with the inline chips that group them.
`sources` returns the cited pages in order and `citationPills` records which sources sit behind each chip, including section-summary chips that cite several pages. Comparison tables in an answer come back as `shoppingCards`.
Returned in result
| Field |
|---|
sources |
citationPills |
Request
curl -X POST "https://api.answerline.dev/v1/monitor/gemini" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt":"iPhone 17 or Galaxy S26?","country":"US"}'
What Gemini’s sources are
A Gemini source is a web page the Gemini app cites for its answer. The app attaches citation chips to passages, some of which bundle several pages, including section-summary chips, and lists the cited pages in a sources rail. This API returns both layers: sources is the ordered list, and citationPills records which pages sit behind each chip.
For the same question, Gemini’s citations can differ from AI Mode and the AI Overview, so they form their own column in an AI share-of-voice report. They show which pages Gemini relies on in your category, what share of answers cite your domain, and whether you are cited alone or as one of many: a page that leads a chip, or sits in a single-source chip, is a different signal from the fourth page of a section summary.
Field reference
result.sources[]
| Field | Type | Meaning |
|---|---|---|
position |
integer | Where the source sits in the list. |
label |
string | Title or label of the source. |
url |
string | URL of the source. |
description |
string | Snippet or description text for the source. |
All four fields are optional. Key on url.
result.citationPills[]
| Field | Type | Meaning |
|---|---|---|
label |
string, required | Per-source title from the sources rail. Always present; may be an empty string, in which case read domain or url. |
citationPillId |
integer, required | 1-based ordinal shared by every entry from the same chip. |
url |
string, required | Link straight to the cited source. |
domain |
string, required | Host extracted from url. |
description |
string | Source description from the rail. Omitted when absent. |
position |
integer, required | 1-based position of this source in result.sources. |
Each entry is one (chip, source) pair. A chip citing three sources produces three entries sharing a citationPillId, each with its own label, url and domain. The whole array is omitted when the answer has no pills.
places (place cards) is not returned today.
Annotated excerpt
Values are illustrative; field names and types follow the POST /v1/monitor/gemini result schema.
{
"success": true,
"result": {
"text": "For a first home espresso setup, a single-boiler machine with...",
"sources": [
{
"position": 1,
"label": "Best espresso machines for beginners",
"url": "https://www.example-coffee.com/guides/beginner-espresso",
"description": "We pulled 300 shots on twelve machines..."
},
{
"position": 2,
"label": "Single vs dual boiler explained",
"url": "https://forum.example-baristas.org/t/single-vs-dual-boiler",
"description": "Temperature stability and steam power..."
}
],
// Two entries, one chip: citationPillId 1 cites both sources.
"citationPills": [
{
"label": "Best espresso machines for beginners",
"citationPillId": 1, // 1-based
"url": "https://www.example-coffee.com/guides/beginner-espresso",
"domain": "example-coffee.com",
"position": 1 // points to result.sources[0]
},
{
"label": "", // no title in the rail: use domain
"citationPillId": 1,
"url": "https://forum.example-baristas.org/t/single-vs-dual-boiler",
"domain": "forum.example-baristas.org",
"position": 2
}
]
}
}
Cost and request options
No include flag is needed. sources, citationPills and shoppingCards are part of the Gemini result whenever the answer carries them. A Gemini request costs $0.0006, and none of the include flags change that.
The request takes prompt and country. Gemini answers from 213 countries, and takes a US state with country: "US". There is no language parameter, so write prompts in the market’s language when you compare countries.
Example: citation share and chip lead share by domain
The script runs each prompt several times as async tasks and reports three numbers per domain: the fraction of answers citing it at least once, the fraction of all chips (distinct citationPillId per answer) that include it, and the fraction of chips where it is the first source, which approximates the label a reader sees on the chip.
import os
import time
from collections import Counter
from datetime import date
from urllib.parse import urlparse
import requests
API = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
PROMPTS = ["best espresso machine for beginners", "is a dual boiler espresso machine worth it"]
SAMPLES = 5
DAY = date.today().isoformat()
def run_tasks(tasks):
resp = requests.post(f"{API}/v1/async/task/batch", headers=HEADERS, json=tasks, timeout=60)
resp.raise_for_status()
pending = {item["task"]["id"] for item in resp.json()["results"] if item["success"]}
results = []
while pending:
time.sleep(10)
for task_id in list(pending):
body = requests.get(f"{API}/v1/async/task/{task_id}", headers=HEADERS, timeout=30).json()
status = body["task"]["status"]
if status in ("COMPLETED", "FAILED"):
pending.discard(task_id)
if status == "COMPLETED":
results.append(body["response"]["result"])
return results
def host(url):
return (urlparse(url).hostname or "").removeprefix("www.")
tasks = [
{
"taskType": "GEMINI",
"payload": {"prompt": prompt, "country": "US"},
"idempotencyKey": f"espresso-sources-{p}-s{s}-{DAY}",
}
for p, prompt in enumerate(PROMPTS)
for s in range(SAMPLES)
]
answers = run_tasks(tasks)
answer_hits, chip_hits, lead_hits = Counter(), Counter(), Counter()
total_chips = 0
for result in answers:
answer_hits.update({host(src["url"]) for src in result.get("sources", []) if src.get("url")})
chips = {}
for pill in result.get("citationPills", []):
chips.setdefault(pill["citationPillId"], []).append(pill)
total_chips += len(chips)
for entries in chips.values():
entries.sort(key=lambda e: e["position"])
chip_hits.update({host(e["url"]) for e in entries})
lead_hits[host(entries[0]["url"])] += 1
n = len(answers) or 1
c = total_chips or 1
print(f"{len(answers)} answers, {total_chips} chips")
for domain, hits in answer_hits.most_common(15):
print(f"{domain:40} answers {hits / n:5.0%} chips {chip_hits[domain] / c:5.0%} lead {lead_hits[domain] / c:5.0%}")
The script sorts entries within a chip by position to pick the lead source. position is the index into sources, not the order inside the chip, so treat lead share as an approximation and keep the definition fixed across periods.
Shopping cards, briefly
When Gemini shows products beside an answer, they come back as shoppingCards (fields). Products are not citations: a product can appear as a card without its site being cited, and the reverse. Report the two separately.
Pitfalls
citationPills is omitted when there are no chips, and shoppingCards when there are no products. Read both with .get() and a default. citationPills[].label can be "", so group by domain or url.
A section-summary chip citing several pages inflates entry counts. Count distinct citationPillId values when you mean chips.
domain is the full host (forum.example-baristas.org). Decide whether to roll subdomains into a registrable domain and apply the rule to sources and citationPills alike.
Gemini’s citationPillId is 1-based like AI Mode, Copilot and Perplexity; ChatGPT’s is 0-based. position is 1-based everywhere and is the safer join key.
Cited pages change between runs of the same prompt and market, so report share with the sample size (AI answer volatility).
Related
- Gemini engine guide: sync and async calls, webhooks, geo targeting and billing.
- Monitoring Gemini with an API for a step-by-step walkthrough.
- How AI engines choose citations and mentions vs citations.
- Compare with ChatGPT sources.
- AI visibility tracking and competitor analysis.
Questions
Do I need an include flag to get Gemini sources?
No. sources and citationPills are part of every Gemini result at the base price: $0.0006. The Gemini include flags (markdown, rawResponse, rawWire) add nothing.
What is the difference between sources and citationPills in Gemini results?
sources is the ordered list of pages Gemini cited. citationPills has one entry per chip and source pair for the chips shown in the answer, with a 1-based citationPillId to regroup them and a position that points back into sources.
Why is citationPills missing from some Gemini results?
The field is omitted from result when the answer carries no pills. Treat a missing key as zero chips rather than as an error.
Are Gemini shopping cards counted as sources?
No. shoppingCards is a separate array of the products Gemini shows beside the answer. Measure it separately from web citations. Place cards (places) are not returned today.
Should I count Gemini citations by chip or by entry?
It depends on the question. Count distinct citationPillId values to count visible chips, and count entries to count every source attached to a chip; a section-summary chip citing four pages is one chip and four entries.