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

@addilytics/nuxt

v0.0.1

Published

Nuxt and Nitro analytics with bundled navigation tracking.

Downloads

209

Readme

@addilytics/nuxt

A Nitro server plugin for Nuxt pageviews and custom events, with optional browser tracking for SPA navigations. It reads the final status and content type in Nitro's public afterResponse hook, after rendering and response middleware have finished. It never reads or changes the application response body.

The Nuxt integration supports Nuxt 3.11 and newer, including Nuxt 4. The underlying Nitro peer must be version 2.9 or newer.

// server/plugins/addilytics.ts
import { addilytics } from '@addilytics/nuxt';

export const analytics = addilytics({
	endpoint: process.env.ADDILYTICS_ENDPOINT!,
	siteKey: process.env.ADDILYTICS_SITE_KEY!
});

export default analytics;

The adapter records only eligible final HTML responses. It skips redirects and 5xx responses by default. It also ignores Nuxt's /_nuxt/ build assets and /__nuxt_island/ component-data routes, including sites mounted below a base path.

SPA pageviews

Use hybrid mode to record the initial document request in Nitro and later client-side navigations through a same-origin relay. Set the same mode on both sides. The helper is bundled by your app; Addilytics does not load a hosted or CDN script.

// server/plugins/addilytics.ts
import { addilytics } from '@addilytics/nuxt';

export const analytics = addilytics({
	endpoint: process.env.ADDILYTICS_ENDPOINT!,
	mode: 'hybrid',
	siteKey: process.env.ADDILYTICS_SITE_KEY!
});
// plugins/addilytics.client.ts
import { createAddilyticsNuxtPlugin } from '@addilytics/nuxt/browser';

export default defineNuxtPlugin(
	createAddilyticsNuxtPlugin({
		mode: 'hybrid'
	})
);

The client plugin records the mounted page and Nuxt's page:finish hook, after the new page has rendered. Hybrid mode skips that first browser event because Nitro already recorded the document. To make the browser own the initial pageview too, set mode: 'client' in both files. Client mode disables automatic document pageviews in the server plugin.

Hash-only changes are ignored by default. Set trackHashChanges: true in the client plugin options to count them. Restoring a page from the browser back-forward cache records a fresh pageview.

The Nitro plugin registers a POST relay at /__addilytics with Nitro's public router. If you change the path, relayPath on the server must match endpoint in the client:

// Server option
relayPath: '/internal/analytics';

// Client option
endpoint: '/internal/analytics';

Do not put the site key or ingest endpoint in the client plugin. The browser sends only an event ID, timestamp, pathname, allowlisted campaign parameters, and the referrer origin. Nitro adds trusted request and identity data before forwarding the event. The relay rejects cross-origin requests and malformed payloads.

Custom events

Import the configured plugin from a server route.

// server/api/signup.post.ts
import { analytics } from '../plugins/addilytics';

export default defineEventHandler(async (event) => {
	await analytics.track(event, 'signup', {
		props: { source: 'pricing' }
	});
	return { ok: true };
});

track() uses the same bot filtering and identity rules as the core client.

Identity and background delivery

The user callback receives the H3 event, so it can read session data placed on event.context.

export const analytics = addilytics({
	endpoint: process.env.ADDILYTICS_ENDPOINT!,
	siteKey: process.env.ADDILYTICS_SITE_KEY!,
	user: (event) => event.context.user?.id
});

When Nitro exposes a platform waitUntil function, the adapter schedules delivery through Nitro's event.waitUntil(). On Node and other runtimes without a background-task hook, the afterResponse hook waits for delivery. Analytics failures never affect the application response.

Scope

This adapter requires Nitro's request and afterResponse hooks. It does not infer pageviews from render:response, because later response hooks may still change the status or content type. API, rendered, and static responses served by Nitro pass through afterResponse; only final HTML responses that match the core pageview rules are recorded. A CDN can serve prerendered files without invoking Nitro. Hybrid mode still requires the initial document request to reach Nitro; use client mode or CDN log ingestion if it does not. Nitro does not expose the original Web Response in this hook, so the adapter passes a status-and-headers snapshot to the core classifier and never touches the response body.