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

@metricflow-ai/web

v0.1.1

Published

MetricFlow browser analytics SDK for event tracking, user identification, and behavioral analytics.

Readme

MetricFlow Browser SDK

A browser analytics SDK for tracking events, identifying users, and capturing behaviour on any web app.


Table of Contents


Installation

npm install @metricflow-ai/web

Quick Start

import { metricflow } from "@metricflow-ai/web";

await metricflow.init("YOUR_PROJECT_ID", {
  track_pageview: true,
  autocapture: false,
  debug: true,
});

metricflow.identify("user_123", {
  email: "[email protected]",
  name: "Alex Kumar",
  plan: "free",
});

metricflow.track("signup_started", {
  plan: "free",
});

Configuration

init(projectId, config?)projectId (first argument) is required. The config object (second argument) is entirely optional; every field below has a working default.

await metricflow.init("YOUR_PROJECT_ID", {
  persistence: "localStorage",
  batch_requests: true,
  batch_size: 20,
  batch_flush_interval_ms: 3000,
  track_pageview: true,
  autocapture: false,
  debug: false,
});

| Field | Type | Required? | Description | | --- | --- | --- | --- | | projectId | string | Required (first argument to init(), not part of the config object) | Your MetricFlow project ID. | | endpoint | string | Optional | Full /api/track URL. Only needed to point at a custom ingestion endpoint — most integrations don't need this. | | api_host | string | Optional | API origin, e.g. https://api.example.com. Used when endpoint is not set. | | persistence | "cookie" | "localStorage" | Optional | Where to store identity and super properties. Default: "localStorage". | | batch_requests | boolean | Optional | Batch events before sending. Default: true. | | batch_size | number | Optional | Number of events per batch flush. | | batch_flush_interval_ms | number | Optional | Auto-flush interval in milliseconds. | | track_pageview | boolean \| string | Optional | true, "url-with-path", "url-with-path-and-query-string", or "full-url". Controls automatic pageview tracking. | | autocapture | boolean \| object | Optional | Default false. Enable automatic click/input/form/scroll capture. | | debug | boolean | Optional | Print SDK logs to the browser console. |


Core API

track(eventName, properties?)

Track any custom event.

metricflow.track("button_clicked", {
  label: "Start Trial",
  location: "hero",
});

track_pageview(properties?, options?)

Manually track a pageview. Useful in SPAs where the URL changes without a full page reload.

metricflow.track_pageview({ page_title: document.title });

// Track with full URL mode
metricflow.track_pageview({}, { mode: "full-url" });

time_event(eventName)

Start timing an event. The next track() call with the same event name will include a duration_ms property.

metricflow.time_event("checkout_completed");

// later...
metricflow.track("checkout_completed", { amount: 49 });
// → event includes duration_ms automatically

Identity

identify(userId, traits?)

Link future events to a known user. Call this after login.

metricflow.identify("user_123", {
  email: "[email protected]",
  name: "Alex Kumar",   // use "name" key — not "fullName" or "displayName"
  plan: "pro",
});

Reserved trait keys (used by the Users list):

| Trait key | Example | Notes | | --- | --- | --- | | name | "Alex Kumar" | Primary display name. | | email | "[email protected]" | Primary email. |

Optional common traits:

| Trait key | Example | | --- | --- | | first_name | "Alex" | | last_name | "Kumar" | | phone | "+15551234567" | | plan | "pro" | | role | "admin" | | company | "Acme" | | created_at | "2026-06-24T10:00:00Z" |

reset()

Clear current user identity and session. Always call this on logout.

metricflow.reset();

After reset, the SDK assigns a new anonymous ID — the next identify() starts a fresh user.

alias(newId, originalId?)

Merge two identities (anonymous pre-login → known post-login).

metricflow.alias("user_123");

get_distinct_id()

Read the current distinct ID (anonymous or identified).

const id = metricflow.get_distinct_id();

Super Properties

Super properties are stored in the browser and automatically merged into every future event.

// Set on every event from now on
metricflow.register({
  app_version: "1.2.0",
  org_id: "org_456",
});

// Set only if not already set
metricflow.register_once({
  first_landing_page: window.location.pathname,
});

// Remove a super property
metricflow.unregister("org_id");

// Read a super property
const version = metricflow.get_property("app_version");

User Profile API

Update profile properties independently of event tracking.

metricflow.people.set({ plan: "pro", role: "admin" });

metricflow.people.set_once({ first_seen_at: new Date().toISOString() });

metricflow.people.increment("login_count", 1);

metricflow.people.append("recent_actions", "opened_dashboard");

metricflow.people.union("features_used", "autocapture");

metricflow.people.unset(["temporary_flag"]);

Revenue tracking:

metricflow.people.track_charge(49, { currency: "USD", plan: "pro" });

metricflow.people.clear_charges();

metricflow.people.delete_user();

Auto-Captured Properties

Every event automatically includes these properties — you do not need to set them manually.

| Property | Example value | Description | | --- | --- | --- | | lib | "metricflow-js" | SDK name. | | lib_version | "1.0.0" | SDK version. | | platform | "Web" | Always "Web" for browser SDK. | | browser | "Chrome" | Detected browser. | | browser_version | "120" | Detected browser version. | | os | "Windows" | Detected OS. | | device | "Desktop" | "Mobile" | Device type. | | language | "en-US" | Browser language. | | screen_width | 1440 | Screen width in pixels. | | screen_height | 900 | Screen height in pixels. | | viewport_width | 1440 | Viewport width in pixels. | | viewport_height | 765 | Viewport height in pixels. | | pathname | "/dashboard" | Current page pathname. | | host | "app.example.com" | Current page host. | | referring_domain | "google.com" | Domain of the referrer page. | | timezone | "Asia/Calcutta" | Browser timezone. | | search_engine | "google" | Detected search engine (if referrer is a search engine). | | search_keyword | "analytics tool" | Search keyword (if referrer is a search engine). |


