Skip to content
Start free in Cloud

HitKeep NPM Package for React, Vue, Angular, and Astro

Script tags are awkward in component frameworks: they live outside the bundler, they offer no types, and every custom event becomes an unchecked window.hk?.event?.() call. @hitkeep/tracker packages the same tracker that ships as hk.js — built from the same source, with the same privacy behavior — as a fully typed ES module.

Terminal window
npm install @hitkeep/tracker

The package is published on npm as @hitkeep/tracker and released in lockstep with HitKeep itself.

import { init, track } from '@hitkeep/tracker';
init({ host: 'https://your-hitkeep.example' });
track('signup_clicked', { plan: 'pro' });

host is the origin (or mounted path prefix) your HitKeep instance serves the tracker from — the same URL the hk.js snippet would load from, including custom tracking domains. The tracker derives /ingest, /ingest/event, and /ingest/web-vitals from it.

Pageviews are captured automatically on init, including history-based SPA navigations, so none of the frameworks below need router wiring. Events tracked before init runs are queued in memory and flushed once the tracker starts. The package is published with every HitKeep release and its version matches the product version.

Initialize once in a client-side module. In a Vite or CRA-style app, the app entry is fine:

main.tsx
import { init } from '@hitkeep/tracker';
init({ host: 'https://your-hitkeep.example' });

In Next.js, init must run in the browser, so use a client component mounted in the root layout:

app/analytics.tsx
'use client';
import { useEffect } from 'react';
import { cleanup, init } from '@hitkeep/tracker';
export function Analytics() {
useEffect(() => {
init({ host: 'https://your-hitkeep.example' });
return cleanup;
}, []);
return null;
}

Route changes are tracked automatically through history patching. Track custom events from any component:

import { track } from '@hitkeep/tracker';
<button onClick={() => track('cta_clicked', { location: 'hero' })}>Get started</button>

Every option maps to a snippet data attribute where one exists. Defaults match the snippet’s behavior.

init({
host: 'https://your-hitkeep.example', // required
autoCapturePageviews: true,
autoTrackSpaNavigation: true,
outboundLinks: true,
fileDownloads: true,
formSubmissions: true,
webVitals: false,
useBeacon: true,
respectDoNotTrack: true,
captureOnLocalhost: false,
bindToWindow: true
});
Option Default Snippet equivalent Effect
host script src origin HitKeep origin or path prefix that receives pageviews, events, and Web Vitals
autoCapturePageviews true always on Send a pageview when init runs
autoTrackSpaNavigation true data-disable-spa-tracking Track history-based route changes as pageviews
outboundLinks true data-disable-outbound-tracking Automatic outbound_click events
fileDownloads true data-disable-download-tracking Automatic file_download events
formSubmissions true data-disable-form-tracking Automatic form_submit events
webVitals false data-enable-web-vitals Load ${host}/hk-vitals.js and send opt-in Web Vitals samples
useBeacon true data-disable-beacon Prefer navigator.sendBeacon() with keepalive fetch fallback
respectDoNotTrack true data-collect-dnt Drop tracking when the browser sends DNT: 1
captureOnLocalhost false none Track on localhost and 127.0.0.1, which are blocked by default
bindToWindow true always on Expose window.hk.event for snippet-compatible callers
trackerSource @hitkeep/tracker data-hitkeep-source Attribution source reported with every request

All functions are exported from the package root with full TypeScript declarations.

function init(config: TrackerConfig): TrackerHandle;
function track(name: string, properties?: Record<string, unknown>): void;
function trackPageview(): void;
function cleanup(): void;
  • init starts the tracker and returns a handle with track, trackPageview, and cleanup. It is idempotent: a second call — or a call on a page where the hk.js snippet already bootstrapped — logs a debug notice and does not double-track.
  • track records a named event with optional properties. Calls made before init are queued in memory and flushed on init.
  • trackPageview sends a manual pageview, for use with autoCapturePageviews: false.
  • cleanup removes all listeners, restores the patched history methods, and allows re-initialization. Useful for hot module replacement and test teardown.

The bundled tracker ships inside your application bundle instead of loading from your analytics host, so content blockers do not filter it. Offer visitors an explicit opt-out:

function blockTrackingForMe(): void;
function enableTrackingForMe(): void;
function isTrackingEnabled(): boolean;

The opt-out persists in localStorage under hk_ignore and is honored by both this package and the hk.js snippet.

Typed wrappers emit the event names and property shapes from Ecommerce Analytics, so checkout instrumentation is checked by the compiler:

import { trackPurchase } from '@hitkeep/tracker';
trackPurchase({
transaction_id: 'tx-1042',
value: 49.9,
currency: 'EUR',
items: [{ item_id: 'sku-1', item_name: 'Starter Plan', quantity: 1, price: 49.9 }]
});
function trackViewItem(properties: ItemEventProperties): void; // view_item
function trackAddToCart(properties: ItemEventProperties): void; // add_to_cart
function trackBeginCheckout(properties: ItemEventProperties): void; // begin_checkout
function trackPurchase(properties: PurchaseProperties): void; // purchase

The runtime behavior — delivery, retries, duplicate suppression, session storage, privacy boundaries — is identical to Tracker Architecture because it is the same code. The differences are in how the tracker reaches the page:

  • Explicit host required. The snippet derives endpoints from its own script URL; a bundled module has no script URL.
  • Localhost stays blocked by default. Set captureOnLocalhost: true in development builds when you want local hits recorded.
  • Content blockers do not filter it, so ship the visitor opt-out above where your privacy posture calls for one.
  • Attribution is reported as @hitkeep/tracker with the package version, visible in ingest payloads as tsrc and tv.
  • Updates arrive through npm, not automatically with your HitKeep instance. Keep major versions aligned with your self-hosted instance version.

Prefer not to run the instance behind the tracker yourself? Start with HitKeep Cloud →