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

unified-analytics

v1.1.12-alpha.0

Published

Unified analytics library for web applications

Readme

Unified Analytics

A unified analytics library for web applications that provides a consistent interface for multiple analytics providers. This library uses the Observer pattern to allow easy integration with multiple analytics providers (like CleverTap and custom providers) through a single consistent API.

Table of Contents

Features

  • 🔄 Unified API - Track events across multiple analytics providers through a single consistent interface
  • 🔌 Pluggable Architecture - Easily add, remove, or swap analytics providers
  • 🔍 Type Safety - Written in TypeScript with comprehensive type definitions
  • 🎯 Common Properties - Set global properties that are included with every event
  • 🧪 Testing Support - Comprehensive Vitest test suite
  • 📦 Small Footprint - Minimal bundle size with size limits enforced
  • 📚 Comprehensive Documentation - Detailed JSDoc comments and examples

Installation

npm install unified-analytics
# or
yarn add unified-analytics
# or
bun add unified-analytics

Package Exports

The package supports subpath imports for better tree-shaking:

// Main import
import analytics from 'unified-analytics';
import type { AnalyticsEvent, AnalyticsObserver } from 'unified-analytics';

// Specific imports
import { cleverTapService } from 'unified-analytics/providers';
import { useScreenDuration } from 'unified-analytics/hooks';

Usage

Basic Usage

import analytics from 'unified-analytics';

// Initialize analytics with providers
// Note: Analytics must be initialized before tracking events
analytics.initialize([providerService]);

// Attach/detach providers as needed
analytics.attach(providerService);
// When detaching, make sure to pass the same service that was attached/initialized
analytics.detach(providerService);

// Set common attributes that will be attached to all events
analytics.setCommonAttributes({
  userAgent: navigator.userAgent
});

// Track events - these will only be processed after initialization
analytics.sendEvent('PAGE_VIEW', {
  page: 'home',
  title: 'Homepage'
});

analytics.sendEvent('BUTTON_CLICKED', {
  buttonId: 'submit-form',
  location: 'header'
});

// You can also use the fluent API for chaining operations
analytics
  .initialize([providerService])
  .setCommonAttributes({ userAgent: navigator.userAgent })
  .sendEvent('APP_STARTED', { timestamp: Date.now() });

API Reference

Core Analytics APIs

| Method | Description | Parameters | |--------|-------------|------------| | initialize() | Initialize the analytics system with observers and options | observers: AnalyticsObserver[], options: InitOptions | | attach() | Register a new analytics provider to receive events | observer: AnalyticsObserver | | detach() | Remove an analytics provider from receiving events | observer: AnalyticsObserver | | sendEvent() | Track an analytics event and notify registered providers | eventName: string, attributes?: EventAttributes, observers?: AnalyticsObserver \| AnalyticsObserver[] | | setCommonAttributes() | Update attributes included with every tracked event | attributes: EventAttributes | | getCommonAttributes() | Get the current common attributes object | - | | setInHouseAttributes() | Update in-house attributes for internal use | attributes: EventAttributes | | getInHouseAttributes() | Get the current in-house attributes object | - | | resetAttributes() | Reset all analytics attributes (common and in-house) | - | | setDebug() | Enable or disable debug mode at runtime | value: boolean | | isInitialized() | Check if analytics has been initialized | - | | cloneProvider() | Create a clone of an existing analytics provider | observer: T, options?: { autoAttach?: boolean } | | use() | Register middleware to process events before sending | middleware: AnalyticsMiddleware |

Available Analytics Providers

| Provider | Description | |----------|--------------| | Firebase Google Analytics | Integration with Firebase Analytics | | CleverTap | Integration with CleverTap analytics platform | | Google Analytics 4 | Direct integration with Google Analytics 4 using gtag.js |

Hooks

| Hook | Description | |------|-------------| | useScreenDuration | React hook for tracking screen/page view duration | | useScrollDepthTracking | React hook for tracking scroll depth |

Each provider implements the AnalyticsObserver interface with methods like getInstance(), onEvent(), and clone().

Common Attributes

Common attributes are key-value pairs that are automatically included with every analytics event you track. They're useful for:

  • Adding global context (user agent, app version, environment)
  • Including user information (userId, accountId)
  • Adding device or platform details (device type, screen size)
// Set common attributes that will be included in all subsequent events
// Make sure analytics is initialized first
analytics
  .initialize([/* your providers */])
  .setCommonAttributes({
    appVersion: '1.2.3',
    platform: 'web',
    environment: isDevelopment() ? 'development' : 'production',
    userId: user.id,
    accountType: user.accountType
  });

// You can update common attributes at any time
analytics.setCommonAttributes({
  // This merges with existing common attributes
  lastActive: new Date().toISOString()
});

