GA4 key events timeline
Daily GA4 key events (conversions) from AI-referred traffic, split by event name and by LLM source.
curl --request GET \
--url 'https://api.aiclicks.io/api/v1/ga4/key-events-timeline?domain_id=8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3&days=30' \
--header 'Authorization: Bearer ak_live_xxx'
import httpx, os
resp = httpx.get(
"https://api.aiclicks.io/api/v1/ga4/key-events-timeline",
params={"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3", "days": 30},
headers={"Authorization": f"Bearer {os.environ['AICLICKS_API_KEY']}"},
)
resp.raise_for_status()
for day in resp.json()["data"]["items"]:
total = sum(sum(by_llm.values()) for by_llm in day["by_event"].values())
print(day["date"], total)
const url = new URL("https://api.aiclicks.io/api/v1/ga4/key-events-timeline");
url.searchParams.set("domain_id", "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3");
url.searchParams.set("llm_source", "chatgpt");
const resp = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.AICLICKS_API_KEY}` },
});
const { data } = await resp.json();
console.log(data.items);
{
"data": {
"items": [
{
"date": "2026-11-02",
"by_event": {
"signup": { "chatgpt": 4, "perplexity": 1 },
"purchase": { "chatgpt": 1 }
}
},
{
"date": "2026-11-03",
"by_event": {
"signup": { "chatgpt": 2, "gemini": 1 }
}
}
]
},
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"llm_source": null,
"start_date": null,
"end_date": null,
"generated_at": "2026-11-09T10:00:11.218Z"
}
{ "detail": "domain_id query parameter is required. List the domains this key can access with GET /api/v1/domains, then pass ?domain_id=<uuid>." }
{ "detail": "Invalid or revoked API key" }
{ "detail": "API access is not enabled for this team. Contact support@aiclicks.io." }
{ "detail": "Too many requests. Please try again later." }
This endpoint returns the daily trend of GA4 key events (conversions) from AI-referred traffic. Each day splits the counts by event name, and each event splits the counts by LLM source.
Use it to see when AI-referred visitors converted, and which assistant sent them. For the window totals, use GET /api/v1/ga4/key-events.
The connected GA4 property sets which events are key events. The event names here are the names in that property.
The domain_id query parameter is required. To find the domains that your key can access, use GET /api/v1/domains.
If the domain has no connected GA4 property, the endpoint returns 200 with an empty items list. Days without key events do not appear in the list.
Authorizations
Your API key formatted as Bearer ak_live_<your-key>. Create one in the dashboard under Settings → Developers.
Optional UUID for log correlation. If you do not send one, the server makes one and returns it in the response.
Query parameters
UUID of the domain. Find domains with GET /api/v1/domains. If you do not send it, the endpoint returns 400.
Trailing look-back window in days, 1–365. Defaults to 30. The server uses the exact value. For example, days=95 returns the last 95 days.
Start of a fixed window, YYYY-MM-DD. Send it with end_date. A fixed window overrides days.
End of a fixed window, YYYY-MM-DD, inclusive. Send it with start_date.
Optional. One AI referral source: chatgpt, perplexity, claude, gemini, copilot, … If you send it, the counts include only that source.
If true, the server ignores the cached result and calculates a new result. The new result replaces the cached result. Defaults to false.
Response
The timeline payload.
One entry for each day with at least one key event, in date order.
Echo of the requested domain.
Echo of the requested window.
Echo of the llm_source filter. null when you do not send it.
Echo of start_date. null when you do not send it.
Echo of end_date. null when you do not send it.
ISO-8601 timestamp of when the server made (or cached) this response.
Response headers
| Header | Description |
|---|---|
X-Cache | HIT, MISS, or REFRESH (when fresh=true). Tells you if the response came from cache. |
X-Request-Id | Unique request id. Echoes your id if you send one. |
X-RateLimit-Limit | Maximum requests per minute for this key. |
X-RateLimit-Remaining | Requests that remain in the current minute. |
X-RateLimit-Reset | Unix epoch seconds when the window resets. |
Caching
The server keeps the result in cache for 1 hour for each (domain_id, days, llm_source, start_date, end_date). New GA4 data shows after the cache expires. To get a new result, send fresh=true.
Errors
The domain_id is missing.
The API key is missing, not valid, or revoked.
The team's developer_access flag is off. Or the domain is not in the scope of your API key.
The domain_id is not valid or does not exist. Or your user is not a member of the domain's team.
You sent too many requests. The Retry-After header tells you how long to wait.
Empty result
{
"data": { "items": [] },
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"llm_source": null,
"start_date": null,
"end_date": null,
"generated_at": "2026-11-09T10:00:11.218Z"
}