---
title: "HitKeep NPM Package for React, Vue, Angular, and Astro | HitKeep"
description: "Install @hitkeep/tracker from npm for typed, bundler-native HitKeep analytics in React, Vue, Angular, and Astro instead of the hk.js script snippet."
canonical: "https://hitkeep.com/guides/tracking/npm-package/"
---

# 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`](https://hitkeep.com/guides/tracking/tracker-architecture/) — built from the same source, with the same privacy behavior — as a fully typed ES module.

```
npm install @hitkeep/tracker
```

The package is published on npm as [`@hitkeep/tracker`](https://www.npmjs.com/package/@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](https://hitkeep.com/guides/tracking/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.

## Framework integration

- React
- Vue
- Angular
- Astro

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>
```

Initialize in your app entry, or wrap it in a small plugin:

main.ts

```
import { createApp } from 'vue';
import { init } from '@hitkeep/tracker';
import App from './App.vue';

init({ host: 'https://your-hitkeep.example' });

createApp(App).mount('#app');
```

Vue Router navigations use the history API and are tracked automatically. Track custom events from any component:

```
<script setup lang="ts">
import { track } from '@hitkeep/tracker';
</script>

<template>
  <button @click="track('cta_clicked', { location: 'hero' })">Get started</button>
</template>
```

Initialize through an app initializer in `app.config.ts`:

app.config.ts

```
import { ApplicationConfig, provideAppInitializer } from '@angular/core';
import { init } from '@hitkeep/tracker';

export const appConfig: ApplicationConfig = {
  providers: [
    provideAppInitializer(() => {
      init({ host: 'https://your-hitkeep.example' });
    })
  ]
};
```

Angular Router navigations go through the history API and are tracked automatically — no `Router.events` subscription is needed. Track custom events from any component or service:

```
import { track } from '@hitkeep/tracker';

onUpgradeClick(): void {
  track('plan_upgraded', { plan: 'pro' });
}
```

Add a module script to your base layout. Astro bundles it like any other import:

src/layouts/Base.astro

```
<html lang="en">
  <body>
    <slot />
    <script>
      import { init } from '@hitkeep/tracker';

      init({ host: 'https://your-hitkeep.example' });
    </script>
  </body>
</html>
```

For a mostly static Astro site without view transitions, the `hk.js` snippet works equally well — the npm package earns its place once you track typed custom events from islands:

```
import { track } from '@hitkeep/tracker';

track('newsletter_subscribed', { source: 'footer' });
```

With `<ClientRouter />` view transitions enabled, navigations use the history API and are tracked automatically.

## Configuration

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 |

## API reference

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.

### Visitor opt-out

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 e-commerce events

Typed wrappers emit the event names and property shapes from [Ecommerce Analytics](https://hitkeep.com/guides/analytics/ecommerce/), 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
```

## Differences from the hk.js snippet

The runtime behavior — delivery, retries, duplicate suppression, session storage, privacy boundaries — is identical to [Tracker Architecture](https://hitkeep.com/guides/tracking/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.

## Related

- [Tracker Architecture](https://hitkeep.com/guides/tracking/tracker-architecture/)
- [Automatic Events](https://hitkeep.com/guides/tracking/automatic-events/)
- [Custom Events](https://hitkeep.com/guides/tracking/custom-events/)
- [Custom Tracking Domains](https://hitkeep.com/guides/tracking/custom-tracking-domains/)
- [Server-Side Tracking](https://hitkeep.com/guides/tracking/server-side-tracking/)
- [Ecommerce Analytics](https://hitkeep.com/guides/analytics/ecommerce/)
- [Web Vitals Analytics](https://hitkeep.com/guides/analytics/web-vitals/)

Prefer not to run the instance behind the tracker yourself? [Start with HitKeep Cloud →](https://cloud.hitkeep.eu/signup?plan=free&billing=monthly&utm_source=hitkeep_docs&utm_medium=referral&utm_campaign=cloud_signup&utm_content=docs_inline)

[Previous Tracker architecture](https://hitkeep.com/guides/tracking/tracker-architecture/)[Next Custom tracking domains](https://hitkeep.com/guides/tracking/custom-tracking-domains/)
