@zenovay/tracker
v0.1.0
Published
Thin npm wrapper around the Zenovay analytics tracking script. Drop-in replacement for the <script> tag install.
Maintainers
Readme
@zenovay/tracker
A tiny (~1 KB) npm wrapper around the Zenovay analytics tracking script. Lets you npm install and import the tracker instead of pasting a <script> tag — without forking the tracker source.
The existing
<script>tag install method continues to work exactly as before. This package is an additional, optional installation surface, not a replacement.
Why a wrapper, not a fork
The canonical Zenovay tracker is a single, frequently-updated bundle served from https://api.zenovay.com/z.js. This package does not vendor that source; it injects the same <script> tag at runtime and proxies calls onto window.zenovay. That means:
- You always get the latest production tracker, automatically.
- The bundle this package adds to your app is just a few hundred bytes.
- Migrating between the script tag and the npm install is a no-op — the wire format is identical.
Install
npm install @zenovay/tracker
# or:
pnpm add @zenovay/tracker
yarn add @zenovay/trackerUsage
import { init, track, identify, page, goal, revenue } from '@zenovay/tracker';
// Run once, as early in your app as possible (typically on first mount).
init('YOUR_TRACKING_CODE');
// Track events
track('Signup clicked', { source: 'hero' });
// Identify a logged-in user
identify('user_123', { email: '[email protected]' });
// Fire a pageview on client-side navigation (the tracker auto-fires the
// initial pageview; you only call page() on subsequent route changes)
page();
// Mark a goal
goal('purchase', { value: 99, currency: 'USD' });
// Revenue
revenue(99, 'USD', { product_id: 'pro-monthly' });Framework examples
- Next.js (App Router) — see
examples/nextjs.tsx - Nuxt 3 — see
examples/nuxt.vue - SvelteKit — see
examples/sveltekit.svelte - Plain HTML — the script-tag install is simpler; see
examples/plain-html.html
API
init(trackingCode, options?)
Inject the tracker into the page. Calling init more than once is a no-op. You can call any of the helper functions (track, page, etc.) before init — they queue and replay once the tracker loads.
| Option | Type | Default | Notes |
|---|---|---|---|
| apiUrl | string | 'https://api.zenovay.com' | Override for first-party proxying. |
| scriptUrl | string | ${apiUrl}/z.js | Full URL of the loader script. |
| debug | boolean | false | Verbose console logging. |
| allowLocalhost | boolean | false | Fire on localhost / 127.0.0.1. |
| allowFile | boolean | false | Fire on file:// URLs. |
| cookieless | boolean | false | Disable cookies + localStorage. |
| silent | boolean | false | Suppress all logging, even in debug. |
| heartbeat | boolean | true | Periodic session-metric heartbeat. |
| trackOutbound | boolean | true | Auto-track outbound link clicks. |
| sessionTimeoutMinutes | number | 30 | Session timeout. |
| cookiePrefix | string | 'zenovay' | Cookie / storage key prefix. |
| attachTo | HTMLElement \| null | document.head | Where to inject the script. |
These options map 1:1 onto the data-* attributes documented in the script-tag install — see the Zenovay docs for the canonical list.
Helpers
| Function | Maps to window.zenovay(...) |
|---|---|
| track(name, props?) | ('track', name, props) |
| page() | ('page') |
| identify(userId, traits?) | ('identify', userId, traits) |
| goal(name, params?) | ('goal', name, params) |
| funnel(funnelId, step, stepName?) | ('funnel', funnelId, step, stepName) |
| defineFunnel(name, steps) | ('defineFunnel', name, steps) |
| revenue(amount, currency, metadata?) | ('revenue', amount, currency, metadata) |
| disable() | ('disable') |
| enable() | ('enable') |
| debug() | ('debug') |
All helpers are safe to call before init — they queue and drain.
Module formats
This package ships dual ESM + CJS builds with TypeScript declarations:
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
}
}Bundle size: under 2 KB minified for the wrapper itself. The actual tracker (loaded async from api.zenovay.com/z.js) is unchanged regardless of how you install.
SSR
Functions are SSR-safe. init and helpers no-op when window is undefined, so calling them in shared code that runs on both server and client is fine.
Idiomatically, framework examples call init from a client-only effect (useEffect, onMount, import.meta.client) — see the examples directory.
Migrating from the script tag
The npm install and the script-tag install are interchangeable. If you have:
<script
defer
data-id="YOUR_TRACKING_CODE"
data-allow-localhost="true"
src="https://api.zenovay.com/z.js"
></script>You can replace it with:
import { init } from '@zenovay/tracker';
init('YOUR_TRACKING_CODE', { allowLocalhost: true });Both forms produce identical network behavior.
Publishing checklist (maintainers only)
This package ships at version 0.0.1 with "private": true set so accidental publishes are blocked. To release:
- Confirm
pwdistracker-zenovay/(never publish from the wrong cwd). - Bump
versioninpackage.json. - Remove
"private": true. npm run build && npm pack --dry-run— confirm the tarball contains onlydist/,README.md, andLICENSE. Never publish ifsrc/orexamples/show up.npm publish --access public --provenance.- Tag the release:
git tag v0.1.0 && git push --tags. - Smoke-test: in a fresh project,
npm install @zenovay/trackerand confirmimport { init } from '@zenovay/tracker'works in both an ESM and a CJS context.
Re-add
"private": trueafter publishing if you want the next session not to accidentally re-publish.