Autocapture

Autocapture is off by default. Enable it only when you want automatic interaction tracking.

// Disabled (default) — only manual track() calls fire
await metricflow.init("PROJECT_ID", { autocapture: false });

// Enabled — captures clicks, inputs, forms, and scroll depth automatically
await metricflow.init("PROJECT_ID", {
  autocapture: true,
  track_pageview: true,
});

With autocapture: true, the SDK fires:

| Event | Trigger | | --- | --- | | $mf_click | Any element click | | $mf_form_submit | Form submission | | $mf_input | Input / select / textarea change (values not captured) | | $mf_scroll | Scroll depth checkpoints |

Granular Autocapture Config

await metricflow.init("PROJECT_ID", {
  track_pageview: "url-with-path",
  autocapture: {
    click: true,
    input: true,
    submit: true,
    scroll: true,
    scroll_depth_percent_checkpoints: [25, 50, 75, 100],
    rage_click: true,
    dead_click: true,
    capture_text_content: false,
  },
});

| Option | Default | Description | | --- | --- | --- | | click | true | Capture clicks. | | input | true | Capture input/select/textarea changes. Values are not captured. | | submit | true | Capture form submissions. | | scroll | true | Capture scroll depth checkpoints. | | scroll_depth_percent_checkpoints | [25, 50, 75, 100] | Which scroll percentages trigger events. | | scroll_capture_all | false | Fire on every throttled scroll instead of checkpoints only. | | page_leave | false | Flush pending events when the user leaves the page. | | rage_click | false | Detect repeated nearby clicks. | | dead_click | false | Detect clicks that do not navigate or change state. | | capture_text_content | false | Include element text for non-sensitive elements. |


Privacy Controls

Add any of these CSS classes to an element to block autocapture on it:

<button class="metricflow-no-track">Not captured</button>
<button class="mf-no-track">Not captured</button>
<button class="mp-no-track">Not captured</button>

Block or allow elements and URLs via config:

await metricflow.init("PROJECT_ID", {
  autocapture: {
    block_selectors: [".sensitive", "[data-private='true']"],
    allow_selectors: [".analytics-allowed"],
    block_url_regexes: [/\/checkout/],
    capture_text_content: false,
    block_element_callback: element => element.hasAttribute("data-no-track"),
  },
});

Opt In / Opt Out

metricflow.opt_out_tracking();           // stop tracking
metricflow.has_opted_out_tracking();     // → true

metricflow.opt_in_tracking();            // resume tracking
metricflow.has_opted_in_tracking();      // → true

metricflow.clear_opt_in_out_tracking();  // clear persisted preference

When opted out, no events are queued or sent.


Link and Form Helpers

Attach tracking to specific elements without writing individual listeners.

metricflow.track_links("a.pricing-link", "pricing_link_clicked", {
  area: "header",
});

metricflow.track_forms("form.newsletter", "newsletter_submitted", {
  source: "footer",
});

Common Patterns

Login flow

// After successful login
metricflow.identify(String(user.id), {
  name: `${user.first_name} ${user.last_name}`,
  email: user.email,
});

metricflow.register({
  org_id: user.orgId,
  user_role: user.role,
});

metricflow.track("user_logged_in");

Logout flow

metricflow.track("user_logged_out");

// Always reset on logout — clears identity and session
metricflow.reset();

SPA pageview tracking (Next.js / React Router)

// Call on every route change instead of using track_pageview: true
metricflow.track_pageview({ page_title: document.title });

Public Methods Reference

| Method | Purpose | | --- | --- | | init(projectId, config?) | Initialize the SDK. Call before anything else — calls made earlier are buffered and replayed once init() resolves, but relying on that isn't recommended. | | track(eventName, properties?) | Track a custom event. | | track_pageview(properties?, options?) | Track a pageview manually. | | time_event(eventName) | Start timing an event. | | identify(userId, traits?) | Link events to a known user. Call after login. | | alias(newId, originalId?) | Merge two identities. | | reset() | Clear identity and session state. Call on logout. | | get_distinct_id() | Read the current distinct ID. | | register(properties) | Set persistent super properties. | | register_once(properties, defaultValue?) | Set super properties only if not already set. | | unregister(propertyName) | Remove a super property. | | get_property(propertyName) | Read a super property value. | | opt_in_tracking() | Resume event tracking. | | opt_out_tracking() | Stop event tracking. | | has_opted_in_tracking() | Check if user has explicitly opted in. | | has_opted_out_tracking() | Check if user has opted out. | | clear_opt_in_out_tracking() | Clear persisted opt-in/out state. | | get_config(key?) | Read current SDK config. | | set_config(config) | Update SDK config at runtime. | | track_links(query, eventName, properties?) | Attach click tracking to matched elements. | | track_forms(query, eventName, properties?) | Attach submit tracking to matched forms. | | push(command) | Run a queued snippet-style command. | | flush() | Immediately flush all queued events. | | people.set(properties) | Set user profile properties. | | people.set_once(properties) | Set profile properties only if not already set. | | people.unset(properties) | Remove profile properties. | | people.increment(property, value?) | Increment a numeric profile property. | | people.append(property, value?) | Append a value to a profile list property. | | people.union(property, value?) | Add unique values to a profile list property. | | people.track_charge(amount, properties?) | Track a revenue charge. | | people.clear_charges() | Clear stored charges. | | people.delete_user() | Delete the user profile. |


License

MIT — see LICENSE.