Cookieless visitor counting
On this page
Cookieless counting is a separate Analytics collection path. It never calls the person/identity resolver, creates sessions, links payments, invokes recordings, or exports events to destinations. Existing SDK analytics remains unchanged.
A trusted application server sends POST /api/v1/cookieless using its secret
key. The request is a strict JSON object (maximum 4 KiB):
id: a fresh UUID per event; reuse it for a retry.kind:pagefor navigation oractivefor a visible-page heartbeat.origin: an allowed site origin, without a trailing slash.ip: the visitor address from a trusted hosting proxy, not browser input.userAgent: visitor user-agent, maximum 512 characters.path: public pathname only, maximum 300 characters, no query or fragment.referrer: referring hostname only, or an empty string for direct traffic.country: optional two-letter country from trusted edge metadata.
Public keys cannot call this endpoint. The existing key rate limit, analytics module switch, telemetry admission policy, retry receipts and monthly quota apply. Bots are discarded. Raw IP/user-agent values exist only during the request. Admission receives an identifier-free event, so logs, telemetry receipts and audit metadata cannot acquire visitor network details from this path.
A random per-app/environment salt, replaced at UTC midnight, hashes the site origin, IP and user-agent. Neither the address nor the full user-agent is stored. Daily hashes and dimension deduplication rows remain for at most two UTC days to serve the rolling 24-hour window, then the minute cleanup job deletes them. Inactive salts are cleared after midnight. Operational backups and hosting logs remain subject to their own retention; this design does not claim that hashes are legally anonymous or that a cookie exemption automatically applies.
Reports#
Analytics → Cookieless shows the same three counts as the public report:
- Online: daily identifiers with activity in the last five minutes.
- Visitors in 24 hours: daily identifiers active in the rolling 24-hour window.
- Visitors: lifetime sum of daily visitor estimates since first collection.
The same person may count twice across midnight, even within a rolling 24-hour
window. Shared addresses and browser changes can undercount or overcount. No
lifetime unique-person claim is made. Heartbeats can start a new daily visitor
at midnight but do not increment pageviews. Chart buckets record the first
appearance of each daily visitor; breakdowns deduplicate each visitor per value
per UTC day. The chart and breakdown window is rounded to the hour. Retained
aggregate history follows applications.retention_days; lifetime totals survive
history retention and are removed when the application is deleted.
In Settings → Public sharing choose Traffic source → Cookieless visitors and
save the existing overview. No extra share kind is created. Its opaque URL and
legacy alias keep working, and the existing details switch controls public pages,
country, browser and OS breakdowns. Referrer and device summaries are included.
The share-bound API is GET /api/v1/public/shares/<share-id>/stats; it contains
only counts, method, timestamps and the public report URL. Sharing authorization
and application/module state are checked on every call. Revocation is immediate
at SaaS Pro; a consuming site may keep its prior result for its documented cache
window. No ingest or management key is exposed by a public report.
Integration requirements#
Implement the visitor-facing notice and applicable lawful basis for your service. Respect user opt-outs, DNT/GPC as configured, exclude private routes and fields, and keep this stream separate from consented analytics. Do not expose the server key, trust browser-supplied addresses, or forward entire request headers.
What the assistant can do here#
The connector and console assistant can inspect collection through
GET /api/v1/apps/{app}/cookieless/status?env=production, read the report through
/cookieless/report?env=production&range=30d, and read server integration
requirements through /cookieless/install?env=production. MCP exposes
get_cookieless_status, get_cookieless_report and
get_cookieless_install_instructions. Status and reports require
analytics.read; installation requirements require apps.read. Reports also
require Analytics to be enabled, and page breakdowns require people.pii.read.
No secret keys, visitor hashes or raw network metadata are returned.
There is no tracking toggle. not_received means no cookieless data has reached
that app/environment; receiving means activity within the retained last
24 hours; previously_received means lifetime evidence exists without recent
activity. A key or enabled module alone does not prove installation. Browser
SDK cookieless: true (local storage) and privacyMode: ephemeral (memory-only
identity) do not populate this separate report.