DEV Community

Cover image for We Asked ChatGPT and Google AI Mode the Same 60 Questions. They Shared 19 of 507 Cited URLs.
Canlah AI
Canlah AI

Posted on AI-assisted

We Asked ChatGPT and Google AI Mode the Same 60 Questions. They Shared 19 of 507 Cited URLs.

We put the same 60 buyer questions to ChatGPT and Google AI Mode on the same night. Question by question, the two engines shared 19 of 507 cited URLs. That's 3.7%. Blend both engines into one "AI visibility" score and you're averaging two different source lists.

Everything behind that number is public: the questions, all 917 citation rows, the ChatGPT answers and our page-by-page notes. CC BY 4.0, on GitHub and Hugging Face, with a DOI. This post covers how it was collected, how a citation is counted, and how to recount every headline number with about 20 lines of pandas.

The GEO Playbook in five moves: plan each engine separately, stop grading yourself on Google's top 10, put the answer in the first 30% of the page, put pricing in a real table, re-ask every month.

What the data turned into: the 44-second film.

GitHub logo Canlah-AI / ai-citations-sg-2026

What ChatGPT and Google AI Mode cite for 110 Singapore buyer questions: every cited URL in answer order, ChatGPT answers, 92 cited pages taken apart. Round 1: 526 citations on two engines; round 2: 241 on ChatGPT. CC BY 4.0, DOI.

AI Citations SG 2026: 7.2% of ChatGPT's cited URLs sat in Google's organic top 10; 23.9% of ChatGPT's cited URLs repeat when the same question is asked twice.

What do ChatGPT and Google AI Mode cite when Singapore buyers ask?
110 questions, every cited URL, open to recount.

License: CC BY 4.0 DOI 10.5281/zenodo.23005020 Hugging Face dataset 110 questions Engines: ChatGPT and Google AI Mode Format: CSV and JSONL

Load it in 30 seconds · Recounts and findings · The playbook built on it · 中文完整数据说明

What this dataset shows, in five moves: plan each engine separately, stop grading yourself on Google's top 10, put the answer in the first 30% of the page, put pricing in a real table, re-ask every month.
▶ Watch the 44-second film


Put the same 60 Singapore buyer questions to ChatGPT and Google AI Mode and they cite almost entirely different pages: 19 of 507 cited URLs shared (3.7%). Ask ChatGPT the same question twice, minutes apart, and only 23.9% of its cited URLs come back. Here is every citation behind those numbers, so you can check them yourself.

Five Singapore industries. 110 buyer questions. ChatGPT (OpenAI API, gpt-5.5 with web search, Singapore location) and, in round 1, Google AI Mode (through a third-party SERP API). This dataset keeps the questions, every cited URL in answer order, the ChatGPT answer texts, our page-by-page annotations of cited pages, and a…




TL;DR

  • 60 buyer questions from five Singapore industries: dental, family law, tuition, B2B SaaS and e-commerce. ChatGPT returned 307 citations, Google AI Mode 219: 526 citations, 474 distinct URLs.
  • Same question, two engines: 19 shared URLs out of 507 (3.7%). In 36 of the 54 questions where both engines cited sources, they shared nothing at all.
  • In that round, ChatGPT cited 0 of 307 forum or social pages. AI Mode cited 30 of 219 (YouTube 13, Reddit 10).
  • Ask ChatGPT the same question twice, minutes apart, and only 53 of 222 cited URLs repeat (23.9%).

What we collected

Two rounds, both run in the early hours of 23 September 2026 (Singapore time), about 55 minutes apart.

Round 1 Round 2
Questions 60 (5 industries × 12, 6 in Chinese) 50 (5 × 10, 5 in Chinese)
Engines ChatGPT + Google AI Mode ChatGPT only
Official citations 307 + 219 = 526 241

