# insight: anonymous usage metrics for Node.js CLI tools

> insight is a Node.js module that reports anonymous usage metrics from a command line tool to Google Analytics or Yandex.Metrica, with a first-run permission prompt and an opt-out flag. It is in maintenance mode and sends events over the web tracking endpoint rather than the Measurement Protocol.

**sindresorhus/insight** — Node.js module to help you understand how your tool is being used by anonymously reporting usage metrics to Google Analytics

- Repository: https://github.com/sindresorhus/insight
- Stars: 555 · Forks: 52
- Language: JavaScript
- License: BSD-2-Clause
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/sindresorhus-insight

## It answers a question no changelog can: which commands people actually run

insight exists to help a tool author understand how the tool is being used, by anonymously reporting usage metrics to Google Analytics or Yandex.Metrica. The problem it solves is specific. A published CLI package accumulates versions and changelog entries, but nobody knows whether the command that took four releases to build is the one anyone uses. The README lists the data it is capable of collecting: the version of the module that implements Insight, module commands and events such as install or search, the name and version of packages involved with the command used, the version of Node.js and the OS for developer debugging, and a random and absolutely anonymous ID. Individual implementations can choose not to track some items, which is the granularity that makes it usable. The audience is a package maintainer who wants aggregate numbers rather than user identifiers, and the license is BSD-2-Clause.

## The tracking model is a URL path, which is why web tracking is required

The mechanism is worth understanding because it constrains everything else. Calling `insight.track('foo', 'bar')` ends up as a path in Analytics, and the README shows that `.track('init', 'backbone')` becomes `/init/backbone`. In other words, the keywords become the path of a page view, which is why the README says Insight should currently be used with GA set up as web tracking due to the use of URLs, and that future plans include refactoring to work with GA set up for app-based tracking and the Measurement Protocol. So this is a library that reports app usage by pretending to be a website. The consequence for an adopter is that a GA property configured for app-based tracking will not receive the data in a useful shape, and the workaround the README describes is a temporary one: set up custom dimensions for the OS version, Node.js version, and the version of the app that implements Insight.

## Installing it and wiring the first call takes two minutes

The install is one command, and the module is published on npm:

```sh
npm install insight
```

The package is an ES module, with `"type": "module"` and a single export at `./lib/index.js`, and it requires Node 18.18 or newer. The first use is a constructor with a tracking code and your package manifest:

```js
import Insight from 'insight';
import packageJson from './package.json' with {type: 'json'};

const insight = new Insight({
	// Google Analytics tracking code
	trackingCode: 'UA-XXXXXXXX-X',
	pkg: packageJson
});

// Ask for permission the first time
if (insight.optOut === undefined) {
	insight.askPermission();
}

insight.track('foo', 'bar');
// Recorded in Analytics as `/foo/bar`

insight.trackEvent({
	category: 'eventCategory',
	action: 'eventAction',
	label: 'eventLabel',
	value: 'eventValue'
});
// Recorded in Analytics behavior/events section
```

Two details in that snippet are the whole opt-in story. The `insight.optOut === undefined` check is how the library distinguishes a user who has never been asked from one who has answered, and `insight.askPermission()` is what puts the prompt on screen and records the answer in the configuration store.

## The permission prompt writes an optOut flag you can also set by hand

The API section describes `askPermission(message?)` as asking the user permission to opt in to tracking and setting the `optOut` property in `config`. You can supply your own message, and if the message is null the default message is used. The method also resolves with the new value of `optIn` when the prompt is done, which the README notes is useful when you want to continue the execution while the prompt is running. The `.optOut` accessor returns a boolean whether the user has opted out of tracking, and the README is careful that it should preferably only be set by a user action, for example a prompt. In other words, the module refuses to decide for you whether to track, and the CLI is expected to make the first run an interactive one. That is a design choice with a cost, since it means the tracking code cannot run in a fully non-interactive context without an explicit decision.

## Yandex.Metrica is the second provider, and events do not work with it

The `trackingProvider` option takes the string `'google'` or `'yandex'` and defaults to `'google'`. The Yandex setup differs in the constructor, which takes a counter id rather than a tracking code, and in the URL shape, since the recorded path becomes `http://<package-name>.insight/foo/bar`:

