Privatrak

Documentation

Learn how to use the tracking tool

Watch the video seriesEight short videos covering the whole product, on YouTube.Opens in a new tab

Custom Events

Page views, clicks and submitted forms are recorded for you. Everything else is a custom event: the things that matter to your product but do not line up with somebody clicking something — a payment that went through, a video watched to the end, an import that failed halfway. There are two ways to record one. An HTML attribute names something already on the page and needs no JavaScript. The track() function records something with no element behind it.

What you can use it for

  • Record what you actually care about: not the click on “Pay”, but the payment that succeeded, sent from the code that knows it did.
  • Measure what has no element: a search that returned nothing, a video reaching the end, a filter applied in a component that never reloads the page.
  • Count the actions that are yours alone: a project created, a teammate invited, a report exported.

HTML attributes

Put a data-track attribute on an element and its clicks get a name. There is nothing to wire up: the tracker is already listening to the whole page.

Naming something with data-track

The attribute’s value becomes the name. An element carrying data-track is recorded even when click auto-capture is switched off, which is how you record a handful of things without recording everything.

<button data-track="signup-cta">Sign Up Free</button>

Adding detail with data-track-*

These become the event’s attributes. The prefix is dropped, so data-track-plan="pro" arrives as plan: pro, and you can add as many as you like. They land in the same data_track_attrs field as the attrs object you pass to track() — the values you filter and break down by afterwards. They have to sit on the same element as data-track itself. One on a child element is not collected.

<button
  data-track="pricing-cta"
  data-track-plan="pro"
  data-track-interval="yearly"
>
  Upgrade to Pro
</button>

Clicking the icon inside the button

People click the label or the icon, not the button. When a click lands on something with no name of its own, the tracker looks outwards from it and uses the first data-track it finds. It looks three levels up by default, which data-walk-depth changes. One attribute on a container therefore names every click inside it, and you never have to mark up the icon.

<div data-track="feature-card" data-track-feature="analytics">
  <h3>Analytics</h3>
  <p>Track your metrics</p>
  <button>Learn more</button>  <!-- click here inherits data-track -->
</div>

The track() method

window.tracker.track() is there on every page the script is on. It takes two arguments:

  • name (string, required): what the event is called. Stored as data_track, the same field a data-track attribute fills — so a custom event and a tagged click can be the same feature.
  • attrs (object, optional): extra values as text. They go into data_track_attrs, the same field data-track-* attributes fill.

An example

// Track a simple event
window.tracker.track("signup-completed");

// Track an event with attributes
window.tracker.track("plan-upgraded", {
  plan: "pro",
  interval: "yearly"
});

What happens to a custom event

The tracker builds an event with the type custom, the page you are on and the current time, then puts it in the same queue as everything else. It travels in the same batches and carries the same session. A call with an empty name does nothing at all, and does it quietly — so check the name if it comes out of a variable.

Session traits

window.tracker.setTraits(["plan:pro", "role:admin"]) attaches traits to the visitor rather than to one event, and everything sent afterwards carries them. They are what the traits filter on the dashboard narrows by. The call replaces the list rather than adding to it, so pass the complete set each time. Nothing is kept in the browser, so every page load starts with no traits until you set them again.

window.tracker.setTraits(["plan:enterprise", "role:admin"]);

Which to use

Use a data-track attribute when:

  • The thing is an element somebody clicks
  • People who do not write JavaScript should be able to add tracking
  • You want it visible in the markup, next to what it measures

Use track() when:

  • Nothing was clicked — a timer, a background request, a payment that failed
  • The values are only known while the page is running
  • It should only count once something succeeded, after validation or in a callback

Use the Element Picker when:

  • You cannot change the site’s code, or not this week
  • Somebody non-technical has to set it up
  • The element is already on the page and only needs a name — see No-Code Tracking

When track() starts working

The window.tracker object exists as soon as the script has run, but nothing is collected until the tracker has initialised. With the defer script tag we recommend, those two moments are the same, so you can call track() straight away. Put the tag in the page head without defer and initialisation waits until the page has finished parsing. A track() call made before that point is dropped silently — it is not queued and nothing is reported. Use the recommended snippet, or make your first call after initialisation.

Starting the tracker yourself

data-manual-init on the script tag stops the tracker starting on its own: nothing is recorded, not even the first page view, until you call window.tracker.init(config). The first page view is delayed rather than lost: init() records one as it runs, for whichever page the visitor is on at that moment. Start the tracker after a client-side navigation and that later page is the one counted. Use it when the settings are only known while the page is running — waiting on a consent decision, reading a key out of your own configuration. The Tracker Reference lists everything the config takes.

<script src="https://api.privatrak.com/tracker.js" data-manual-init defer></script>
<script>
  window.tracker.init({
    apiKey: "your-public-key",
    apiHost: "https://api.privatrak.com",
    autocapture: false
  });
</script>

Examples

// After a successful purchase
window.tracker.track("purchase-completed", {
  plan: "starter",
  amount: "29"
});

// Feature toggle usage
window.tracker.track("feature-toggled", {
  feature: "dark-mode",
  enabled: "true"
});

// Search performed
window.tracker.track("search", {
  query: "pricing",
  results: "5"
});

Never put a person’s identity in an attribute

Attribute values are stored exactly as you send them. Nothing is shortened, hashed, or checked on the way in, so whatever you put in an attribute is what anyone who can query your data reads back.

Do not send anything that points at one individual. That means account IDs, user IDs, email addresses, usernames, phone numbers, order numbers, and hashes of any of those. A hashed user ID is still a per-person value: the same person gets the same hash every time, which is all it takes.

This matters because it undoes the property you are presumably here for. Privatrak never stores an IP address or a user agent, and the session ID it derives is rebuilt from a new key every night, so a visitor’s activity cannot be joined up across days. One stable per-person attribute puts that link straight back: sessions can be stitched together and a single person’s whole history reconstructed from the events.

A simple test

  • Good: a value drawn from a short, fixed list that many people share: plan: "pro", interval: "yearly", result: "error", step: "3".
  • Bad: a value that is different for nearly every event or belongs to one account: user_id: "4711", email: "ada@example.com", cart_id: "c_8f3a...", uid_hash: "9b1c...".

If you want to compare groups of people, send the group and not the member: plan: "pro" tells you what you wanted to know, and account_id does not tell you any more than that while making everyone traceable.

This applies to every attribute

It makes no difference which way you set one. A data-track-* attribute and the attrs object end up in the same field, and the rule is the same for both.

The PII controls under Privacy & Security do not help here. They clean up URL path segments and URL parameters only, and they run inside the tracker before the event is sent, so a modified or hand-written client skips them entirely. Attributes are never inspected.

Finding them again

Custom events sit on the Events page with everything else. Filter by the type custom to see only yours, then narrow further by the name or by any attribute you attached. The counts at the top of that page include one for custom events, which is the quickest way to confirm that a new call is arriving at all.

Related documentation

Tracker Reference lists every setting and function in one place. To name elements without touching code at all, see No-Code Tracking.

Custom Events and Session Traits – Privatrak Tracking Guide