Round 1 asks buying questions: how much, which one, A or B, what if it goes wrong. Round 2 uses the same nine question types in every industry: definition, process, statistics, calculation, near me, single review, full guide, rules and checklist.

The rounds ask different questions, so we never add them together. Each one stands on its own.

How one citation is captured

ChatGPT goes through the OpenAI Responses API: gpt-5.5 with the web_search tool, approximate location Singapore, no system prompt, the question passed in as-is. Citations come from the url_citation annotations on the answer text.

Google AI Mode goes through a third-party SERP API with gl=sg; citations come from its reference list.

Both are API results, not what someone sees in the consumer app, and each question was asked once in the official runs.

Here's the shape of the ChatGPT call, simplified from the method in the dataset README:

from urllib.parse import urlsplit, urlunsplit
from openai import OpenAI

client = OpenAI()


def strip_openai_utm(url: str) -> str:
    """Drop only utm_source=openai; leave every other parameter byte-for-byte."""
    parts = urlsplit(url)
    kept = [p for p in parts.query.split("&") if p and p != "utm_source=openai"]
    return urlunsplit(parts._replace(query="&".join(kept)))


resp = client.responses.create(
    model="gpt-5.5",
    tools=[{"type": "web_search",
            "user_location": {"type": "approximate", "country": "SG", "city": "Singapore"}}],
    input="how much does a single tooth dental implant cost in Singapore and can I use Medisave",
)

citations = []  # one entry per distinct URL, in order of first mention
for item in resp.output:
    if item.type != "message":
        continue
    for part in item.content:
        for ann in getattr(part, "annotations", None) or []:
            if ann.type == "url_citation":
                url = strip_openai_utm(ann.url)
                if url not in citations:
                    citations.append(url)

print(resp.model, len(citations))
Enter fullscreen mode Exit fullscreen mode

Three rules turn raw answers into rows:

  1. One citation = one distinct URL within one answer. A URL linked five times in one answer counts once. That's why 526 citations collapse to 474 distinct URLs once you dedupe across answers.
  2. Strip only utm_source=openai. ChatGPT appends it to links. It touched 30 of the 917 rows, and removing it creates no new duplicates.
  3. Keep the order. position is the order of first mention in the ChatGPT answer, or the order of AI Mode's reference list.

The files

File Rows One row is
queries.csv 110 a question, with industry, round, language and question type
citations.csv 917 one URL in one answer (767 official, 150 supplementary)
chatgpt_answers.jsonl 141 one ChatGPT call, with the model receipt and answer text
page_annotations.csv 141 our notes on one cited page
page_types.csv 46 one type of cited page

Filter on official == "yes" for the headline numbers. The supplementary rows are an independent second run of 30 round-2 questions, plus one retry, kept for the repeat test further down.

Recount the headline numbers

No clone needed:

import pandas as pd

BASE = "https://raw.githubusercontent.com/Canlah-AI/ai-citations-sg-2026/main/"
cites = pd.read_csv(BASE + "citations.csv")

# Headline numbers use the official runs only
r1 = cites[(cites["official"] == "yes") & (cites["round"] == "r1")]

print(r1["engine"].value_counts().to_dict())
print(len(r1), "citations,", r1["url"].nunique(), "distinct URLs")

# Same question, two engines: how many cited URLs overlap?
shared = union = 0
for _, g in r1.groupby("query_id"):
    a = set(g.loc[g["engine"] == "chatgpt", "url"].str.rstrip("/"))
    b = set(g.loc[g["engine"] == "google_ai_mode", "url"].str.rstrip("/"))
    shared += len(a & b)
    union += len(a | b)
print(f"{shared} shared of {union} ({shared / union:.1%})")

# Forum and social pages, per engine
print(r1[r1["is_ugc"] == "yes"]["engine"].value_counts().to_dict())
Enter fullscreen mode Exit fullscreen mode

Output:

