Analytics built for browser extensions.
One ~3 KB SDK for installs, active users, and custom events — across Chrome, Firefox, Edge, VS Code and more. Zero dependencies. No user tracking.
npm install extstat · free for 10,000 events / month
Why extstat
Cross-store, one SDK
Chrome, Firefox, and Edge (MV3), plus VS Code and Figma. Write once; measure everywhere.
Tiny & zero-dependency
~2.9 KB minified, ~1.2 KB gzipped. No dependencies, safe inside an MV3 service worker. Bundle size is a feature.
Privacy-first by design
No personal data, no cookies, no fingerprinting. Honors Do Not Track and a one-line opt-out — GDPR-friendly out of the box.
The metrics that matter
The full lifecycle — installs, updates, uninstalls, sessions — plus daily & weekly active users (DAU/WAU), unique clients, and your own events, filterable by date range.
Up and running in three steps
- Create a project in the dashboard and copy your API key.
- Install & init the SDK in your extension's background script.
- Track events — they appear in your dashboard within seconds.
import { init } from "extstat";
const analytics = init({
apiKey: "esk_your_project_key", // from your dashboard
endpoint: "https://ingest.extstat.dev/v1/e",
});
analytics.track("install");
analytics.track("feature_used", { feature: "export" });That's the whole integration. The SDK batches events, persists them offline, and retries on its own.
Show more — events, examples & opt-out
What the dashboard measures
install·update·uninstall— your lifecycle metrics: unique installs, updates, and uninstalls (counted per device). See the snippet below — uninstall is special, since your code can't run when the extension is removed.session— Sessions: total engagement volume (counts every event, not unique devices).- Active users (DAU/WAU) & unique clients — automatic, and defined plainly: DAU = unique clients active in the last day, WAU = the last 7 days ("active" = sent any event). extstat assigns a random, persistent client id — no fingerprinting.
- Total events — everything you send.
- Custom events — any other name + properties. They still feed the active-user metrics and totals; name them whatever fits your extension.
Track the full lifecycle
// background.js — your MV3 service worker
// Installs & updates fire from the lifecycle hook:
chrome.runtime.onInstalled.addListener(({ reason }) => {
if (reason === "install") analytics.track("install");
else if (reason === "update") {
analytics.track("update", { version: chrome.runtime.getManifest().version });
}
});
// Uninstall is the one event you can't track() — your code is gone on removal.
// Point Chrome at the SDK's uninstall URL; it records the "uninstall" for you:
analytics.uninstallUrl().then((url) => {
if (url) chrome.runtime.setUninstallURL(url);
});
// A session = your extension becoming active. Fire on startup (and/or popup open):
chrome.runtime.onStartup.addListener(() => analytics.track("session"));Track your own events
// Fire your own events whenever something happens. Properties
// (a flat object) let you slice the event in the dashboard later.
analytics.track("export_completed", { format: "csv", rows: 128 });
button.addEventListener("click", () => {
analytics.track("upgrade_clicked", { plan: "pro" });
});Let users opt out
const analytics = init({
apiKey: "esk_your_project_key",
endpoint: "https://ingest.extstat.dev/v1/e",
disabled: userOptedOut, // one-line opt-out (wire to a setting)
// respectDoNotTrack defaults to true — sends nothing under DNT
});Simple pricing
Free
$0/month
- 10,000 events / month
- Unlimited projects
- All metrics & date ranges
- Privacy features included