Tracker API
Everything the browser tracker understands: the attributes on its script tag and the five commands it takes. There’s no other surface.
Updated
Script attributes
<script async src="https://app.clickclacks.io/c.js" data-key="pk_live_3f9a1c7e5b2d4f6a8c0e1b3d" data-domains="acme.com,www.acme.com,app.acme.com"></script>| Attribute | Meaning | |
|---|---|---|
src | Required | https://app.clickclacks.io/c.js, or https://<your custom domain>/c.js. Events go to the same origin the script loads from. |
async | Recommended | Loads without blocking the page. |
data-key | Required | The source’s browser key, pk_live_…. Without it the tracker does nothing. |
data-domains | Required | Comma-separated hostnames the tracker may run on, matched exactly and case-insensitively. Links between them carry identity. |
data-query | Optional | off sends page paths and campaign data without the query string. |
data-capture | Optional | off stops heatmap captures from this page. Events are unaffected. |
nonce | Optional | Your CSP nonce. Passed on to the heatmap helper the tracker loads. |
The tracker reads these from its own tag when it starts, and only starts when the page’s hostname is in data-domains, data-key is set, and browser storage works. Otherwise window.clickclacks is never defined.
Commands
window.clickclacks(command: string, ...args): void- Every command returns
undefinedand never throws. A call with the wrong arguments, or an unknown command, is ignored. - While the visitor is opted out, every command except
optInandoptOutis ignored. reset,optOutandoptInare also methods:clickclacks.reset().
event
clickclacks('event', 'Report exported', { format: 'csv', rows: 1200 })- name: a string of 1–128 characters, not starting with
$. - properties (optional): a plain object. Functions and
undefinedvalues are dropped. Over 2 KB of JSON, the event is sent without them. - The page is added as
path: the pathname only, never the query string or#fragment. Reports read it as Page. Pass your ownpathand yours is kept. - After
identify, the ID is added as$distinct_id.
Events sent from your servers (the API and the SDKs) carry no page. Add path to their properties if you want one.
Guide: Custom events.
identify
clickclacks('identify', 'user_4821', { plan: 'pro' })- id: a string of 1–128 characters, your own user ID.
- traits (optional): a plain object, same rules as event properties. Over 2 KB, only the ID is sent.
- Sends a
$identifyevent withdistinct_idand the traits, and saves the ID for later events in this browser. - Links this browser to anyone who identified with the same ID elsewhere.
$identifyevents are free.
Guide: Identify people.
reset
clickclacks('reset') // or clickclacks.reset()Forgets the identified ID, drops events not sent yet, and starts a new anonymous ID and session. Tracking continues. Call it on sign-out.
optOut
clickclacks('optOut') // or clickclacks.optOut() Drops events not sent yet, deletes the tracker’s IDs, stops all tracking, and remembers the choice (cco) so it holds on later page loads on this hostname.
optIn
clickclacks('optIn') // or clickclacks.optIn()Forgets the opt-out and resumes tracking with new IDs. Counts the current page if the opt-out stopped it being counted. Guide: Consent and opt-out.
The call queue
If window.clickclacks.q is an array when the tracker starts, each entry (an arguments list) is replayed in order, before the first pageview. That lets you call the tracker before it has loaded:
<script>
window.clickclacks = window.clickclacks || function () {
(window.clickclacks.q = window.clickclacks.q || []).push(arguments)
}
</script>Browser storage
No cookies. Everything is in the page’s own origin, so each hostname has its own copy.
| Key | Where | Holds |
|---|---|---|
ccp | localStorage | The browser’s anonymous ID, per_ + 32 hex characters. |
cci | localStorage | The ID passed to identify. |
cco | localStorage | 1 while the visitor is opted out. |
_cc_cap | localStorage | Markers for heatmap captures already taken from this browser. |
ccs | sessionStorage | The session ID, ses_ + 32 hex characters. |
ccl | sessionStorage | When the session was last active. After 30 minutes without an event, the next one starts a new session. |
ccc<key> | sessionStorage | The source’s heatmap and click-capture settings, cached for the tab. |
Network requests
| Request | What for |
|---|---|
GET /c.js | The tracker, from app.clickclacks.io or your custom domain. |
POST /api/ingest?key=… | Event batches, to app.clickclacks.io. On a custom domain: POST /e?key=…. Sent as text/plain JSON, without credentials. |
GET /api/heatmap-config?key=… | The source’s capture and click settings, to app.clickclacks.io. Cached for the tab session, and asked again only on pages that may still need a capture. |
GET /heatmap-screenshot.js | Only when this browser is asked to take a heatmap capture, from the same origin as c.js. |
POST /api/heatmap-capture?key=… | A masked heatmap capture, to app.clickclacks.io. |
Events are batched: sent every 5 seconds, as soon as 25 are waiting, and when the page is hidden or closed. A failed batch is kept and retried with the next one, up to 100 waiting events.
Browser support
The tracker is a small ES5 script with no dependencies. It needs URL, localStorage and sessionStorage, which every current browser has. It sends with fetch and keepalive, falling back to sendBeacon. Where storage is blocked it stays off rather than break your page.