Skip to main content

JavaScript SDK

A lightweight JavaScript/TypeScript SDK for web applications.

Requirements​

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

Installation​

Use JavaScript SDK 0.13.1 or later for the exception containment and bounded event storage described below.

npm install @mostly-good-metrics/javascript@^0.13.1

Quick Start​

Initialize​

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

MostlyGoodMetrics.configure({
apiKey: 'mgm_proj_your_api_key',
trackPageViews: true, // Enable the Web Analytics overview
});

Track Events​

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

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

Identify Users​

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

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

User Identification​

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

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

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

Cross-Subdomain Tracking​

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

Privacy Mode (No Cookies)​

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

Configuration Options​

MostlyGoodMetrics.configure({
apiKey: 'mgm_proj_your_api_key',
baseURL: 'https://ingest.mostlygoodmetrics.com',
environment: 'production',
appVersion: '1.0.0',
maxBatchSize: 100,
flushInterval: 30,
maxStoredEvents: 10000,
enableDebugLogging: process.env.NODE_ENV === 'development',
trackAppLifecycleEvents: true,
trackPageViews: true,
});
OptionDefaultDescription
apiKeyRequiredYour API key
baseURLhttps://ingest.mostlygoodmetrics.comAPI endpoint
environment"production"Environment name
appVersion-App version (required for install/update tracking)
maxBatchSize100Events per batch
flushInterval30Auto-flush interval in seconds
enableDebugLoggingfalseEnable console output
trackAppLifecycleEventsfalseAuto-track lifecycle events
trackPageViewsfalseCapture initial and SPA page views plus visible-page engagement
sessionTimeoutMinutes30Start a new website visit after this many inactive minutes
existingInstallationfalseBaseline lifecycle state on a provider migration without emitting $app_installed
contextProvider-Dynamic properties evaluated for every event; precedence is super properties, context, event properties, then MGM system properties
cookieDomain-Cookie domain for cross-subdomain tracking
disableCookiesfalseDisable cookies, use only localStorage
persistence'localStorage+cookie'Where state persists: 'localStorage+cookie', 'localStorage', or 'memory'
respectDoNotTrackfalseTreat browsers with DNT or GPC enabled as opted out (Privacy)
optedOutByDefaultfalseStart opted out until optIn() is called (Privacy)
collectDevicePropertiestrueCollect device properties

Automatic Events​

Website analytics​

Set trackPageViews: true to capture an initial page_view, History API and back/forward navigation, and $page_engagement when the current page becomes hidden. This powers the Web Analytics screen without replacing your product events.

Page views include the URL, hostname, pathname, title, referrer/referring domain, and UTM campaign values. Browser sessions continue across reloads and navigation, then renew after 30 minutes of inactivity. The SDK also attaches browser, OS, device, screen, viewport, and user-agent context unless collectDeviceProperties is disabled.

When trackAppLifecycleEvents is enabled:

EventWhenProperties
$app_installedFirst visit (localStorage)$version
$app_updatedVersion change detected$version, $previous_version
$app_openedPage load / tab visible-
$app_backgroundedTab hidden / page unload-

Migration and dynamic context​

For an existing site moving from another provider, derive existingInstallation from that provider's persisted install marker. Do not set it to true for all users: that would suppress genuine new installs.

MostlyGoodMetrics.configure({
apiKey: 'mgm_proj_your_api_key',
existingInstallation: legacyAnalytics.hasInstallationMarker(),
contextProvider: () => ({ active_workspace_id: currentWorkspaceId() }),
});

contextProvider runs for every event. Its values override super properties; explicit event properties and MGM system properties take precedence. With enableDebugLogging, MGM warns when custom properties use reserved $ keys.

Callback and failure handling​

contextProvider runs synchronously on the JavaScript caller. Return ordinary JSON-like values; asynchronous providers are unsupported. Provider exceptions are contained, unreadable property getters are omitted, and traversal of nested objects and arrays is bounded. Properties are copied at capture time, including super properties.

Automatic batch, timer, and page-exit work handles storage and network failures internally. If an error callback returns a rejected promise, MGM observes that rejection without waiting for the callback to complete. Explicitly awaited operations retain their failure contract for custom adapters:

try {
await MostlyGoodMetrics.flush();
} catch (error) {
// Handle an unexpected failure from a custom storage or network adapter.
}

Also handle promises returned by clearPendingEvents() and getPendingEventCount() when using custom adapters.

Built-in event stores enforce a 1 MiB serialized event-data ceiling as well as maxStoredEvents. They drop the oldest events when either limit is reached and reject oversized persisted queues before parsing. Analytics can be dropped to protect the host during long offline periods; a custom storage adapter must enforce its own resource limits.

Call MostlyGoodMetrics.reset() when tearing down the singleton. This stops its timers, removes browser hooks, and aborts its built-in network requests. Late responses from the destroyed instance cannot update its experiment cache.

Privacy​

The SDK collects no advertising identifiers or precise client location. identify() is optional — without it, users are tracked under a random, resettable anonymous ID ($anon_...). Automatic browser/device context is documented above and can be disabled with collectDeviceProperties: false; page URL, title, referrer, and campaign values are collected only when trackPageViews is enabled.

Opt-out​

MostlyGoodMetrics.optOut();      // stop all tracking immediately
MostlyGoodMetrics.optIn(); // resume tracking
MostlyGoodMetrics.isOptedOut(); // current state

While opted out, tracking calls are no-ops and queued (unsent) events are purged. The choice is persisted and survives page loads.

For consent-first sites (e.g. GDPR), start opted out and call optIn() after consent:

MostlyGoodMetrics.configure({
apiKey: 'mgm_proj_your_api_key',
optedOutByDefault: true, // no events until optIn() is called
});

A persisted opt-in/opt-out choice always wins over optedOutByDefault on later visits.

Do Not Track / Global Privacy Control​

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

When enabled, browsers with Do Not Track (navigator.doNotTrack === '1') or Global Privacy Control (navigator.globalPrivacyControl === true) are treated as opted out automatically.

Persistence modes​

MostlyGoodMetrics.configure({
apiKey: 'mgm_proj_your_api_key',
persistence: 'memory', // nothing written to disk
});
ModeBehavior
'localStorage+cookie' (default)localStorage plus a cookie (enables cross-subdomain tracking)
'localStorage'No cookies — same as disableCookies: true
'memory'Nothing persisted; IDs and the event queue live only for the page session

Rotating the anonymous ID​

Rotate the anonymous ID so future events can't be linked to earlier anonymous activity:

const newId = MostlyGoodMetrics.resetAnonymousId();

Forget me​

resetIdentity() clears the user ID (e.g. on logout); pass clearAnonymousId: true for a full local reset:

MostlyGoodMetrics.resetIdentity({ clearAnonymousId: true });

This clears the user ID, rotates the anonymous ID, purges pending events and super properties, and starts a new session.

Limiting device properties​

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

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
'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,
} from '@mostly-good-metrics/javascript';