@privatrak/nuxt
v1.0.0
Published
Nuxt module for Privatrak analytics: cookieless, privacy-first tracking that auto-captures pageviews, clicks and form submissions without a consent banner.
Maintainers
Readme
@privatrak/nuxt
Nuxt module for Privatrak, a privacy-first product
analytics service. Add it to modules, give it your project key, and your Nuxt
app starts reporting pageviews — including every client-side route change —
along with clicks and form submissions, without a single track() call in your
components. It sets no cookies, writes nothing to localStorage or
sessionStorage, does no browser fingerprinting, and never reads what a visitor
typed into a form, so there is no consent banner to show and no cookie policy to
write. Visitors are counted server-side from an irreversible daily hash.
The module is a thin Nuxt wrapper: a client-only plugin, an auto-imported
useTracker() composable, and a typed tracker config block. The tracking
itself is @privatrak/tracker,
which comes along as a dependency.
Installation
npm install @privatrak/nuxtNuxt 3 or newer. Nothing else to install — the core tracker is a dependency of this package, not a peer you have to remember.
Quick start
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@privatrak/nuxt'],
tracker: {
apiKey: 'stk_your_project_key',
apiHost: 'https://api.privatrak.com',
},
});That is the whole setup. Start the app and pageviews arrive; navigate and the next one arrives; click a link or submit a form and those arrive too.
Your project key is in the Privatrak dashboard under Settings → API Keys. It
is a public, write-only key and is meant to ship in client code — the module
puts it in runtimeConfig.public.tracker, so you can still override it per
environment with NUXT_PUBLIC_TRACKER_API_KEY rather than rebuilding.
Label the things you want to see as features, in markup:
<template>
<button data-track="signup-cta" data-track-plan="pro">Sign up</button>
</template>…or record an event from code with the composable, which is auto-imported:
<script setup lang="ts">
const { track, setTraits } = useTracker();
function onCheckout(): void {
track('checkout-completed', { plan: 'pro' });
}
// Label the session so the dashboard can segment by it.
setTraits(['paid', 'admin']);
</script>Configuration
The tracker block accepts every option the core tracker takes. Only apiKey
is required; anything you leave out follows your project's settings from the
dashboard, which the tracker fetches at startup.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| apiKey | string | — | Project API key. Required; without it nothing is sent. |
| apiHost | string | the app's own origin | Base URL of the Privatrak API, e.g. https://api.privatrak.com. Set it unless the API answers on the same origin as the app. |
| autocapture | boolean | true | Record clicks and form submissions automatically. |
| autocapturePageviews | boolean | true | Record pageviews, including client-side route changes. |
| autocaptureElements | string[] | a, button, input[type=submit], plus ARIA roles such as [role=button], [role=menuitem], [role=tab] | Selectors treated as interactive click targets. |
| walkDepth | number | 3 | How many ancestors to walk up when looking for an interactive element or a data-track label. |
| maxTextLength | number | 100 | Element text is truncated to this many characters. |
| flushIntervalMs | number | 5000 | How often the queue is sent. |
| maxQueueSize | number | 10 | Queue length that triggers an immediate send. |
| piiUrlParams | string[] | ['email', 'token', 'key', 'password', 'secret'] | Query parameters whose values are replaced with :redacted before the URL is sent. |
| piiPathPatterns | string[] | [] | Regular expressions whose matching path segments are replaced with :redacted. |
| normalizePathIds | boolean | true | Collapse ID-shaped path segments to :id, so /orders/4711 and /orders/4712 are one page. |
| excludedUrls | string[] | [] | URL patterns that are not tracked at all. |
| samplingRate | number | 1.0 | Fraction of visitors recorded, from 0 to 1. |
| traits | string[] | [] | Session labels attached to every event — see setTraits(). |
The block is typed as TrackerInitConfig, so an unknown key or a wrong type is
an error in nuxt.config.ts rather than a setting that silently does nothing.
API
The module
modules: ['@privatrak/nuxt'], configured under the tracker key. It merges
that block into runtimeConfig.public.tracker, registers a client-only plugin
that calls the tracker's init() once the app starts, and registers the
useTracker auto-import. Nothing runs during server-side rendering.
useTracker()
Auto-imported in components, composables and plugins. Returns:
| Member | Signature | Description |
|--------|-----------|-------------|
| track | (name: string, attrs?: Record<string, string>) => void | Records a custom event. name is the feature label you will see in the dashboard; attrs is the same idea as data-track-* attributes in markup. |
| setTraits | (traits: string[]) => void | Labels the current session with your own strings — ['paid', 'trial'], a plan name, a feature-flag bucket — which every subsequent event carries and the dashboard can filter and break down by. At most 50, 64 characters each. |
Both are safe to call from code that also runs on the server: they do nothing there.
Package exports
import type { TrackerInitConfig } from '@privatrak/nuxt';
import { version } from '@privatrak/nuxt';TrackerInitConfig is the shape of the tracker block. version is this
module's version, worth quoting in a bug report.
Privacy
The reason to choose this over the alternatives, so it is worth being specific.
- No cookies and no storage. Nothing is written to
document.cookie,localStorageorsessionStoragewhile tracking. There is no device identifier, which is why no consent banner is required for it. - No fingerprinting. No canvas, WebGL or AudioContext probing, no navigator enumeration.
- Visitors are counted server-side. The API derives a session ID from
HMAC(IP + User-Agent + project, daily key)and stores only that hash — raw IP and User-Agent are never written down. The key rotates at midnight in the project's timezone, so yesterday's sessions cannot be linked to today's. It is the model Plausible Analytics uses, which CNIL has found acceptable without consent. - Form values are never captured. Not opt-in, not redacted afterwards — the tracker does not read them. Password fields, hidden fields and credit-card inputs are skipped entirely.
- URLs are cleaned in the browser before the event is sent, using
piiUrlParams,piiPathPatternsandnormalizePathIds.
More detail, and the data processing terms, are at privatrak.com/privacy.
Links
- Privatrak — the product this reports into
- How it works · Features · Pricing
@privatrak/tracker— the core tracker, for apps that are not Nuxt, and the reference for what each event contains- Contact — questions and bug reports
Versioning and license
This package is versioned independently of the core tracker and of the hosted
product. Changes are recorded in CHANGELOG.md, shipped in the package.
Released under the MIT license (LICENSE).
