Tests and methodology

We test each surface (for example the web app or the iOS app) at each link location where a link can appear (inline citations, the sources panel, cards, deep research reports and more). Each test has a stable ID used in the data, on lab pages and in the prompts.

Statuses

The status shown for a cell is the most recent result by date. On the same date, a verified result (manual, automated or community) takes precedence over a reported one. Every cell links to its evidence.

How to reproduce

  1. Ask the assistant to cite or link one of the target pages below. For a self-identifying link use /t/<test>/<lab>/<surface>/<location>, for example /t/ref-01/openai-chatgpt/web-desktop/inline-citation.
  2. Open the link from the answer.
  3. The page shows the server-side Referer, document.referrer, the query string and the fragment. The visit is also logged (without IP addresses).
  4. Record the result as described on Contribute.

Test catalog

REF-01: Referrer present

Pass criteria: Request to the target carries Referer with the assistant's origin (e.g. https://chatgpt.com/).

When a person clicks a link, the browser can send a Referer header that names the page they came from. Analytics tools use it to say where a visit came from. If an assistant sends its origin, such as https://chatgpt.com/, the website can count the visit as coming from that assistant instead of "Direct".

Scope: per surface and link location. Target: /t/ref-01

REF-02: No full-URL leak

Pass criteria: Referer is origin only; no conversation path or IDs.

The referrer should say which product sent the visit, not which conversation. Sending only the origin (https://claude.ai/) keeps conversation paths and IDs private while still giving websites the signal they need.

Scope: per surface and link location. Target: /t/ref-02

Pass criteria: Citation links use noopener without noreferrer; page/link referrer policy is origin or strict-origin-when-cross-origin.

On the web, rel="noreferrer" and window.open(url, "_blank", "noopener,noreferrer") remove the referrer. rel="noopener" alone keeps the security benefit and still lets the origin through. A referrer policy of origin or strict-origin-when-cross-origin sends the origin to other sites and never the full path.

Scope: per surface and link location, web surfaces only. Target: /t/ref-03

UTM-01: UTM present

Pass criteria: Landing URL contains utm_source=<documented value>.

Apps and webviews often cannot send a referrer. A utm_source parameter on the link still tells the website where the visit came from. It works in every browser and every app.

Scope: per surface and link location. Target: /t/utm-01

UTM-02: UTM consistent

Pass criteria: Same utm_source value on every surface and link location.

One stable value per product lets websites write one rule and keep it. Different values per app or per link type split the same traffic into several rows that teams then have to merge by hand.

Scope: once per lab. Target: /t/utm-02

UTM-03: UTM documented

Pass criteria: Value published in the lab's public docs/help.

A documented value turns a guess into a contract. Analytics vendors and site owners can add it to their channel rules with confidence, and they know where to look if it changes.

Scope: once per lab. Target: /t/utm-03

MRG-01: Keeps existing query

Pass criteria: Target ?a=1&b=2 arrives with a and b intact.

Many links already carry query parameters for search, filters or product variants. Adding attribution must keep every existing parameter and its value exactly as it was.

Scope: per surface and link location. Target: /t/mrg-01?a=1&b=2

MRG-02: Keeps fragment

Pass criteria: #section is preserved and the tag is inserted before it.

A fragment such as #section-2 points to a place on the page. Query parameters must go before the #; anything after it never reaches the server and breaks the jump to the right section.

Scope: per surface and link location. Target: /t/mrg-02#section-2

MRG-03: No overwrite

Pass criteria: Target with existing utm_source=newsletter keeps that value.

Some links already carry campaign tags set by the website itself. Replacing them would erase the site's own campaign data. The safe default is to leave existing utm_* parameters alone.

Scope: per surface and link location. Target: /t/mrg-03?utm_source=newsletter&utm_medium=email

MRG-04: Signed URLs untouched

Pass criteria: Target with signature/token/expires params arrives byte-identical.

Signed and expiring URLs (downloads, cloud storage, one-time links) stop working if a single byte changes. Links with parameters such as signature, token or expires should be passed through unchanged.

Scope: per surface and link location. Target: /t/mrg-04?expires=2099-01-01&signature=abc123

OPS-01: Changelog

Pass criteria: Lab publishes link-behavior changes (help page, release notes).

Link behavior changes with UI updates. A short public note when it changes lets websites tell a product change from a real drop in traffic, and saves both sides time.

Scope: once per lab. Target: /t/ops-01

Test vectors

Use these input and output pairs to test a link-tagging function. They match the reference implementation on best practices. Each one runs as a unit test in our build.

Source value example.ai. Machine-readable: lib/vectors.json.