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

analytics-adapters

v1.1.0

Published

One analytics API with swappable provider adapters and framework integrations.

Readme

analytics-adapters

One analytics API. Swap the provider, keep your calls.

pnpm add analytics-adapters
// lib/analytics.ts
import { createAnalytics } from 'analytics-adapters'
import { google } from 'analytics-adapters/google'

export const analytics = createAnalytics(google({ id: 'G-XXXXXXX' }))

analytics.track('signup', { plan: 'pro' })
analytics.page({ page_path: '/pricing' })
analytics.identify('user_123')

Every call is a no-op on the server, so it's safe to import anywhere.

Next.js Google Analytics

// app/layout.tsx
import { GoogleAnalytics } from 'analytics-adapters/next'

<GoogleAnalytics id="G-XXXXXXX">{children}</GoogleAnalytics>

Pageviews track on every navigation. useAnalytics() works in any client component for custom events. Works in pages/_app.tsx too.

For multiple providers or a custom adapter, pass your own instance:

// app/layout.tsx
import { Analytics } from 'analytics-adapters/next'
import { analytics } from '@/lib/analytics'

export default function RootLayout({ children }) {
  return (
    <html><body><Analytics analytics={analytics}>{children}</Analytics></body></html>
  )
}

<Analytics> is a client component; it wraps children in the provider and sends a page_view on every App Router navigation. Use useAnalytics() from the same subpath in client components.

TanStack Start Google Analytics

// routes/__root.tsx
import { GoogleAnalytics } from 'analytics-adapters/tanstack'

<GoogleAnalytics id="G-XXXXXXX">{children}</GoogleAnalytics>

Or with your own instance:

import { Analytics } from 'analytics-adapters/tanstack'
import { analytics } from '~/lib/analytics'

<Analytics analytics={analytics}>{children}</Analytics>

Plausible

Wraps the official @plausible-analytics/tracker; install it alongside:

pnpm add @plausible-analytics/tracker
import { plausible } from 'analytics-adapters/plausible'

export const analytics = createAnalytics(plausible({ domain: 'example.com' }))

Or zero-config: <PlausibleAnalytics domain="example.com"> from analytics-adapters/next or analytics-adapters/tanstack.

Options are the tracker's PlausibleConfig (endpoint for self-hosted/proxy, outboundLinks, fileDownloads, revenue, …) plus defer (default true: load on requestIdleCallback; calls queue meanwhile). autoCapturePageviews is forced off so page() is the only pageview source. Props are stringified (Plausible only accepts strings). identify, consent, and get are no-ops — Plausible is cookieless.

Any other React app

analytics-adapters/react exports the building blocks: AnalyticsProvider, useAnalytics, and usePageview(path) — pass whatever your router says the current path is.

Google options

| option | default | | | --------------- | ------------- | -------------------------------- | | id | required | GA4 measurement ID (G-…) | | nonce | | CSP nonce for the script tag | | consent | | Consent Mode defaults, e.g. { analytics_storage: 'denied' } | | defer | true | Inject the script on requestIdleCallback; events queue meanwhile |

Calls made before load() auto-load first, so nothing is ever dropped. Update consent later with analytics.consent({ analytics_storage: 'granted' }). Read values with await analytics.get('client_id') (resolves undefined after 3s if the script is blocked).

Auto pageviews are disabled (send_page_view: false); usePageview / page() is the single source of truth, so SPA navigations never double-count.

Custom adapter

import type { Adapter } from 'analytics-adapters'

const logger: Adapter = {
  load() {},
  page: (p) => console.log('page', p),
  track: (n, p) => console.log(n, p),
}

createAnalytics([google({ id: 'G-X' }), logger]) // fans out to all