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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@betterumami/core

v0.2.0

Published

Framework-agnostic tracker core for BetterUmami. Drop-in replacement for the script-tag tracker.

Readme

@betterumami/core

Framework-agnostic BetterUmami tracker. Drop-in replacement for the script-tag tracker — same POST /api/send payload, headers, and cache-token handling.

Install

npm install @betterumami/core

Usage

import { init, track, trackEvent, trackPageview, identify, getSession } from '@betterumami/core';

init({
  websiteId: 'your-website-id',
  hostUrl: 'https://analytics.example.com', // optional, defaults to window.location.origin
});

trackEvent('signup-button', { plan: 'pro' }); // custom event
trackPageview(); // manual pageview
identify('user-123', { plan: 'pro' }); // visitor identity

Automatic pageviews fire on load and on SPA route changes (History API pushState/replaceState hooks + popstate). Elements with data-umami-event="name" are tracked on click.

How to tell the SDK actually loaded

After init() runs you can confirm it two ways:

  1. In the DOM. A no-op marker is injected into <head>:

    <script type="text/betterumami"
            data-betterumami-marker
            data-website-id="abc-123"
            data-version="0.1.2"></script>

    The type is non-JS so the browser stores it as text but never executes it. Open DevTools → Elements → <head> and look for the marker.

  2. In DevTools. A window.betterumami namespace is installed:

    window.betterumami.track('devtools-test');
    window.betterumami.getSession();
    window.betterumami.version; // '0.1.2'

Debugging failures

Network or server errors no longer fail silently. Failed sends log a warning so you can spot them in the console:

[BetterUmami] failed to send event TypeError: Failed to fetch
[BetterUmami] failed to send event 500 Internal Server Error (https://api.example.com/api/send)

If you want to inspect payloads without sending anything, set dryRun: true. Every event is logged to console.log instead of POSTed — useful for local development.

Config

| Option | Type | Default | Description | |---|---|---|---| | websiteId | string | — | Required. The website ID from your BetterUmami dashboard. | | hostUrl | string | window.location.origin | Origin of the BetterUmami instance. | | endpoint | string | /api/send | Collection path. Combined with hostUrl at init. | | autoTrack | boolean | true | Enable automatic tracking (clicks, pageviews) on init. | | autoPageview | boolean | true | Send a pageview on load and on SPA route changes. Set to false if your framework already reports its own route changes. | | trackPopstate | boolean | true | Also listen to popstate (back/forward). | | domains | string \| string[] | — | Only track on these hostnames. Comma-separated or array. | | excludeSearch | boolean | false | Strip the query string from tracked URLs. | | excludeHash | boolean | false | Strip the hash from tracked URLs. | | doNotTrack | boolean | false | Respect the browser's Do Not Track setting. | | tag | string | — | Tag attached to every event. | | credentials | RequestCredentials | 'omit' | fetch credentials mode. | | beforeSend | (type, payload) => payload \| null | — | Inspect / modify / drop every payload. Return null to drop. | | nonce | string | — | CSP nonce to apply to the in-page marker <script>. | | dryRun | boolean | false | Log payloads to console.log instead of POSTing. Nothing leaves the browser. |

SPA route tracking

@betterumami/core patches history.pushState and history.replaceState, and listens for popstate. No router integration is required for any framework. Disable with autoPageview: false if you report route changes yourself (e.g. with appWithTranslation in Next.js).

Programmatic API

| Function | Purpose | |---|---| | init(config) | Initialize the SDK. Idempotent — re-calling is a no-op. | | track(name?, data?) | Send a pageview, named event, or arbitrary payload. | | trackEvent(name, data?) | Convenience wrapper for track(name, data). | | trackPageview(url?) | Force a pageview (optionally overriding the URL). | | identify(id, data?) | Attach a stable visitor ID and/or session data. | | getSession() | Returns { cache, website } for inspection. | | destroy() | Remove listeners, marker, and window.betterumami. Mainly for tests / HMR. |

Why is there a window.betterumami global?

For parity with upstream Umami (window.umami) and to make the SDK discoverable. Other libraries can detect that the SDK is loaded by checking window.betterumami; users can run window.betterumami.track('foo') from the console without importing anything.

TypeScript

The package ships .d.ts files. All public APIs (init, track, trackEvent, trackPageview, identify, getSession, BetterUmamiConfig, EventData) are typed.