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

@cbnsndwch/react-tracking

v0.1.6

Published

Declarative tracking for React apps. Based on nytimes/react-tracking

Readme

@cbnsndwch/react-tracking

Fork Notice: This is a modernized fork of nytimes/react-tracking. See ACKNOWLEDGEMENTS.md for attribution and license details.

Declarative tracking for React apps.

  • React Hook (useTracking) and Higher-Order Component (track()) APIs
  • Compartmentalize tracking concerns to individual components
  • Analytics platform agnostic
  • Full TypeScript support with bundled type declarations
  • ESM-only, tree-shakeable

Installation

npm install @cbnsndwch/react-tracking
# or
pnpm add @cbnsndwch/react-tracking

Usage

import track, { useTracking } from '@cbnsndwch/react-tracking';

Both track() and useTracking() accept two arguments: trackingData and options.

  • trackingData — the data to be tracked (or a function returning that data)
  • options — an optional object with the following properties:
    • dispatch — a function to use instead of the default dispatch behavior. See Custom dispatch below.
    • dispatchOnMount — when true, dispatches tracking data when the component mounts. When a function, it is called with all contextual tracking data on initial render.
    • process — a function defined once at some top-level component, used for selectively dispatching tracking events based on each component's tracking data. See Top level process below.
    • forwardRef (HoC only) — when true, a ref on the wrapped component returns the underlying component instance. Default: false.
    • mergeOptionsdeepmerge options.

useTracking Hook

The recommended API. Returns trackEvent, getTrackingData, and a <Track /> provider component:

import { useTracking } from '@cbnsndwch/react-tracking';

function FooPage() {
    const { Track, trackEvent } = useTracking({ page: 'FooPage' });

    return (
        <Track>
            <button onClick={() => trackEvent({ action: 'click' })}>
                Click Me
            </button>
        </Track>
    );
}

Wrap your returned markup with <Track /> to pass contextual tracking data to child components via deepmerge. Leaf components that don't have tracked children can skip <Track />:

import { useTracking } from '@cbnsndwch/react-tracking';

function Child() {
    const { trackEvent } = useTracking();

    return (
        <button onClick={() => trackEvent({ action: 'childClick' })}>
            Click
        </button>
    );
}

function FooPage() {
    const { Track, trackEvent } = useTracking({ page: 'FooPage' });

    return (
        <Track>
            <Child />
            <button onClick={() => trackEvent({ action: 'click' })}>
                Click Me
            </button>
        </Track>
    );
}

In this example, clicking the button in Child dispatches:

{ "page": "FooPage", "action": "childClick" }

track() Higher-Order Component

The track() export wraps a component and injects a tracking prop with trackEvent() and getTrackingData() methods:

import track from '@cbnsndwch/react-tracking';

function FooPage({ tracking }) {
    return (
        <button onClick={() => tracking.trackEvent({ action: 'click' })}>
            Click Me
        </button>
    );
}

export default track({ page: 'FooPage' })(FooPage);

Custom options.dispatch() for tracking data

By default, tracking data is pushed to window.dataLayer[] (see src/dispatchTrackingEvent.ts), which works well with Google Tag Manager.

Override this by passing a dispatch function at a top-level component:

import { useTracking } from '@cbnsndwch/react-tracking';

export default function App({ children }) {
    const { Track } = useTracking(
        {},
        { dispatch: data => window.myCustomDataLayer.push(data) }
    );

    return <Track>{children}</Track>;
}

Every child component will inherit this dispatch function.

options.dispatchOnMount

As a boolean

Dispatches tracking data when a component mounts — useful for page-level tracking:

function FooPage() {
    useTracking({ page: 'FooPage' }, { dispatchOnMount: true });
    return <div>Foo</div>;
}

As a function

Called with all contextual tracking data on mount. The returned object is deepmerged with context data and dispatched:

function FooPage() {
    useTracking(
        { page: 'FooPage' },
        { dispatchOnMount: contextData => ({ event: 'pageDataReady' }) }
    );
    return <div>Foo</div>;
}

Dispatches: { event: 'pageDataReady', page: 'FooPage' }

Top level options.process

Define an options.process function once at a top-level component to implicitly dispatch events based on each component's tracking data. Return a falsy value to skip dispatch:

function App() {
    const { Track } = useTracking(
        {},
        {
            process: ownTrackingData =>
                ownTrackingData.page ? { event: 'pageview' } : null
        }
    );

    return (
        <Track>
            <Page1 />
            <Page2 />
        </Track>
    );
}

function Page1() {
    useTracking({ page: 'Page1' });
}

function Page2() {
    useTracking({});
}

When Page1 mounts, { page: 'Page1', event: 'pageview' } is dispatched. Page2 dispatches nothing.

Dynamic Tracking Data

Pass a function to compute tracking data from props at render time:

import track from '@cbnsndwch/react-tracking';

const FooPage = track(props => ({
    page: props.isNew ? 'new' : 'existing'
}))(({ tracking }) => (
    <button onClick={() => tracking.trackEvent({ action: 'click' })}>
        Click
    </button>
));

getTrackingData()

Access all contextual tracking data accumulated up the component tree:

import { useMemo } from 'react';
import { useTracking } from '@cbnsndwch/react-tracking';

function AdComponent() {
    const randomId = useMemo(() => Math.floor(Math.random() * 100), []);
    const { getTrackingData } = useTracking({ page_view_id: randomId });
    const { page_view_id } = getTrackingData();

    return <Ad pageViewId={page_view_id} />;
}

Tracking Data Format

There are no restrictions on the shape of tracking data objects. The format is a contract between your app and the consumer of the tracking data.

This library merges tracking data objects (via deepmerge) as they flow through your React component hierarchy into a single object sent to the tracking agent.

TypeScript

Types are bundled with the package — no need for @types/*. All public APIs are fully typed.

Deepmerge

You can use the copy of deepmerge bundled with this library:

import { deepmerge } from '@cbnsndwch/react-tracking';

License

MIT

This project is a fork of nytimes/react-tracking, originally licensed under Apache 2.0. See ACKNOWLEDGEMENTS.md.