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

tracklane

v0.6.0

Published

One interface between your application and every tool that receives events, for the browser and server. GA4, Meta and PostHog today; LinkedIn and X next.

Readme

tracklane

One interface between your application and every analytics and advertising tool, in the browser and through their conversion APIs.

Every analytics and advertising tool arrives with its own SDK, its own event names and its own payload format. Add a second one and the tracking call at each conversion point stops being a line and becomes a block. Add a third and every one of those blocks has to change.

The server-side half is worse. Each vendor ships a separate conversion API with a different name and a different contract: Google's Measurement Protocol, Meta's Conversions API, LinkedIn's Conversions API, PostHog's Capture API. Each wants its own identifiers, its own hashing rules, and its own way of tying a server event back to the browser event so the two are not counted twice.

tracklane gives your application one interface for both. Name what happened once, in GA4's vocabulary, and it reaches every tool you configured, translated into that tool's event names, payload shape and identifiers.

Documentation: https://tracklane.codar.me

Install

pnpm add tracklane

Node >=22.14.0, ESM only.

Browser

The vendor's own tag goes on your page first, the way the vendor documents it. This library talks to the tag that is there. It does not inject third-party scripts.

import { createTracking, ga4 } from 'tracklane/browser';

const { track, identify, consent } = createTracking({
  providers: [ga4('G-XXXXXXX')],
  onError: (error) => report(error),
});

track('purchase', { transaction_id: 'T-1024', value: 49.9, currency: 'BRL' });
identify({ userId: 'user_42', email: '[email protected]' }, { plan: 'pro' });
consent('update', { ad_storage: 'granted', analytics_storage: 'granted' });

Server

Each vendor's conversion API, behind the call you already wrote. The credentials are that vendor's own: GA4's Measurement Protocol wants a measurementId alongside its apiSecret, exactly as its own endpoint does.

import { createTracking, ga4 } from 'tracklane/server';

const { track } = createTracking({
  providers: [ga4({ measurementId: 'G-XXXXXXX', apiSecret })],
});

await track('purchase', order, {
  cookies: request.headers.get('cookie'),
  user: { userId: order.userId, email: order.email },
  dedupId: order.id,
  timestamp: order.paidAt,
});

Pass the request's cookies: the vendors' own tags set them in the browser, and their server APIs need what is inside. This library reads them for you, because that parsing is the part that fails silently.

What it does not do

It standardises and organises, and it never changes behaviour. The test applied to every decision is if you did not have this library, how would you write this line by hand? It replicates exactly that.

So it is not a consent platform: it forwards the consent call you make, when you make it, and decides nothing. It is not a compliance layer, a validator, or a delivery guarantee. There is no queue, no retry, and one vendor failing never affects another or your call site. And it does not install vendor tags.

Providers

Both surfaces, or it does not count as shipped. This table is checked against the source on every build, so it is never ahead of the library.

| Vendor | Conversion API | Status | | -------- | -------------------- | ------ | | GA4 | Measurement Protocol | shipped | | Meta | Conversions API | shipped | | LinkedIn | Conversions API | next | | PostHog | Capture API | shipped | | X | Conversions API | next |

Any tool that receives events about what your users do can be a destination, and writing your own uses the same public contract the built-in ones use, without a registry entry, an allow-list, or a release of this library. See writing a provider.

License

MIT © Bruno Bertolini