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

@sperax/analytics

v0.2.2

Published

SperaxOS analytics library — type-safe event tracking with PostHog and GA4

Readme

@sperax/analytics

Install

npm install @sperax/analytics

One typed track() call, fanned out to every analytics provider you have configured. PostHog (browser and Node), GA4, and Umami today; adding a provider does not change a single call site.

import { createAnalytics } from '@sperax/analytics';

const analytics = createAnalytics({
  business: 'speraxos',
  providers: {
    ga4: { enabled: true, measurementId: 'G-XXXXXXX' },
    posthog: { enabled: true, host: 'https://eu.i.posthog.com', key: 'phc_…' },
  },
});

await analytics.initialize();
await analytics.trackEvent('button_click', { button_name: 'connect_wallet' });

Install

npm install @sperax/analytics

React is an optional peer — only needed for the /react entry point.

Three entry points, because the browser and the server need different provider implementations:

| Import | Use in | | --- | --- | | @sperax/analytics | Browser and shared code — PostHog (posthog-js), GA4, Umami | | @sperax/analytics/server | Node — PostHog (posthog-node), no DOM access | | @sperax/analytics/react | React — provider + hooks |


Why a manager at all

Every provider fails differently and none of them should ever break a render or a request. AnalyticsManager guarantees three things:

  • Failures are swallowed per provider. One misconfigured key cannot take down tracking for the others, and no track() call ever rejects into your code.
  • Calls before initialize() are dropped, not queued forever. track() returns immediately when the manager is not ready.
  • Every event is enriched once, centrally, rather than at each call site.

Configuration

interface AnalyticsConfig {
  /** Product/business identifier attached to every event. */
  business: string;
  debug?: boolean;
  providers: {
    ga4?: { enabled: boolean; measurementId: string; gtagConfig?: Record<string, any>; debug?: boolean };
    posthog?: { enabled: boolean; key: string; host?: string; debug?: boolean };
    posthogNode?: { enabled: boolean; key: string; host?: string; debug?: boolean };
    umami?: { enabled: boolean; websiteId: string; scriptUrl?: string; debug?: boolean };
  };
}

Every provider carries its own enabled flag, so a provider can be wired up in config and switched off per environment without a code change:

providers: {
  posthog: { enabled: process.env.NODE_ENV === 'production', key: process.env.POSTHOG_KEY! },
}

Manager API

await analytics.initialize();                                  // load provider SDKs
await analytics.track({ name: 'swap_executed', properties: { chain: 42_161 } });
await analytics.trackEvent('page_view', { page: '/portfolio' }); // typed, see below
await analytics.trackPageView('/portfolio', { referrer });
await analytics.identify(userId, { plan: 'pro' });
await analytics.reset();                                        // on sign-out
analytics.getStatus();                                          // { initialized, providersCount }

trackEvent is the typed path. Its event names and property shapes come from PredefinedEvents, so a typo or a missing required property is a compile error:

interface PredefinedEvents {
  button_click: { button_name: string; spm?: string; [key: string]: any };
  page_view: { page: string; spm?: string; [key: string]: any };
  user_login: { spm?: string; [key: string]: any };
  user_signup: { spm?: string; [key: string]: any };
}

Extend that interface to cover your own events. Anything ad-hoc still goes through track({ name, properties }).


React

import { AnalyticsProvider, createAnalytics } from '@sperax/analytics/react';

const client = createAnalytics({ business: 'speraxos', providers: { … } });

export function Root({ children }) {
  return (
    <AnalyticsProvider client={client} onInitializeError={(e) => reportError(e)}>
      {children}
    </AnalyticsProvider>
  );
}

AnalyticsProvider calls initialize() once on mount (guarded against Strict Mode double-invocation) and registers the client globally so non-React code can reach it.

| Prop | Default | Description | | --- | --- | --- | | client | — | Required. An AnalyticsManager. | | autoInitialize | true | Initialize on mount. Set false to gate on consent. | | registerGlobal | true | Also register via setGlobalAnalytics. | | globalName | '__default__' | Key for the global registration. | | onInitializeSuccess | — | Called once initialization resolves. | | onInitializeError | — | Called with the error if it rejects. |

Four hooks, differing only in how they handle "not ready yet":

const { analytics, isReady, isInitializing, error } = useAnalytics();  // nullable + state
const analytics = useAnalyticsStrict();     // throws if no provider above it
const analytics = useAnalyticsOptional();   // null outside a provider
const { isInitialized, isInitializing, error } = useAnalyticsState(); // state only

useAnalytics is the default. Reach for useAnalyticsStrict in components that are always inside the provider, and useAnalyticsOptional in shared components that must also render in apps with no analytics at all.

Gating on consent is autoInitialize={false} plus an explicit call:

const { analytics } = useAnalytics();
const onAccept = () => analytics?.initialize();

Server

import { createServerAnalytics } from '@sperax/analytics/server';

const analytics = createServerAnalytics({
  business: 'speraxos',
  providers: { posthogNode: { enabled: true, key: process.env.POSTHOG_KEY! } },
});

await analytics.initialize();
await analytics.track({ name: 'agent_run_completed', properties: { durationMs, userId } });

The server entry point never touches window, so it is safe in route handlers, cron jobs, and workers. Use posthogNode there — the browser posthog provider expects a DOM.


Singleton

Most apps want one instance for the whole process:

import { createSingletonAnalytics, getGlobalAnalytics } from '@sperax/analytics';

createSingletonAnalytics(config);          // once, at startup
getGlobalAnalytics().track({ name: 'x' }); // anywhere

createAnalytics returns a fresh, unregistered manager — use it for tests and for anywhere you need two independent configurations.


Exports

import {
  AnalyticsManager, BaseAnalytics,
  PostHogAnalyticsProvider, GoogleAnalyticsProvider,
  createAnalytics, createSingletonAnalytics,
  getGlobalAnalytics, setGlobalAnalytics,
} from '@sperax/analytics';

import type {
  AnalyticsConfig, AnalyticsEvent, EventContext, Platform,
  PredefinedEvents, ProviderConfig, ProviderTypeMap,
  GoogleAnalyticsProviderConfig, PostHogProviderAnalyticsConfig,
  PostHogNodeProviderAnalyticsConfig, UmamiProviderAnalyticsConfig,
} from '@sperax/analytics';

import { PostHogNodeAnalyticsProvider, createServerAnalytics } from '@sperax/analytics/server';

import {
  AnalyticsProvider, useAnalytics, useAnalyticsOptional,
  useAnalyticsState, useAnalyticsStrict, useEventTracking,
} from '@sperax/analytics/react';

Apache-2.0

License

analytics is released under the Apache-2.0 license.