Every Gemini citation we stored was the same wrong domain
Gemini reports its sources as links through Google’s own redirector. Read the URL and you record Google as the source — 768 times, then recommend outreach to an API endpoint.
Our citations table had 768 Gemini rows in it. Every single one named the same source, and the source was vertexaisearch.cloud.google.com. Not one real domain among them.
Nothing had errored. The scans ran, the answers came back, the rows were written, the dashboard drew a chart. The column was full and it was measuring nothing.
What Gemini actually returns
When Gemini answers with Google Search grounding, it reports its sources as grounding chunks. A chunk looks like this:
uri: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQ…
title: serpmaestro.comThe uri is not the page Gemini read. It is a link through Google’s own redirector that will, when followed, arrive at the page Gemini read. The actual source is sitting in title, which for a web chunk holds a bare hostname rather than the page headline you would expect from a field with that name.
So the obvious thing to do with a citation API — take the URI, parse it, keep the hostname — records Google as the source of every answer Google gives you. Which is what we did.
Why it survived review
This is the part worth dwelling on, because the bug is trivial and the reason it lived for months is not.
It produced well-formed data. A hostname is a hostname; nothing downstream could tell that this one was wrong. There was no null to trip an assertion, no parse failure to log, no empty state to notice. A column full of a plausible string looks exactly like a column that works.
It was also consistent, which made it worse. Had half the rows been right we would have seen the other half immediately, by contrast. All of them being identical read as a quiet engine rather than a broken parser — Gemini cites fewer sources than Perplexity, so a thin, repetitive citation list was already the expected shape.
And the other two engines gave us no reason to look. OpenAI returns real URLs in its url_citation annotations. Perplexity returns real URLs in citations. Two providers behaving normally is enough to make you trust the shape of the third.
What it cost
A wrong value in a list nobody reads is cheap. This one was not in a list nobody reads.
The action engine ranks cited domains as outreach targets — if a domain keeps getting quoted in answers about your category, being present on it is worth something. Feed it 768 rows naming one host and it does the arithmetic correctly: the single most-cited domain in the dataset, by a margin, recommended at the top of the list. The highest-scoring piece of advice we served a paying account was to go and get mentioned on vertexaisearch.cloud.google.com, which is a Google API endpoint. They generated the brief for it twice.
The second cost was subtler and more corrosive. Whether a brand is cited is decided by matching the customer’s domain against the cited ones. No real domain can ever match that redirect host, so brand_cited was structurally false on Gemini, for everybody, always. Not noisy — impossible. Every Gemini citation rate we had ever shown was a zero with a mechanism behind it, and zero is a number people believe.
The fix, and the part of it that is a judgement call
Read title, validate it looks like a hostname, keep that. Where uri is not the redirect host, keep the URI, because a real URL beats a domain derived from one.
The judgement call is what to do with the redirect link itself, and the tempting answer is to store it as the citation URL — it is, after all, the only deep link on offer, and it resolves today.
We throw it away, for two reasons. Those tokens expire, so a citations table full of them is a table of links that will 404 on whatever schedule Google chooses, and a broken reference in an audit report is worse than an honest domain. More importantly they are unique per answer: the same page cited by two different prompts yields two distinct URLs that will never aggregate. A citation queue whose job is to count how often a source comes up would see every mention as a first mention.
A chunk we cannot resolve is dropped rather than downgraded. Recording the redirect host is not a lesser version of the truth — it is the thing that produced the bad advice.
Three checks on your own data
If anything you own records AI citations, these take a minute each and one of them will probably find something.
Group your citation sources and read the top row. Not the chart — the raw count, by host, descending. A redirector, a CDN, a consent-wall domain or a search engine sitting at the top is a parser bug wearing a result’s clothes. Real citation distributions have a long tail of ordinary domains.
Count the distinct hosts per engine. One is a bug. A number suspiciously close to your row count is a different bug: URLs carrying per-answer tracking parameters, never aggregating, every mention looking unique. Strip query strings before you count anything.
Ask whether your match condition can ever be true. Our brand-cited check was comparing a customer domain against a set that could not contain it. A boolean that is false for a structural reason and a boolean that is false because the thing did not happen are indistinguishable on a dashboard, and only one of them is information.
The general shape
A citation is a claim about where an answer came from, and this is the second time on this site we have found a claim like that quietly pointing at the wrong place — the canonical tag pointing at a redirect was the same failure in a different field.
Both share a property: if a column can hold a value that no real source could ever be, it is not validating what its name says it validates. The redirect host was never a possible answer to “which site did this come from”. Nothing in the system knew that, because nobody had written it down.
Which also means the engines do not agree on what a citation is, and any tool that treats the three as one field has made a decision on your behalf about whose definition wins. Worth asking which one, and whether a search ran at all.
CiteSite asks each engine directly, keeps the source each one reports, and records whether the answer was grounded in a live search or recalled from training. When a citation says a domain, that is the domain.