@identityjs/tracker
v1.3.6
Published
Visitor fingerprinting, identification & analytics — drop-in script or npm package
Maintainers
Readme
identity-js
Open-source visitor intelligence for modern web apps. Drop-in analytics with browser fingerprinting, behavioral tracking, and real-time insights — no cookies, no consent banners, zero dependencies.
Dashboard & Docs · Live Demo · Get API Key
Why identity-js?
Most analytics tools tell you what happened. Identity-js tells you who did it and how frustrated they were.
| | identity-js | Google Analytics | Hotjar | Microsoft Clarity | |---|:---:|:---:|:---:|:---:| | Cookie-free tracking | Yes | No | No | No | | Browser fingerprinting (40+ signals) | Yes | No | No | No | | Frustration scoring | Yes | No | Yes | Partial | | Rage / dead / phantom click detection | Yes | No | Partial | Yes | | Bot detection with scoring | Yes | No | No | Yes | | Persistent ID (survives cookie clears) | Yes | No | No | No | | Form abandonment tracking | Yes | No | Yes | No | | Real-time visitor dashboard | Yes | Delayed | No | Delayed | | Self-hostable | Yes | No | No | No | | No consent banner needed | Yes | No | No | No | | Bundle size | 45 KB | 90 KB+ | 80 KB+ | 60 KB+ | | Free tier | Generous | Limited | Limited | Unlimited |
Quick start
npm
npm install @identityjs/trackerimport IdentityJS from '@identityjs/tracker';
const visitor = await IdentityJS.init({
apiKey: 'pk_live_YOUR_KEY',
});
console.log(visitor.visitorId); // "a3f2b1c4d5e6-k9m2"Script tag
<script src="https://cdn.jsdelivr.net/npm/@identityjs/tracker/dist/identity.min.js"></script>
<script>
IdentityJS.init({ apiKey: 'pk_live_YOUR_KEY' });
</script>That's it. Pageviews, sessions, fingerprints, behavioral tracking — all automatic.
Get your API key at identity-js.com/dashboard.
Framework examples
React
import { useEffect } from 'react';
import IdentityJS from '@identityjs/tracker';
function App() {
useEffect(() => {
IdentityJS.init({
apiKey: process.env.REACT_APP_IDENTITY_KEY,
onReady: (v) => console.log('Visitor:', v.visitorId),
});
}, []);
return <div />;
}Next.js
// app/layout.js or pages/_app.js
import IdentityJS from '@identityjs/tracker';
if (typeof window !== 'undefined') {
IdentityJS.init({ apiKey: process.env.NEXT_PUBLIC_IDENTITY_KEY });
}Gatsby
// gatsby-browser.js
import IdentityJS from '@identityjs/tracker';
export const onClientEntry = () => {
IdentityJS.init({ apiKey: 'pk_live_YOUR_KEY' });
};Vue / Nuxt
// plugins/identity.client.js
import IdentityJS from '@identityjs/tracker';
export default defineNuxtPlugin(() => {
IdentityJS.init({ apiKey: 'pk_live_YOUR_KEY' });
});Svelte / SvelteKit
// src/routes/+layout.svelte
<script>
import { onMount } from 'svelte';
import IdentityJS from '@identityjs/tracker';
onMount(() => {
IdentityJS.init({ apiKey: 'pk_live_YOUR_KEY' });
});
</script>Plain HTML / WordPress
<!-- Add before </head> -->
<script defer src="https://cdn.jsdelivr.net/npm/@identityjs/tracker/dist/identity.min.js"
data-api-key="pk_live_YOUR_KEY"></script>What gets tracked automatically
Once you call init(), everything below starts working with zero configuration:
| Tracker | What it detects | |---|---| | Fingerprinting | 40+ browser signals — canvas, WebGL, audio, fonts, speech voices, math quirks, screen, CPU, timezone | | Dead Clicks | Clicks on non-interactive elements (nothing happened) | | Phantom Clicks | Clicks on elements that look clickable but aren't (pointer cursor, underline, hover effect) | | Rage Clicks | Rapid frustrated clicking on the same element | | Form Abandonment | Forms started but never submitted — which field they stopped at | | Input Hesitation | Time between focusing a field and first keystroke (confusion signal) | | Reading Behavior | Scroll velocity classified as reading, skimming, or scanning per page | | Frustration Score | 0-100 weighted composite: rage clicks (30), dead clicks (15), errors (15), form abandons (20), rapid nav (20) | | Error Tracking | JS exceptions, promise rejections, console errors — with severity classification (error vs warning) | | Text Copy | When users copy text from your page | | Bot Detection | 0-100 bot score with specific detection reasons |
API
IdentityJS.init(options?)
Returns Promise<VisitorObject>.
| Option | Type | Default | Description |
|---|---|---|---|
| apiKey | string | — | Project API key (pk_live_...) from your dashboard |
| endpoint | string | https://www.identity-js.com/api/ping | API endpoint |
| onReady | function | — | Called with the visitor object once ready |
| trackBehavior | boolean | true | Track clicks, scrolls, keystrokes |
| trackSpaNavigation | boolean | true | Auto-track SPA route changes |
| sendOnLoad | boolean | true | Send fingerprint on page load |
| sendOnUnload | boolean | true | Send session data on page close |
| requireConsent | boolean | false | If true, no data sent until grantConsent() is called |
VisitorObject
{
visitorId: string; // Persistent ID (survives cookie clears)
sessionId: string; // Per-tab session ID
isNewVisitor: boolean; // True on first ever visit
fingerprintHash: string; // Stable hash of browser signals
signals: object; // Full fingerprint signal set
track(name, data?): void; // Send custom event
getBehavior(): object; // Live behavioral snapshot
flush(): void; // Force-send buffered data
destroy(): void; // Remove all event listeners
grantConsent(): void; // Start sending (consent mode)
revokeConsent(): void; // Stop sending, clear buffers
hasConsent(): boolean; // Check consent state
}Custom events
// Queue-safe — works even before init() resolves
IdentityJS.track('added_to_cart', { productId: 'abc', price: 29.99 });
// Or use the visitor object
const visitor = await IdentityJS.init({ apiKey: 'pk_live_...' });
visitor.track('purchase_clicked', { plan: 'pro', price: 49 });Consent mode
Works with Cookiebot, OneTrust, CookieYes, or any consent manager. The tracker buffers data in memory and sends nothing until the user accepts.
await IdentityJS.init({ apiKey: 'pk_live_YOUR_KEY', requireConsent: true });
// Cookiebot example:
window.addEventListener('CookiebotOnAccept', () => {
if (Cookiebot.consent.statistics) IdentityJS.grantConsent();
});
window.addEventListener('CookiebotOnDecline', () => {
IdentityJS.revokeConsent();
});How it works
Fingerprinting — Collects 40+ passive browser signals (canvas rendering, WebGL renderer, audio context, installed fonts, math precision quirks, etc.) and hashes them into a stable visitor ID that persists even after cookie clears.
Session tracking — Each tab gets a unique session ID. Heartbeats track active time, page changes, and scroll depth. SPA navigations are detected automatically via pushState/popstate.
Behavioral analysis — Click, scroll, and keystroke patterns are analyzed in real-time. Frustrated users trigger rage click, dead click, and form abandonment events that feed into the frustration score.
Bot detection — A weighted scoring system analyzes UA patterns, browser capabilities, and client-side signals. Real social app WebViews (Instagram, Facebook, Viber) are distinguished from unfurler bots.
Privacy-first — No cookies are set. No PII is collected. The fingerprint is a one-way hash. Works without consent banners under most GDPR interpretations for legitimate interest analytics.
License
MIT — use it however you want.