// Clear specific common attributes when needed (e.g., on user logout)
analytics.clearCommonProperties(['userId', 'accountType']);

// In-house attributes are for internal or advanced analytics needs
analytics.setInHouseAttributes({
  internalUserType: 'beta',
  experimentGroup: 'A',
});

// Retrieve in-house attributes
const inHouseAttrs = analytics.getInHouseAttributes();

// Reset all attributes (both common and in-house)
analytics.resetAttributes();

// Common and in-house attributes are automatically included in all events
analytics.sendEvent('FEATURE_USED', {
  featureId: 'dark-mode'
  // Common attributes will be merged with the event attributes
});

Hooks

The library provides React hooks to simplify analytics integration in React applications.

useScreenDuration

Tracks how long a user spends on a screen or component. Useful for measuring engagement and session length.

useScreenDuration(screenName: string, additionalAttributes: Record<string, any> = {})
  • screenName: The event name to track (will be used as the event name when sending to analytics)
  • additionalAttributes: Optional object with additional data to include with the duration event
import { useScreenDuration } from 'unified-analytics/hooks';

function MyComponent() {
  // Track the time spent on this component
  useScreenDuration(
    'MY_COMPONENT_DURATION', // Event name to track
    {
      componentVersion: '1.0.0',
      section: 'dashboard'
    } // Optional additional attributes
  );
  
  return <div>My Component</div>;
}

The hook will automatically track:

  • When the component mounts (screen view start)
  • When the component unmounts (screen view end)
  • The total duration spent on the screen
  • Any additional attributes you specify
Browser Tab Visibility

The hook intelligently handles browser tab visibility changes to provide accurate engagement metrics:

  • Pauses tracking when the tab is not visible (user switches tabs)
  • Resumes tracking when the tab becomes visible again
  • Only counts actual engagement time (when the tab is in focus)

useScrollDepthTracking

Tracks how far users scroll down a page. Useful for content engagement analysis and identifying content visibility issues.

useScrollDepthTracking(eventName: string, throttleMs: number = 500, additionalAttributes: Record<string, any> = {})
  • eventName: The name of the event to track when scrolling
  • throttleMs: Optional throttle time in milliseconds (default: 500ms) to avoid excessive event firing
  • additionalAttributes: Optional object with additional data to include with the scroll events
import { useScrollDepthTracking } from 'unified-analytics/hooks';

function LongContentPage() {
  // Track how far users scroll down this page
  useScrollDepthTracking(
    'CONTENT_SCROLL_DEPTH',  // Event name
    1000,                   // Throttle to once per second
    {
      pageId: 'article-123',
      contentType: 'blog'
    }                       // Additional attributes
  );
  
  return (
    <div className="long-content">
      {/* Long scrollable content */}
    </div>
  );
}

The hook will automatically track:

  • Scroll position as a percentage (0-100%)
  • Throttled scroll events to avoid overwhelming analytics
  • The current timestamp of each scroll event
  • Any additional attributes you specify

Best Practices

  • Set early in app lifecycle: Set common attributes as early as possible, ideally during app initialization
  • Keep them lightweight: Include only essential information that's relevant across all events
  • Prefer specific attributes for one-time events: Don't overload common attributes with data only relevant to specific events
  • Update when user context changes: Update common attributes when user logs in/out or changes settings
  • User consent: Respect user privacy and obtain necessary consents before tracking. This responsibility falls on the application code. The analytics library does not handle user consent.
  • Using the Analytics Service: Always fire events through the Analytics Service, not directly to providers. This is a critical best practice for maintaining consistency and ensuring all configured providers receive events properly.
    • Fire events directly via providers is still technically possible but events won't include common attributes.
  • Provider Configuration: Initialize providers before adding them to analytics. This ensures providers are ready to receive events.
  • Provider Instance: Use the provider instance returned by getInstance() to access provider instances if they are provided by the provider.
  • Provider Initialization: Due to the differences between providers, the initialization process may vary. Always see what's available in each provider service, as well as referring to the provider's documentation for specific initialization instructions.
  • Google Analytics Implementations: Do not use Firebase Google Analytics and Google Analytics 4 (gtag.js) providers simultaneously. Both implementations modify the same global window objects under the hood, which can cause one configuration to overwrite the other. This behavior is outside the control of the unified-analytics service.
// ✅ CORRECT: Fire events through the Analytics Service
// Single provider
analytics.sendEvent('USER_ACTION', { actionId: 'submit' }, googleAnalytics4Service);
// Multiple providers
analytics.sendEvent('USER_ACTION', { actionId: 'submit' }, [googleAnalytics4Service, cleverTapService]);

