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

@startsimpli/analytics

v0.4.13

Published

Shared analytics and telemetry package for StartSimpli Next.js apps

Readme

@startsimpli/analytics

Shared telemetry layer for the StartSimpli Next.js apps. Wraps Google Analytics 4 (gtag.js) and PostHog (product analytics + feature flags + session recording) behind a single TelemetryService so events, page views, identifies, and feature-flag lookups fan out to every configured provider with the same call. Ships React hooks, a Next-aware <GoogleAnalyticsScript> component, and a reportWebVital handler for Next's useReportWebVitals.

Currently consumed by raise-simpli/web-app/ and market-simpli/ (browser-side only — there is no server SDK here).

Install

Workspace dependency only:

// app/package.json
"dependencies": {
  "@startsimpli/analytics": "workspace:*"
}

posthog-js is an optional peer dependency — pulled in via dynamic import('posthog-js'). Install it in the consuming app if you want PostHog wired up; GA-only deployments can omit it.

Public surface

| Export | Type | Description | | --- | --- | --- | | telemetry | TelemetryService singleton | Global instance; call .initialize() once per page load | | TelemetryService | class | Constructable for tests / multi-tenant cases | | trackEvent / trackPageView / identifyUser / resetUser | functions | Singleton convenience wrappers | | GoogleAnalyticsProvider / PostHogProvider | classes | Direct provider access (custom wiring) | | gtagEvent / gtagPageView / gtagSetUserId | functions | Low-level gtag helpers | | AnalyticsEvent / PageViewEvent / UserIdentity / TelemetryConfig / FeatureFlagResult / AnalyticsProvider / EventCategory | types | Public type surface | | GoogleAnalyticsScript (from /components) | React component | Drop-in Next <Script> injector for GA4 | | useAnalytics (from /hooks) | hook | Returns bound { track, pageView, identify, reset, isFeatureEnabled } | | useAnalyticsLifecycle (from /hooks) | hook | Initializes telemetry, fires page views on route change, identifies on auth settle, resets on logout | | reportWebVital (from /vitals) | function | Handler for Next's useReportWebVitals — rates against Google's thresholds and POSTs to a configurable endpoint in prod | | WebVital / WebVitalName / ReportWebVitalOptions | types | Web vitals types |

Subpath exports: ., ./providers, ./components, ./hooks, ./vitals.

Event-naming convention

EventCategory is a union of standard buckets plus string (open for app-specific extensions):

navigation | user | search | filter | export | integration | error | <any string>

Event names are not enforced by the type system — convention across consuming apps is snake_case_verb_noun (e.g. fundraise_created, button_clicked, pageview_dashboard). Categories are passed alongside as the second argument and become event_category in GA4 and a category property in PostHog.

Configuration

Telemetry reads from NEXT_PUBLIC_* env vars at initialize() time. All are optional — missing keys silently disable that provider.

| Variable | Purpose | | --- | --- | | NEXT_PUBLIC_GA_MEASUREMENT_ID | GA4 measurement ID (e.g. G-XXXXXXXXXX) | | NEXT_PUBLIC_POSTHOG_KEY | PostHog project API key | | NEXT_PUBLIC_POSTHOG_HOST | PostHog host (defaults to https://us.i.posthog.com) | | NEXT_PUBLIC_ANALYTICS_ENABLED | Set to 'true' to enable telemetry in non-production builds |

By default telemetry is only enabled in production — set NEXT_PUBLIC_ANALYTICS_ENABLED=true to capture in dev/staging.

You can also pass overrides directly:

telemetry.initialize({
  googleAnalytics: { enabled: true, measurementId: 'G-XYZ' },
  posthog: { enabled: true, apiKey: 'phc_…', apiHost: 'https://eu.i.posthog.com' },
  debug: true,
})

Usage

Real wiring from raise-simpli/web-app/src/components/analytics/AnalyticsProvider.tsx:

'use client'
import { usePathname, useSearchParams } from 'next/navigation'
import { useAuth } from '@startsimpli/auth'
import { useAnalyticsLifecycle } from '@startsimpli/analytics/hooks'

export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
  const pathname = usePathname()
  const searchParams = useSearchParams()
  const { user, isLoading } = useAuth()

  useAnalyticsLifecycle({ pathname, searchParams, user, isLoading })

  return <>{children}</>
}

And app/layout.tsx (market-simpli):

import { GoogleAnalyticsScript } from '@startsimpli/analytics/components'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <GoogleAnalyticsScript measurementId={process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID!} />
        {children}
      </body>
    </html>
  )
}

Track an event from anywhere client-side:

'use client'
import { useAnalytics } from '@startsimpli/analytics/hooks'

export function SignupButton() {
  const { track } = useAnalytics()
  return <button onClick={() => track('button_clicked', 'user', { button: 'signup' })}>Sign up</button>
}

Web vitals (market-simpli/src/components/analytics/WebVitalsReporter.tsx):

'use client'
import { useReportWebVitals } from 'next/web-vitals'
import { reportWebVital } from '@startsimpli/analytics/vitals'

export function WebVitalsReporter() {
  useReportWebVitals(reportWebVital)
  return null
}

Verification

cd packages/analytics
pnpm tsc --noEmit

This package currently ships no unit tests — the lifecycle behavior is exercised in the consumer apps (see raise-simpli/web-app/src/__tests__/components/useAnalyticsLifecycle.test.tsx and …/lib/vitals.test.ts). Adding a vitest suite here is tracked as future work.

Shared-first

Per CLAUDE.md rule 9, analytics primitives never live in app src/. If you find an AnalyticsProvider.tsx or a track(…) helper duplicated inside an app, hoist it into @startsimpli/analytics and consume it. Both raise-simpli and market-simpli already follow this pattern — their app-local components are thin wrappers around the hooks here.