```js
import Insight from 'insight';
import packageJson from './package.json' with {type: 'json'};

const insight = new Insight({
	// Yandex.Metrica counter id
	trackingCode: 'XXXXXXXXX'
	trackingProvider: 'yandex',
	pkg: packageJson
});

// Ask for permission the first time
if (insight.optOut === undefined) {
	insight.askPermission();
}

insight.track('foo', 'bar');
// Recorded in Yandex.Metrica as `http://<package-name>.insight/foo/bar`
```

The limitation to note is stated plainly in the API section: `trackEvent` does not work with Yandex.Metrica. The richer event model, with category, action, label and an integer value, is a Google Analytics concept, so a Yandex user is limited to the path-based tracking. That is a real difference in what you can measure between the two providers, and it is easy to discover late.

## The configuration store is swappable if conf is not what you want

Persistence is handled by an object in the `config` option, and the default is an instance of the `conf` package. The README explains that if you want your own configuration mechanism you can provide an object that has to implement two synchronous methods, `get(key)` and `set(key, value)`. That is a small, clean seam, and it matters more than it looks, because the opt-out decision has to live somewhere on disk for the check on the first run to mean anything. The dependencies list shows the supporting cast: `ky` for the HTTP requests, `inquirer` for the prompt, `chalk` for the prompt styling, `os-name` for the OS version, and `lodash.debounce` to keep rapid repeated calls from turning into a burst of requests.

## Where insight is the wrong tool

Three limits are concrete. The first is that the package is in maintenance mode, with the README stating that no new features will be added. The last release was v0.12.0 on 2025-01-26, after v0.11.1 in 2021 and v0.11.0 in 2021, and the last push was on 2026-09-18, so the release cadence has already slowed and the project is not being extended. The second is the privacy and architecture issue that the README itself frames as temporary: because the tracking is web tracking, the events pass through a Google Analytics property that you configure, and the custom-dimension workaround for OS, Node.js and app versions is explicitly described as a temporary solution until the app-based refactor happens, which in maintenance mode it will not. The third is that the tool only works when the network and the analytics property cooperate. A CLI used on a locked-down machine, offline, or behind a proxy that blocks Google, will silently produce no data, and a maintainer who reads an empty dashboard may draw the wrong conclusion about their users.

## A self-hosted collector is the different approach

The realistic alternative is to skip the third-party analytics property and send the same events to a collector you control. The difference in approach is where the data lands and who can see it. With insight, a page view carrying your package name and version goes to a GA property, and reading the aggregate numbers requires a GA account and the permissions that come with it. With a self-hosted endpoint, the same payload shape, essentially a path plus a random anonymous identifier, is posted to a service under your control, and you get raw data you can query, diff over time, and delete. The trade-off is that you have to build or run the receiver, whereas insight hands you a working receiver in exchange for the dependency on Google. The middle path that insight itself models is the custom dimension setup, where the debug fields travel as GA custom dimensions, which keeps the reporting familiar at the cost of staying inside the same web tracking model.

## Conclusion

insight fits a maintainer of a command line tool who wants a rough count of which commands and package versions people actually run, and who is comfortable with the trade-off of sending that to a third-party analytics property. It is the wrong tool for a package with sensitive usage data, since the tracking code is yours and every event passes through it, and it is the wrong tool for a tool that must work offline or behind a restrictive network. Before you adopt it, note that the README marks the package as in maintenance mode with no new features, that the last release was v0.12.0 on 2025-01-26 with the last push on 2026-09-18, and that Google Analytics web tracking is the only provider path that works today.

## FAQ

### How do I install insight?

Run `npm install insight`. The package is an ES module published on npm with the export at `./lib/index.js`, and it requires Node 18.18 or newer.

### Does insight ask the user before tracking anything?

Yes. The intended pattern is to check `if (insight.optOut === undefined)` on the first run and then call `insight.askPermission()`, which prompts the user and writes the `optOut` value into the configuration store. You can also set the `optOut` property in the configuration manually.

### Can I send events to Yandex.Metrica instead of Google Analytics?

Yes, by passing `trackingProvider: 'yandex'` and a Yandex.Metrica counter id as the tracking code. Note that `trackEvent` does not work with Yandex.Metrica, so the path-based `track` calls are the only option there.

### Is insight still being developed?

The README states the package is in maintenance mode and that no new features will be added. The last release was v0.12.0 on 2025-01-26, and the last push to the repository was on 2026-09-18.

## Sources

- [Issues](https://github.com/sindresorhus/insight/issues)
- [License: BSD-2-Clause](https://github.com/sindresorhus/insight/blob/main/LICENSE)
- [README](https://github.com/sindresorhus/insight/blob/main/README.md)
- [Releases](https://github.com/sindresorhus/insight/releases)
- [sindresorhus/insight on GitHub](https://github.com/sindresorhus/insight)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sindresorhus-insight
