Cookieless tracker reference (pa.js)
How the cookieless pa.js tracker works and when it sends nothing, with links to every script attribute, the JavaScript API, modules, SPA support and debugging.
pa.js is the browser tracker. It's open source (MIT), a few kilobytes,
and it:
- sends one small request per pageview or event to
https://privatusanalytics.com/api/event, and retries it a few times if the server answers with an error, - uses no cookies,
localStorage,sessionStorage, IndexedDB or fingerprinting APIs (canvas, WebGL, fonts, audio, battery). The one exception is the opt-out flag a visitor sets themselves, - makes no request to any third party.
<script defer src="https://privatusanalytics.com/js/pa.js" data-site="pa_YOURSITEID"></script>
Reference#
- Script attributes: every
data-option. - JavaScript API:
track,pageview,props,optOut,readyand the queue stub. - Modules:
engage,auto,vitals,clicks. - Single-page apps and manual mode.
- Exclusions, masking and URLs: domains, excluded paths, masks, query parameters, canonical URLs, hash routing.
- Debug mode, CSP, versioning and SRI, opt-out.
- What the tracker sends: the exact request body.
When the tracker sends nothing#
The tracker stays silent (and says why in the console with
data-debug="true") when:
| Reason | Details |
|---|---|
missing data-site |
The script tag has no data-site |
opted out |
The visitor opted out in this browser |
localhost |
The page is on localhost, 127.*, [::1], 0.0.0.0, a .local host or file://, and neither data-debug nor data-allow-local is set |
domain not in data-domains |
You set data-domains and this hostname isn't in it |
automated browser |
navigator.webdriver is set, or PhantomJS, Nightmare or Cypress is detected |
| excluded path | The path matches data-exclude |
It also waits for a prerendered page to become visible before sending
anything (prerenderingchange), and sends a fresh pageview when a page is
restored from the back/forward cache.
Open source#
The tracker source, tests and build are public. Every file starts with a comment naming Privatus Analytics: we don't disguise the script or offer ways to hide it from blockers. See Ad blockers.
Every data- attribute the pa.js tracker reads from its script tag, with defaults and examples for modules, SPA mode, domains, exclusions and masks.
Tracker JavaScript API reference: track custom events, send pageviews, add properties to every hit, opt out, use ready() and queue calls before pa.js loads.
Load optional tracker modules for time on page and scroll depth, automatic outbound link, download, form and 404 events, Web Vitals and aggregate click maps.
How the tracker follows single-page app navigation with the History API or hash routing, what counts as a new page, and how to avoid counting pageviews twice.
Turn off the automatic pageview with data-manual and send pageviews yourself with privatus.pageview(), for example after reading an A/B test variant at runtime.
Exclude pages and mask URLs in the browser: control which hostnames and paths are tracked and which URL is recorded, including query parameters.
Use tracker debug mode to log every hit to the console without sending it, send real hits from localhost, and check the /api/event request in your dev tools.
The Content Security Policy directives the analytics tracker needs (script-src, connect-src and img-src), plus the setup for nonces.
How the hosted pa.js tracker is updated, and how to self-host a pinned copy with a Subresource Integrity (SRI) hash when your security policy requires it.
Let visitors opt out of analytics with privatus.optOut(), the only flag the tracker stores, and exclude your own visits by browser, IP range or WordPress.
The exact POST request the tracker sends to /api/event, every field in its JSON payload, and what is never sent: no cookies, identifiers or fingerprints.