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

reova

v0.7.0

Published

Opt-in npm install analytics: sends install metrics to an endpoint you configure.

Readme

reova

Lightweight, opt-in install telemetry for npm packages. After someone installs your package, reova can report a small set of signals — enough to see where adoption is happening and which organizations are pulling your library — to an analytics endpoint you choose.

Nothing is sent unless a consuming package turns it on and sets that endpoint. Never blocks an install.

Setup

Add reova as a dependency and configure it in your package.json:

{
  "name": "your-package",
  "version": "1.0.0",
  "reova": {
    "enabled": true,
    "endpoint": "https://analytics.your-domain.com/data"
  },
  "dependencies": {
    "reova": "^0.7.0"
  }
}

Both enabled: true and a valid endpoint are requiredreova sends nothing until both are set. There is no default endpoint.

Configuration

| Key | Location | Required | Description | |-----|----------|:--------:|-------------| | enabled | package.jsonreova.enabled | yes | true to opt in. Anything else = disabled. | | endpoint | package.jsonreova.endpoint | yes | Where events are POSTed. http/https only. No default. |

Flags (environment variables)

| Variable | Effect | |----------|--------| | REOVA_ENDPOINT | Override the endpoint. | | REOVA_ENABLED=true | Force-enable (still requires an endpoint). | | REOVA_ANALYTICS=false | Global kill-switch — disables everything. | | DO_NOT_TRACK=1 | Also disables everything. | | REOVA_VERBOSE=true | Log what is sent to the console. |

Programmatic usage

Besides the automatic install-time event, you can import reova and send the same event yourself, at a time of your choosing.

track() is non-blocking by default — the POST is fired in the background, so it never blocks your callers even if the endpoint is slow or unreachable, and it never keeps a short-lived process alive. It returns true (queued) / false (opted out or no endpoint) almost immediately.

CommonJS:

const reova = require('reova');

// Fire-and-forget (default) — never blocks, safe on request/hot paths:
reova.track({
  endpoint: 'https://analytics.your-domain.com/data', // or reova.endpoint / REOVA_ENDPOINT
  packageName: 'your-package',        // optional overrides
  packageVersion: '1.0.0',
  activityType: 'feature_used',       // optional, defaults to 'npm_install'
  properties: { feature: 'checkout' } // optional extra fields
});

ESM:

import reova from 'reova';

reova.track({
  endpoint: 'https://analytics.your-domain.com/data',
  activityType: 'feature_used',
  properties: { feature: 'checkout' }
});

Want to wait for the network result (e.g. a CLI/cron that must confirm delivery before exiting)? Pass blocking: true:

const result = await reova.track({ blocking: true, endpoint: '…' });
// result → { success: true, statusCode: 200 }  (or { success: false, ... })

Send only once (ever)

Use once: true to send an event at most once per machine, even across restarts — e.g. a first-launch / activation signal:

reova.track({
  once: true,
  onceKey: 'first-launch',   // distinct key per once-event (default: package name)
  endpoint: 'https://analytics.your-domain.com/data'
});
  • A small marker is stored under ~/.reova (override with REOVA_STATE_DIR), keyed by onceKey.
  • The marker is written only on confirmed delivery, so a failed send retries on a later call rather than being lost.
  • If it has already been delivered, track() returns false and sends nothing.
  • Use a distinct onceKey for each independent once-event. To reset, delete the marker file(s) under ~/.reova.

Survives version upgrades and reinstalls. Because the marker lives in ~/.reova (outside node_modules) and the default onceKey is version-independent, upgrading your package — or deleting node_modules and reinstalling — does not re-fire the event. "Once ever" means once ever on that machine.

Want it once per version instead? Put the version in the key, so each new release is a fresh once-event:

const { version } = require('./package.json');

reova.track({
  once: true,
  onceKey: `first-launch@${version}`, // fires once per version (re-fires on upgrade)
  endpoint: 'https://analytics.your-domain.com/data'
});

⚠️ With once + non-blocking in a short-lived process, use blocking: true so the marker is written before the process exits (otherwise the detached send may be abandoned and the marker not recorded, causing a resend next run).

  • Importing has no side effects — it does not run the postinstall or exit the process.
  • Calling track() is the opt-in, so it does not require reova.enabled. It still honors the global kill-switches (REOVA_ANALYTICS=false / DO_NOT_TRACK) and still requires an endpoint (option, reova.endpoint, or REOVA_ENDPOINT).
  • Same payload as the automatic flow; best-effort and never throws.

The automatic postinstall flow is unchanged.

Opt out

REOVA_ANALYTICS=false npm install
# or
DO_NOT_TRACK=1 npm install

On install, reova sends the package name/version, OS/arch/Node version, a CI flag, a random per-event id, and your git email domain (domain only, e.g. company.com — never the full address) to the configured endpoint. It is best-effort and never blocks or delays an install.

License

MIT