// ❌ INCORRECT: Don't call provider methods directly
// This is still technically works, but events won't include common attributes
cleverTapService.onEvent({ ... });
googleAnalytics4Service.onEvent({ ... });

Supported Providers

CleverTap

import analytics from 'unified-analytics';
import { cleverTapService } from 'unified-analytics/providers';

// Initialize CleverTap with your API key
const cleverTapInstance = cleverTapService.getInstance();
cleverTapInstance.init('YOUR_CLEVERTAP_API_KEY');

// Add to analytics
analytics
  .initialize([cleverTapService])
  .setCommonAttributes({
    userAgent: navigator.userAgent,
  });

// Track events
analytics.sendEvent('USER_LOGIN', { userId: '12345' });

Google Analytics via Firebase

import analytics from 'unified-analytics';
import { firebaseGoogleAnalyticsService } from 'unified-analytics/providers';

// Initialize Google Analytics
firebaseGoogleAnalyticsService.init({
  // Pass your initialization here
  apiKey: 'YOUR_GOOGLE_ANALYTICS_API_KEY',
  projectId: "YOUR_GOOGLE_ANALYTICS_PROJECT_ID",
  // Optional: Additional initialization options
  // ...
});

// Add to analytics
analytics
  .initialize([firebaseGoogleAnalyticsService])
  .setCommonAttributes({
    userAgent: navigator.userAgent,
  });

// Track events
analytics.sendEvent('PAGE_VIEW', { 
  page: '/home',
  title: 'Home Page' 
});

Google Analytics 4 (using gtag.js)

import analytics from 'unified-analytics';
import { googleAnalytics4Service } from 'unified-analytics/providers';

// Initialize Google Analytics 4
googleAnalytics4Service.init({
  measurementId: 'G-XXXXXXX', // Your GA4 measurement ID
  debug: true, // Optional: Enable debug logging
  config: {    // Optional: Additional configuration parameters
    send_page_view: true,
    cookie_domain: 'auto'
  },
});

// Add to analytics
analytics
  .initialize([googleAnalytics4Service])
  .setCommonAttributes({
    userAgent: navigator.userAgent,
  });

// Track events
analytics.sendEvent('PAGE_VIEW', { 
  page: '/home',
  title: 'Home Page' 
});

Custom Provider

Create your own provider by implementing the AnalyticsObserver interface:

import { AnalyticsEvent, AnalyticsObserver } from 'unified-analytics';

class MyCustomProvider implements AnalyticsObserver {
  private apiKey: string | null = null;
  
  init(apiKey: string): void {
    this.apiKey = apiKey;
  }
  
  getInstance(): MyCustomProvider {
    return this;
  }
  
  onEvent(event: AnalyticsEvent): void {
    // Your implementation to handle the event
    console.log(`Sending ${event.name} to MyCustomProvider`);
    // Send to your analytics service...
  }
}

export const myCustomProvider = new MyCustomProvider();

Recipes

React Integration

An example React application is included in the examples/react-app directory, which demonstrates how to use the analytics library in a real-world React application. The example app showcases:

  • Setting up analytics providers with proper initialization
  • Managing analytics for authentication states (login/logout)
  • Setting different common properties for authenticated vs. anonymous users
  • Implementing protected routes with React Router
  • Tracking page views and user interactions
  • Properly cleaning up analytics on component unmount

Refer to the example app for best practices on integrating the analytics library with React applications.

Testing

The library includes a Vitest-based test suite, which is fast and ESM-compatible.

# Run tests
bun run test

# Run tests in watch mode during development
bun run test:watch

# Generate test coverage report
bun run test:coverage

Development

# Install dependencies
bun install

# Build the library
bun run build

# Run type checking
bun run typecheck

Analytics Architecture

The application uses a flexible analytics system that supports multiple providers (CleverTap, Google Analytics) through a modular observer pattern implementation.

graph TD
    subgraph Subject
        A[Analytics Class] -.implements.-> B[AnalyticsSubject Interface]
        A -->|maintains| J[Observer Set]
        A -->|attach/detach| J
    end

    subgraph Observers
        E[AnalyticsObserver Interface]
        G[CleverTap Service] -.implements.-> E
        H[Google Analytics Service] -.implements.-> E
    end

    J -->|notifies| G
    J -->|notifies| H
    I[Application Code] -->|sendEvent| A

    subgraph Event Types
        L[AnalyticsEvent Interface] -->|contains| M1[name: AppEventName]
        L -->|contains| M2[attributes?: Record]
    end

Key Components

Observer Pattern

  • Analytics class acts as the subject
  • Analytics providers (CleverTap, Google Analytics) are observers
  • All observers implement the AnalyticsObserver interface

License

MIT