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

@mostly-good-metrics/javascript

v0.7.0

Published

JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications

Readme

MostlyGoodMetrics JavaScript SDK

A lightweight JavaScript/TypeScript SDK for tracking analytics events with MostlyGoodMetrics.

Requirements

  • Node.js 16+ (for build tools)
  • Modern browser with ES2020 support, or Node.js runtime

Installation

npm install @mostly-good-metrics/javascript

Or with yarn:

yarn add @mostly-good-metrics/javascript

Quick Start

1. Initialize the SDK

Initialize once at app startup:

import { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';

MostlyGoodMetrics.configure({
  apiKey: 'mgm_proj_your_api_key',
});

2. Track Events

// Simple event
MostlyGoodMetrics.track('button_clicked');

// Event with properties
MostlyGoodMetrics.track('purchase_completed', {
  product_id: 'SKU123',
  price: 29.99,
  currency: 'USD',
});

3. Identify Users

// Set user identity (optional - anonymous ID is auto-generated)
MostlyGoodMetrics.identify('user_123');

// Reset identity (e.g., on logout)
MostlyGoodMetrics.resetIdentity();

That's it! Events are automatically batched and sent.

User Identification

The SDK automatically generates and persists an anonymous user_id (UUID) for each user. This ID:

  • Is auto-generated on first visit
  • Persists across sessions (stored in cookies and localStorage)
  • Is included in every event as user_id

When you call identify(), the identified user ID takes precedence over the anonymous ID.

// Before identify(): user_id = "550e8400-e29b-41d4-a716-446655440000" (auto-generated)
MostlyGoodMetrics.identify('user_123');
// After identify(): user_id = "user_123"

MostlyGoodMetrics.resetIdentity();
// After reset: user_id = "550e8400-e29b-41d4-a716-446655440000" (back to anonymous)

Cross-Subdomain Tracking

By default, the anonymous ID is stored in cookies (with localStorage fallback). To share the anonymous ID across subdomains:

MostlyGoodMetrics.configure({
  apiKey: 'mgm_proj_your_api_key',
  cookieDomain: '.yourdomain.com', // Share across all subdomains
});

This allows tracking the same user across app.yourdomain.com, www.yourdomain.com, etc.

Privacy Mode (No Cookies)

For GDPR compliance or privacy-focused applications, you can disable cookies entirely:

MostlyGoodMetrics.configure({
  apiKey: 'mgm_proj_your_api_key',
  disableCookies: true, // Only use localStorage
});

Configuration Options

For more control, pass additional configuration:

MostlyGoodMetrics.configure({
  apiKey: 'mgm_proj_your_api_key',
  baseURL: 'https://mostlygoodmetrics.com',
  environment: 'production',
  appVersion: '1.0.0',
  maxBatchSize: 100,
  flushInterval: 30,
  maxStoredEvents: 10000,
  enableDebugLogging: process.env.NODE_ENV === 'development',
  trackAppLifecycleEvents: true,
});

| Option | Default | Description | |--------|---------|-------------| | apiKey | - | Required. Your API key | | baseURL | https://mostlygoodmetrics.com | API endpoint | | environment | "production" | Environment name | | appVersion | - | App version string (required for install/update tracking) | | maxBatchSize | 100 | Events per batch (1-1000) | | flushInterval | 30 | Auto-flush interval in seconds | | maxStoredEvents | 10000 | Max cached events | | enableDebugLogging | false | Enable console output | | trackAppLifecycleEvents | false | Auto-track lifecycle events ($app_opened, etc.) | | bundleId | auto-detected | Custom bundle identifier | | cookieDomain | - | Cookie domain for cross-subdomain tracking (e.g., .example.com) | | disableCookies | false | Disable cookies, use only localStorage | | anonymousId | auto-generated | Override anonymous ID (for wrapper SDKs like React Native) | | storage | auto-detected | Custom storage adapter | | networkClient | fetch-based | Custom network client |

Automatic Events

When trackAppLifecycleEvents is enabled, the SDK automatically tracks:

| Event | When | Properties | |-------|------|------------| | $app_installed | First visit (localStorage) | $version | | $app_updated | Version change detected | $version, $previous_version | | $app_opened | Page load / tab visible | - | | $app_backgrounded | Tab hidden / page unload | - |

Note: Install and update detection require appVersion to be configured.

Automatic Properties

The SDK automatically includes these properties with every event:

| Property | Description | |----------|-------------| | $device_type | Device type (desktop, phone, tablet) | | $device_model | Browser name and version |

Additionally, osVersion and appVersion (if configured) are included at the event level.

Event Naming

Event names must:

  • Start with a letter (or $ for system events)
  • Contain only alphanumeric characters and underscores
  • Be 255 characters or less
// Valid
MostlyGoodMetrics.track('button_clicked');
MostlyGoodMetrics.track('PurchaseCompleted');
MostlyGoodMetrics.track('step_1_completed');

// Invalid (will be ignored)
MostlyGoodMetrics.track('123_event');      // starts with number
MostlyGoodMetrics.track('event-name');     // contains hyphen
MostlyGoodMetrics.track('event name');     // contains space

Properties

Events support various property types:

MostlyGoodMetrics.track('checkout', {
  string_prop: 'value',
  int_prop: 42,
  double_prop: 3.14,
  bool_prop: true,
  null_prop: null,
  list_prop: ['a', 'b', 'c'],
  nested: {
    key: 'value',
  },
});

Limits:

  • String values: truncated to 1000 characters
  • Nesting depth: max 3 levels
  • Total properties size: max 10KB

Manual Flush

Events are automatically flushed periodically and when the page is hidden. You can also trigger a manual flush:

await MostlyGoodMetrics.flush();

To check pending events:

const count = await MostlyGoodMetrics.getPendingEventCount();
console.log(`${count} events pending`);

Automatic Behavior

The SDK automatically:

  • Generates anonymous user ID (UUID, persisted in cookies + localStorage)
  • Persists events to localStorage (with in-memory fallback)
  • Batches events for efficient network usage
  • Flushes on interval (default: every 30 seconds)
  • Flushes on visibility change when the tab is hidden
  • Compresses payloads using gzip for large batches (>1KB)
  • Retries on failure for network errors (events are preserved)
  • Handles rate limiting with exponential backoff
  • Persists identified user ID across page loads
  • Generates session IDs per page load

Debug Logging

Enable debug logging to see SDK activity:

MostlyGoodMetrics.configure({
  apiKey: 'mgm_proj_your_api_key',
  enableDebugLogging: true,
});

Output example:

[MostlyGoodMetrics] [INFO] MostlyGoodMetrics initialized with environment: production
[MostlyGoodMetrics] [DEBUG] Tracking event: button_clicked
[MostlyGoodMetrics] [DEBUG] Starting flush
[MostlyGoodMetrics] [DEBUG] Successfully sent 5 events

Custom Storage

You can provide a custom storage adapter for environments where localStorage isn't available:

import { MostlyGoodMetrics, IEventStorage, InMemoryEventStorage } from '@mostly-good-metrics/javascript';

// Use in-memory storage
MostlyGoodMetrics.configure({
  apiKey: 'mgm_proj_your_api_key',
  storage: new InMemoryEventStorage(10000),
});

// Or implement your own
class MyCustomStorage implements IEventStorage {
  async store(event: MGMEvent): Promise<void> { /* ... */ }
  async fetchEvents(limit: number): Promise<MGMEvent[]> { /* ... */ }
  async removeEvents(count: number): Promise<void> { /* ... */ }
  async eventCount(): Promise<number> { /* ... */ }
  async clear(): Promise<void> { /* ... */ }
}

Framework Integration

React

// src/analytics.ts
import { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';

export function initAnalytics() {
  MostlyGoodMetrics.configure({
    apiKey: process.env.REACT_APP_MGM_API_KEY!,
    environment: process.env.NODE_ENV,
    appVersion: process.env.REACT_APP_VERSION,
  });
}

// src/index.tsx
import { initAnalytics } from './analytics';
initAnalytics();

Next.js

// lib/analytics.ts
import { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';

export function initAnalytics() {
  if (typeof window !== 'undefined') {
    MostlyGoodMetrics.configure({
      apiKey: process.env.NEXT_PUBLIC_MGM_API_KEY!,
      environment: process.env.NODE_ENV,
    });
  }
}

// app/layout.tsx or pages/_app.tsx
'use client';
import { useEffect } from 'react';
import { initAnalytics } from '@/lib/analytics';

export default function RootLayout({ children }) {
  useEffect(() => {
    initAnalytics();
  }, []);

  return <html>...</html>;
}

Vue

// src/plugins/analytics.ts
import { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';

export default {
  install() {
    MostlyGoodMetrics.configure({
      apiKey: import.meta.env.VITE_MGM_API_KEY,
      environment: import.meta.env.MODE,
    });
  }
};

// src/main.ts
import analytics from './plugins/analytics';
app.use(analytics);

TypeScript Support

Full TypeScript support with exported types:

import {
  MostlyGoodMetrics,
  MGMConfiguration,
  MGMEvent,
  EventProperties,
  IEventStorage,
  INetworkClient,
} from '@mostly-good-metrics/javascript';

License

MIT