{'chatgpt': 307, 'google_ai_mode': 219}
526 citations, 474 distinct URLs
19 shared of 507 (3.7%)
{'google_ai_mode': 30}
Enter fullscreen mode Exit fullscreen mode

Prefer Hugging Face? load_dataset("CanlahAI/ai-citations-sg-2026", "citations") gives you the same 917 rows.

Read the 3.7% for what it is: overlap of cited URLs, not a score for either engine. Two engines, two source lists. If you care about both, check both.

Ask twice, get a different list

Thirty round-2 questions were sent twice, minutes apart, same model, same settings. Same cites frame as above:

twice = cites[cites["run_id"].isin(["r2", "r2_rerun"])]

inter = union = 0
for q in twice.loc[twice["run_id"] == "r2_rerun", "query_id"].unique():
    g = twice[twice["query_id"] == q]
    a = set(g.loc[g["run_id"] == "r2", "url"])
    b = set(g.loc[g["run_id"] == "r2_rerun", "url"])
    inter += len(a & b)
    union += len(a | b)

print(f"{inter} of {union} URLs repeat ({inter / union:.1%})")  # 53 of 222 (23.9%)
Enter fullscreen mode Exit fullscreen mode

By registered domain it's 64 of 146 (43.8%). Exactly 1 of the 30 questions came back with an identical list. One answer is one sample. A ranking built on one sample is noise with a decimal point.

What else is in there

  • Different engines lean on different sources. For dental questions, 76% of ChatGPT's citations (38 of 50) went to government and public-institution pages, while 75% of AI Mode's (39 of 52) went to clinics and other commercial sites. Filter r1 to query_id values containing DEN and run pd.crosstab(den["engine"], den["site_type"]).
  • Mostly not the Google top ten. Only 7.2% of ChatGPT's cited URLs (22 of 307) sat in Google's organic top ten for the same question. For AI Mode it was 40.6% (89 of 219). Google's result lists aren't redistributed, so this one lives as aggregates in stats.md.
  • The lifted line opens a paragraph. On 15 of 18 cited family-law pages, the sentence the engine used was the first sentence of its paragraph. The position notes (written in Chinese) are in page_annotations.csv.
  • 46 types of cited page, from price guides to statute explainers: 9 tested on both engines, 33 with ChatGPT evidence only, 4 untested and labelled that way in page_types.csv.

Scope, in one paragraph

These are API results, not the consumer UI. One market (Singapore), mostly English, 10 to 12 questions per industry, one night in September. Official answers are stored as their first 600 characters, so later sentences can't be matched to citations. Site types come from domain rules, not hand checks. The README (English summary on top, detail in Chinese) spells out what the data shouldn't be used for, including scoring individual businesses.

Ideas if you want to build on it

  • Re-run the 110 questions on a newer model and diff against September.
  • Add a Google AI Mode leg to round 2, which is ChatGPT only today.
  • Test whether the "first sentence of a paragraph" pattern holds outside Singapore.

To cite it: Pang, H. (2026). Singapore GEO Citation Probes, September 2026 (ChatGPT and Google AI Mode). Canlah AI. doi.org/10.5281/zenodo.23005020

Why it exists

We collected it to write the GEO Playbook, a free method book on getting a business named in AI answers: 9 chapters plus 4 appendices, a blueprint for each of the 46 page types, and dental and law-firm editions. All CC BY 4.0, and every number in it is sourced, with our own measurements tracing back to these files (evidence appendix).

If you'd rather hand the method to an agent, the condensed version is a Claude Code plugin:

/plugin marketplace add Canlah-AI/geo-playbook
/plugin install geo-playbook@canlah-ai
Enter fullscreen mode Exit fullscreen mode

Codex, Cursor and other agents can read the same rules from AGENTS.md in the repo.

What would you test first with 917 labelled citations? Tell me in the comments.


Written with AI assistance. The headline numbers were recounted from the dataset with the code in this post; the rest come from the dataset's stats.md and README.

Top comments (0)