Tracker API
Everything the browser tracker understands: the attributes on its script tag and the six 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" data-consent="opt-out" data-respect-gpc="on"></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-consent | Optional | opt-out (the default, also when absent) starts tracking on load. opt-in waits for optIn. |
data-respect-gpc | Optional | on keeps tracking off, and makes optIn do nothing, while the browser sends Global Privacy Control. |
data-query | Optional | off sends page paths and campaign data without the query string. |
data-click-text | Optional | off records no text for clicked links and buttons. |
data-carry-identity | Optional | off neither adds _ccid to links between your domains nor reads it on arrival. |
data-capture | Optional | off stops heatmap captures from this page. Events are unaffected. |
data-mask | Optional | strict masks all text and leaves out images in heatmap captures. |
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, keeping onlypath. - 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. Aftergroup, the groups are added as$groups.
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.
group
clickclacks('group', 'company', 'cmp_311', { name: 'Acme', plan: 'pro' })
clickclacks('group', 'company', null) // leave the group- type: 1–64 lower-case letters, digits or underscores, such as
company. - id: a string of 1–255 characters (numbers become strings), or
nullto leave the group. - traits (optional): a plain object describing the group. Sends a
$group_identifyevent, which is free. Traits that look personal, such as an email or phone number, are dropped unless the source allows them. - The browser remembers one ID per type, at most 5 types, and adds them to every later event as
$groups, such as{ "company": "cmp_311" }.
Guide: Companies and groups.
reset
clickclacks('reset') // or clickclacks.reset()Forgets the identified ID and groups, 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, cancels retries and heatmap captures in progress, deletes the tracker’s IDs, groups and capture markers, removes the _ccid it added to links, and stops all tracking. It remembers the choice (cco) so it holds on later page loads on this hostname, and other open tabs on the same hostname stop too.
optIn
clickclacks('optIn') // or clickclacks.optIn() Forgets the opt-out and resumes tracking with new IDs. Counts the current page if it wasn’t counted yet. In opt-in mode this is the call that starts tracking, and it applies to the current tab only. It does nothing while data-respect-gpc="on" and the browser sends Global Privacy Control. 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. |
ccg | localStorage | The groups set with group, one ID per group type. |
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.