Displaying Serge analytics
You are rendering Serge data in your own dashboard or in client reports. This page is the display contract: what each number is, what to call it, and what never to claim. The field-level shapes live in the API reference; the rules here are the same ones Serge's own surfaces follow.
Three populations, never blurred
Serge measures three different things. Most display mistakes are one of them wearing another one's label.
- AI-assistant sessions
- An assistant active on the site itself — fetching, browsing, or acting for a user. This is what the /traffic endpoints count.
- Assistant clicks — organic
- A person who clicked a link inside an assistant and landed on the site. ChatGPT tags its outbound links; Serge counts the landings. Not ads.
- Ad clicks — paid
- A person who clicked a paid placement, identified by a platform click ID or an explicit paid utm_medium. A landing that merely carries UTM parameters is not an ad click.
Paid and organic may sit side by side. They never share a number, and they never share a label.
Wording rules
- 01
Tracked, not driven.
Serge counts what landed and what it did on the site. "12 orders from tracked ChatGPT ad clicks" is supportable; "ChatGPT drove 12 orders" claims incrementality that nobody measured.
- 02
Counts are counts.
No error bars or ± on a count. Below roughly ten events, show the bare count and skip rates — a precise-looking percentage on a noise-sized sample misleads.
- 03
No conversation claims.
No platform exposes prompts or user-level data. Never imply the data shows what people asked an assistant.
- 04
Name the window.
Every number carries its period — the API returns period_start and period_end. Compare only equal windows.
- 05
Platform names verbatim.
ChatGPT, Perplexity, Claude, Gemini, Copilot — brand names are not translated, abbreviated, or folded into a house taxonomy.
The same number, said honestly
Don't"ChatGPT drove $4,200 in revenue."
Do"$4,200 in orders from tracked ChatGPT ad clicks (30 days)."
Don't"Verified AI traffic: 1,020 sessions" — when 117 of them are heuristic detections.
Do"1,020 AI-assistant sessions — 903 verified, 117 heuristic."
Don't"100% completion rate" — from one session.
Do"1 session, 1 completed." Rates start when the sample can carry them.
Per endpoint: what to watch, with a sample
The samples below are the same validated examples the API reference publishes — they cannot drift from the contract. The notes cover only what matters once the number reaches a human.
Traffic overview
GET /api/v1/traffic/overview
Sessions and unique visitors are different numbers — label the one you show. share_pct arrives computed; do not recompute it on a filtered subset. In by_outcome, "abandoned" means the session ended without completing — not that an error occurred. median_duration_ms is a median: label it "median", never "avg".
{
"domain": "yourstore.example",
"site_id": "srg_site_9f2c41",
"period": "7d",
"period_start": "2026-07-23T00:00:00.000Z",
"period_end": "2026-07-30T00:00:00.000Z",
"total_sessions": 1284,
"unique_visitors": 1102,
"by_platform": [
{
"platform": "chatgpt",
"sessions": 812,
"share_pct": 63.2
},
{
"platform": "perplexity",
"sessions": 301,
"share_pct": 23.4
},
{
"platform": "claude",
"sessions": 171,
"share_pct": 13.4
}
],
"by_outcome": [
{
"outcome": "completed",
"sessions": 402
},
{
"outcome": "abandoned",
"sessions": 882
}
],
"top_pages": [
{
"entry_url": "/products/aurora-x20",
"sessions": 486
},
{
"entry_url": "/collections/headphones",
"sessions": 210
}
],
"median_duration_ms": 42150
}Purpose split
GET /api/v1/traffic/purpose-split
user_action is an assistant acting on someone's behalf; search is retrieval for an answer; crawl is indexing. Keep the unknown bucket visible — folding it into another category overstates certainty. The split is a composition: one stacked bar or a share list, not four disconnected KPIs.
{
"domain": "yourstore.example",
"site_id": "srg_site_9f2c41",
"period": "7d",
"period_start": "2026-07-23T00:00:00.000Z",
"period_end": "2026-07-30T00:00:00.000Z",
"total_sessions": 1284,
"user_action_sessions": 517,
"search_sessions": 604,
"crawl_sessions": 148,
"unknown_sessions": 15,
"by_purpose": [
{
"purpose": "user_action",
"sessions": 517,
"share_pct": 40.3
},
{
"purpose": "search",
"sessions": 604,
"share_pct": 47
},
{
"purpose": "crawl",
"sessions": 148,
"share_pct": 11.5
}
]
}Verification breakdown
GET /api/v1/traffic/verification
verified, declared and heuristic are tiers of evidence, strongest first. A heuristic session never renders under a "verified" label. If you show one total, keep the tier mix one glance away.
{
"domain": "yourstore.example",
"site_id": "srg_site_9f2c41",
"period": "7d",
"period_start": "2026-07-23T00:00:00.000Z",
"period_end": "2026-07-30T00:00:00.000Z",
"total_sessions": 1284,
"verified_sessions": 903,
"declared_sessions": 264,
"heuristic_sessions": 117,
"by_platform": [
{
"platform": "chatgpt",
"sessions": 812,
"verified": 690,
"declared": 96,
"heuristic": 26,
"tier": "verified"
}
]
}Attribution overview
GET /api/v1/attribution/overview
Never sum value across currencies — render one line per currency (value_minor is in minor units). There is no ROAS field by design: Serge does not read spend yet, and computing your own from partial data produces a false number. Attribution basis matters: a platform click ID is hard evidence, a UTM label is self-declared — keep that distinction reachable.
{
"site_id": "srg_site_9f2c41",
"domain": "yourstore.example",
"period": "30d",
"period_start": "2026-06-30T00:00:00.000Z",
"period_end": "2026-07-30T00:00:00.000Z",
"total_conversions": 214,
"attributed_conversions": 96,
"unattributed_conversions": 118,
"by_currency": [
{
"currency": "USD",
"conversions": 214,
"value_minor": 1893400
}
],
"by_platform": [
{
"platform": "openai",
"conversions": 71,
"by_currency": [
{
"currency": "USD",
"conversions": 71,
"value_minor": 642900
}
]
},
{
"platform": "unattributed",
"conversions": 118,
"by_currency": [
{
"currency": "USD",
"conversions": 118,
"value_minor": 1015300
}
]
},
{
"platform": "google",
"conversions": 25,
"by_currency": [
{
"currency": "USD",
"conversions": 25,
"value_minor": 235200
}
]
}
],
"by_basis": [
{
"basis": "none",
"conversions": 118
},
{
"basis": "declared_click_id",
"conversions": 84
},
{
"basis": "declared_utm",
"conversions": 12
}
]
}Shapes, auth, and limits live in the API reference. If a metric you want to display is not covered here, ask — the rule you get will match how Serge itself renders the same data.