npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@telemetry-kit/browser

v0.1.0

Published

Privacy-first telemetry for browsers - lightweight (~1.4KB gzipped) with Proof of Work anti-spam

Readme

@telemetry-kit/browser

Privacy-first telemetry for browsers. Lightweight (~2KB gzipped) with Proof of Work anti-spam protection.

Features

  • Zero dependencies - No external packages required
  • Tiny bundle size - ~2KB gzipped
  • Privacy-first - Respects navigator.doNotTrack and GPC
  • No secrets required - Uses Proof of Work instead of API keys
  • Reliable delivery - Uses navigator.sendBeacon for page unload events
  • Modern Web APIs - Uses Web Crypto API for SHA-256 hashing

Installation

npm install @telemetry-kit/browser

Quick Start

import { TelemetryKit } from '@telemetry-kit/browser';

// Initialize
const telemetry = new TelemetryKit({
  appId: 'your-app-id',
  endpoint: 'https://api.telemetry-kit.dev/v1/collect'
});

// Track events
telemetry.track('button_click', { button: 'submit' });

// Track page views
telemetry.trackPageView();

// Track features
telemetry.trackFeature('dark_mode', { enabled: true });

// Track errors
telemetry.trackError('api_failed', { status: 500 });

Configuration

const telemetry = new TelemetryKit({
  // Required: Your application ID
  appId: 'your-app-id',

  // Optional: Ingestion endpoint (default: telemetry-kit.dev)
  endpoint: 'https://api.telemetry-kit.dev/v1/collect',

  // Optional: Proof of Work difficulty (default: 4)
  // Higher = more spam protection, but slower (~10ms at 4)
  difficulty: 4,

  // Optional: Respect navigator.doNotTrack (default: true)
  respectDNT: true,

  // Optional: Auto-flush interval in ms (default: 5000)
  flushInterval: 5000,

  // Optional: Max events before auto-flush (default: 10)
  maxQueueSize: 10,

  // Optional: Debug logging (default: false)
  debug: false
});

How Proof of Work Works

Instead of requiring API secrets (which can't be hidden in browser code), this SDK uses Proof of Work (PoW) to prevent spam:

  1. Each event requires solving a SHA-256 hash puzzle
  2. Finding a valid nonce takes ~10ms for legitimate users
  3. Mass-generating fake events becomes computationally expensive
  4. No secrets needed in client code
Difficulty | Leading Zeros | Avg Iterations | Time
-----------+---------------+----------------+------
    3      |     000       |     ~4,096     | ~1ms
    4      |     0000      |    ~65,536     | ~10ms
    5      |     00000     |  ~1,048,576    | ~150ms

Privacy Features

Do Not Track

By default, the SDK respects:

  • navigator.doNotTrack === '1'
  • navigator.globalPrivacyControl === '1'
// Disable DNT checking
const telemetry = new TelemetryKit({
  appId: 'app',
  respectDNT: false
});

Anonymous Sessions

  • Session IDs are random UUIDs
  • No persistent identifiers stored
  • No cookies or localStorage used

Manual Control

// Disable tracking
telemetry.setEnabled(false);

// Enable tracking
telemetry.setEnabled(true);

// Check status
const isEnabled = telemetry.getEnabled();

API Reference

new TelemetryKit(config)

Create a new TelemetryKit instance.

track(type: string, data?: Record<string, unknown>): Promise<void>

Track a custom event with optional data.

trackPageView(path?: string): Promise<void>

Track a page view. Defaults to current window.location.pathname.

trackFeature(feature: string, metadata?: Record<string, unknown>): Promise<void>

Track feature usage.

trackError(error: string, metadata?: Record<string, unknown>): Promise<void>

Track an error.

flush(): Promise<void>

Immediately flush queued events to the server.

setEnabled(enabled: boolean): void

Enable or disable tracking.

getEnabled(): boolean

Get current enabled state.

destroy(): void

Stop the flush timer and flush remaining events.

Framework Integration

React

import { useEffect } from 'react';
import { TelemetryKit } from '@telemetry-kit/browser';

const telemetry = new TelemetryKit({ appId: 'my-app' });

function App() {
  useEffect(() => {
    telemetry.trackPageView();
    return () => telemetry.destroy();
  }, []);

  const handleClick = () => {
    telemetry.track('button_click', { button: 'cta' });
  };

  return <button onClick={handleClick}>Click me</button>;
}

Vue

import { onMounted, onUnmounted } from 'vue';
import { TelemetryKit } from '@telemetry-kit/browser';

const telemetry = new TelemetryKit({ appId: 'my-app' });

onMounted(() => {
  telemetry.trackPageView();
});

onUnmounted(() => {
  telemetry.destroy();
});

Next.js

// app/providers.tsx
'use client';

import { useEffect } from 'react';
import { TelemetryKit } from '@telemetry-kit/browser';

const telemetry = new TelemetryKit({ appId: 'my-app' });

export function TelemetryProvider({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    telemetry.trackPageView();
    return () => telemetry.destroy();
  }, []);

  return <>{children}</>;
}

Self-Hosting

For self-hosted telemetry-kit servers, just change the endpoint:

const telemetry = new TelemetryKit({
  appId: 'my-app',
  endpoint: 'https://your-server.com/v1/collect'
});

License

MIT OR Apache-2.0