Developer reference

Tracker & snippet

Everything the Trafnova tracker (t.js) does and every attribute you can set on the install tag. One static file, no cookies, no consent banner required by default - but every knob you need for SPAs, custom events, content dimensions, privacy gating, and keeping staging traffic out is here.

On this page

Install

Paste this into the <head> of every page you want to track:

<script>window.tn=window.tn||function(){(window.tn.q=window.tn.q||[]).push(arguments)}</script>
<script defer data-token="YOUR_SITE_TOKEN" src="https://cdn.trafnova.com/t.js"></script>

Your token is on the site's Install card in the dashboard. The first line is a tiny stub so any tn() call you make before the deferred tracker finishes loading is buffered and replayed (nothing lost on early events). The script is served first-party from the CDN (or your own CNAME), respects navigator.doNotTrack, and ships a stable v: "x.y.z" version on every payload so you can spot a stale cache.

What is tracked automatically

With just the snippet above (no extra config) the tracker collects:

Don't call POST /api/v1/event yourself. The collector is an implementation detail of t.js (cookieless session id, dwell beacons, batched queue, bot signals). Use the snippet and the tn() API below.

Custom events

The tracker exposes a global tn() function once loaded:

// fire a custom event with optional properties (<= 2KB JSON)
tn('event', 'Signup', { plan: 'pro', source: 'hero' });

// manually trigger a pageview - escape hatch for SPA routers that
// don't go through history.pushState
tn('pageview');

Custom events show up in the dashboard's Custom event properties breakdown.

Declarative event tagging

No JavaScript required - tag any element and the tracker fires the event on click:

<button data-tn-event="Signup" data-tn-event-plan="pro">Sign up</button>

data-tn-event is the event name; every data-tn-event-<key> attribute becomes a property (dashes kept: data-tn-event-plan-typeplan-type). A click on a child element still finds the tagged ancestor. If the tagged element is also an outbound link or download, its URL (and file extension) is folded into the event's props instead of firing a second event - so a tagged "Buy" button that points at Stripe is one conversion, not two.

Pageview dimensions (custom properties)

Segment your content by author, category, plan, anything - declare <meta> tags and they attach to the pageview:

<meta name="tn:author" content="Jane Doe">
<meta name="tn:category" content="Engineering">

Every name="tn:KEY" meta becomes a property {KEY: content} on the pageview. They are re-read on each SPA navigation, so a router that swaps the meta tags per route reports the right dimensions. These surface in the dashboard's Custom dimensions card.

Restrict tracking to specific hostnames

Running the same snippet on staging or localhost? Keep that traffic out of your stats with an allowlist:

<script defer data-token="YOUR_SITE_TOKEN"
        data-domains="example.com,www.example.com"
        src="https://cdn.trafnova.com/t.js"></script>

When data-domains is present the tracker only runs if the current location.hostname is in the comma list (case-insensitive). Absent = track everywhere (default).

Exclude specific paths

Drop pageviews and events on admin / checkout / internal routes:

<script defer data-token="YOUR_SITE_TOKEN"
        data-exclude="/admin/**, /checkout"
        src="https://cdn.trafnova.com/t.js"></script>

Glob patterns: * matches within a single path segment, ** matches across segments. So /admin/** excludes /admin/users/42, while /blog/* excludes /blog/post but not /blog/2026/post. Re-evaluated on each navigation, so an excluded route in a SPA is dropped while the rest of the app is tracked.

Manual-only mode

Want full control? Turn off automatic collection and fire everything yourself with tn():

<script defer data-token="YOUR_SITE_TOKEN"
        data-auto-track="false"
        src="https://cdn.trafnova.com/t.js"></script>

data-auto-track="false" loads the tracker and keeps the tn() API but wires none of the automatic collectors (initial pageview, SPA hooks, outbound / download / form / tagging clicks). You call tn('pageview') and tn('event', ...) when you want.

Privacy / consent hook

Gate sending on cookie consent, or scrub PII out of payloads, with a function the tracker calls before every send:

<script defer data-token="YOUR_SITE_TOKEN"
        data-before-send="tnBeforeSend"
        src="https://cdn.trafnova.com/t.js"></script>
<script>
  window.tnBeforeSend = function (payload) {
    if (!window.userAcceptedAnalytics) return null;  // consent gate: drop the event
    delete payload.referrer;                          // PII scrub: strip a field
    return payload;                                   // send the (mutated) payload
  };
</script>

window.<fnName>(payload) is called before each send, including the engagement beacon. Return the (optionally mutated) payload to send it, or a falsy value to cancel. A hook that throws is treated as pass-through, so a bug can't silently kill all your analytics.

Excluding yourself & specific forms

Keep your own visits out of the stats without touching the server - run this once in your browser console, or visit any page with ?tn_ignore=true:

localStorage.setItem('tn_ignore', 'true');   // sticky, this device only
// or visit: https://example.com/?tn_ignore=true   (?tn_ignore=false clears it)

To stop auto-tracking a single form's submission, add data-tn-skip to it:

<form data-tn-skip> ... </form>

Attribute reference

AttributeOnWhat it does
data-tokenscriptYour site token (required).
data-domainsscriptComma list of hostnames to track on. Absent = everywhere.
data-excludescriptComma list of path globs (* / **) to drop.
data-auto-trackscript"false" disables all automatic collection (manual tn() only).
data-before-sendscriptName of a window function called before each send; mutate or cancel.
data-tn-eventany elementFires a named custom event on click; data-tn-event-* become props.
data-tn-skipformSkip auto-tracking this form's submit.
name="tn:KEY"metaAttaches {KEY: content} as a pageview dimension.

Prefer the HTTP API for pulling data back out? See the API reference. Missing something? Tell us.