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

analytics-signal-sdk

v1.0.2

Published

Browser analytics SDK for Matomo, ContentSquare, and Hotjar with consent-aware virtual path tracking

Readme

analytics-signal-sdk

Browser analytics SDK for React, Angular, Vue, and plain JavaScript apps.

This package gives you one simple API for Matomo, Hotjar, and ContentSquare. It helps you:

  • initialize analytics in one place
  • track page views in SPA apps
  • track events, screens, timing, and errors
  • delay tracking until user consent
  • load provider scripts automatically
  • keep one SDK instead of separate vendor integrations

Package Details

Package name:

npm install analytics-signal-sdk

What this package ships:

  • main: CommonJS build for tools that use require()
  • module: ES module build for modern bundlers like Vite, Webpack, Rollup
  • browser: browser-focused module entry for frontend tooling
  • types: TypeScript definitions for editor autocomplete and type safety
  • exports: safe package entry mapping for modern tooling
  • dist/umd/analytics.js: browser-ready build for direct <script> usage

Why this is helpful:

  • your app code stays the same even if you use multiple analytics providers
  • modern bundlers can consume the ES module build cleanly
  • TypeScript projects get types without extra setup
  • older tools can still use the CommonJS build

Package publish hygiene:

  • only built files from dist/ and README.md are published to npm
  • source files and local node_modules are not shipped to package consumers
  • you do not need to manually clean extra files before publishing

Runtime Support

Supported environments:

  • React apps
  • Angular apps
  • Vue apps
  • plain JavaScript apps with a bundler
  • direct browser usage through the UMD build
  • BrightSign HTML applications that run in a browser-like HTML widget and allow script execution

Not supported:

  • Node.js server-side tracking
  • non-browser runtimes without window and document

Important note:

  • no frontend SDK can honestly guarantee "everything supported" in every browser and player
  • this package is designed to be stable in browser-style environments
  • for enterprise use, pin a package version, test on your exact target runtime, and roll out in stages

Current Provider Support

Included now:

  • Matomo
  • Hotjar
  • ContentSquare

Not included right now:

  • Google Analytics / GA4

If you need Google Analytics support, it must be added as a new adapter in the SDK. It is not part of the current package.

How Pure JavaScript Works

You noticed import in the examples. That is normal.

The source code in this repo is written in TypeScript, but npm users do not consume the TypeScript source directly. They consume the built JavaScript files in dist/.

There are two ways to use this package in pure JavaScript:

  1. Pure JavaScript with npm and a bundler Use this in Vite, Webpack, Parcel, or similar tools. Your file can still be plain .js.
  2. Pure JavaScript without npm bundling Use the UMD build with a normal <script> tag and access window.AnalyticsSignal.

Example with plain index.js in a bundler-based app:

import { Analytics } from 'analytics-signal-sdk';

Analytics.init({
  matomo: {
    serverUrl: 'https://analytics.example.com',
    siteId: 1,
  },
  consent: {
    mode: 'manual',
  },
});

Example without bundler:

<script src="https://cdn.jsdelivr.net/npm/analytics-signal-sdk/dist/umd/analytics.js"></script>
<script>
  const { Analytics } = window.AnalyticsSignal;

  Analytics.init({
    matomo: {
      serverUrl: 'https://analytics.example.com',
      siteId: 1
    },
    consent: {
      mode: 'manual'
    }
  });
<\/script>

Before You Start

You only need the provider config you actually use:

  • matomo.serverUrl and matomo.siteId
  • hotjar.siteId
  • contentSquare.tagId

Important:

  • Do not add Matomo, Hotjar, or ContentSquare script tags manually
  • This SDK loads provider scripts for you
  • For production, prefer consent.mode: 'manual'
  • For BrightSign or digital signage, call trackPage() yourself whenever the screen, state, scene, or content changes

Install

npm install analytics-signal-sdk

Quick Start

import { Analytics } from 'analytics-signal-sdk';

Analytics.init({
  matomo: {
    serverUrl: 'https://analytics.example.com',
    siteId: 1,
  },
  hotjar: {
    siteId: 123456,
  },
  contentSquare: {
    tagId: 'YOUR_CONTENTSQUARE_TAG_ID',
  },
  consent: {
    mode: 'manual',
  },
  script: {
    nonce: 'your-csp-nonce',
    timeoutMs: 15000,
  },
  security: {
    redactKeys: ['customer_id'],
    maxStringLength: 300,
  },
  initialContext: {
    app: 'storefront',
    region: 'india',
  },
});

After init, use the same API everywhere:

Analytics.trackPage('/checkout', {
  title: document.title,
});

Analytics.trackEvent({
  category: 'Checkout',
  name: 'continue_clicked',
  label: 'step_1',
});

Integration Steps

React

  1. Install the package.
  2. Initialize it once in your app root.
  3. Track route changes.
  4. Call grantConsent() after cookie acceptance.

Where to put this code:

  • install in your React project root with npm install analytics-signal-sdk
  • put Analytics.init() in src/main.jsx, src/main.tsx, src/App.jsx, or src/App.tsx
  • put page tracking in a route listener component such as AnalyticsPageTracker
  • your HTML page stays the normal React index.html; you usually do not add the SDK there directly

Example root setup:

import { useEffect } from 'react';
import { Analytics } from 'analytics-signal-sdk';

export function App() {
  useEffect(() => {
    Analytics.init({
      matomo: {
        serverUrl: 'https://analytics.example.com',
        siteId: 1,
      },
      hotjar: {
        siteId: 123456,
      },
      consent: {
        mode: 'manual',
      },
    });
  }, []);

  return <div>My App</div>;
}

Track page changes with React Router:

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { Analytics } from 'analytics-signal-sdk';

export function AnalyticsPageTracker() {
  const location = useLocation();

  useEffect(() => {
    Analytics.trackPage(location.pathname + location.search + location.hash, {
      title: document.title,
    });
  }, [location.pathname, location.search, location.hash]);

  return null;
}

Track a custom event:

Analytics.trackEvent({
  category: 'Checkout',
  name: 'continue_clicked',
});

Grant consent:

Analytics.grantConsent();

Angular

  1. Install the package.
  2. Create one analytics service.
  3. Initialize it in the root component.
  4. Track navigation with Router.
  5. Grant consent after user approval.

Install command:

npm install analytics-signal-sdk

Where to put this code:

  • install in the Angular app root with npm install analytics-signal-sdk
  • create an analytics.service.ts file
  • call init() from app.component.ts
  • keep route tracking inside the service
  • you usually do not add the SDK directly in index.html

Typical Angular file placement:

  • src/app/analytics.service.ts: SDK setup and common helper methods
  • src/app/app.component.ts: call analyticsService.init()
  • src/app/...page.component.ts: track button clicks or page-specific events

Example service:

import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { NavigationEnd, Router } from '@angular/router';
import { filter } from 'rxjs/operators';
import { Analytics, TrackEventOptions, TrackPageOptions } from 'analytics-signal-sdk';

@Injectable({
  providedIn: 'root',
})
export class AnalyticsService {
  private readonly isBrowser: boolean;
  private initialized = false;

  constructor(
    private router: Router,
    @Inject(PLATFORM_ID) platformId: object
  ) {
    this.isBrowser = isPlatformBrowser(platformId);
  }

  init(): void {
    if (!this.isBrowser || this.initialized) {
      return;
    }

    Analytics.init({
      matomo: {
        serverUrl: 'https://analytics.example.com',
        siteId: 1,
      },
      hotjar: {
        siteId: 123456,
      },
      consent: {
        mode: 'manual',
      },
    });

    this.router.events
      .pipe(filter((event) => event instanceof NavigationEnd))
      .subscribe((event) => {
        const nav = event as NavigationEnd;

        Analytics.trackPage(nav.urlAfterRedirects, {
          title: document.title,
        });
      });

    this.initialized = true;
  }

  trackPage(path: string, options?: TrackPageOptions): void {
    if (this.isBrowser) {
      Analytics.trackPage(path, options);
    }
  }

  trackEvent(event: TrackEventOptions): void {
    if (this.isBrowser) {
      Analytics.trackEvent(event);
    }
  }

  grantConsent(): void {
    if (this.isBrowser) {
      Analytics.grantConsent();
    }
  }
}

Initialize in AppComponent:

import { Component } from '@angular/core';
import { AnalyticsService } from './analytics.service';

@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet>',
})
export class AppComponent {
  constructor(private analyticsService: AnalyticsService) {
    this.analyticsService.init();
  }
}

Page-level tracking example in an Angular page component:

Use this when you want to track that a specific page or screen is visible.

import { Component, OnInit } from '@angular/core';
import { AnalyticsService } from './analytics.service';

@Component({
  selector: 'app-checkout-page',
  template: `
    <h1>Checkout</h1>
    <button (click)="onContinue()">Continue</button>
  `,
})
export class CheckoutPageComponent implements OnInit {
  constructor(private analyticsService: AnalyticsService) {}

  ngOnInit(): void {
    this.analyticsService.trackPage('/checkout', {
      title: 'Checkout Page',
    });
  }

  onContinue(): void {
    this.analyticsService.trackEvent({
      category: 'Checkout',
      name: 'continue_clicked',
      label: 'checkout_page',
    });
  }
}

Button-level tracking example:

Use this when you want to track a specific button click in any Angular component.

import { Component } from '@angular/core';
import { AnalyticsService } from './analytics.service';

@Component({
  selector: 'app-product-card',
  template: `
    <button (click)="onBuyNow()">Buy Now</button>
  `,
})
export class ProductCardComponent {
  constructor(private analyticsService: AnalyticsService) {}

  onBuyNow(): void {
    this.analyticsService.trackEvent({
      category: 'Product',
      name: 'buy_now_clicked',
      label: 'product_card',
    });
  }
}

If you want route-based page tracking for the whole Angular app:

  • keep the Router subscription inside analytics.service.ts
  • this will automatically track page changes for every route
  • use component-level trackEvent() for button clicks and user actions

Vue

  1. Install the package.
  2. Initialize it in main.ts or main.js.
  3. Track route changes with Vue Router.
  4. Grant consent after user approval.

Where to put this code:

  • install in the Vue app root with npm install analytics-signal-sdk
  • put Analytics.init() in src/main.js or src/main.ts
  • put page tracking in router.afterEach()
  • your index.html usually does not need a direct SDK script tag

Example with Vue 3:

import { createApp } from 'vue';
import { Analytics } from 'analytics-signal-sdk';
import App from './App.vue';
import router from './router';

Analytics.init({
  matomo: {
    serverUrl: 'https://analytics.example.com',
    siteId: 1,
  },
  hotjar: {
    siteId: 123456,
  },
  consent: {
    mode: 'manual',
  },
});

router.afterEach((to) => {
  Analytics.trackPage(to.fullPath, {
    title: document.title,
  });
});

createApp(App).use(router).mount('#app');

Track an event in a component:

import { Analytics } from 'analytics-signal-sdk';

Analytics.trackEvent({
  category: 'Signup',
  name: 'submit_clicked',
});

Grant consent:

Analytics.grantConsent();

Plain JavaScript With npm

This works well in Vite, Webpack, Parcel, or any plain JS app that has a build step.

  1. Install the package.
  2. Import and initialize it once.
  3. Call tracking methods where needed.
  4. Grant consent after approval.

Where to put this code:

  • put import { Analytics } from 'analytics-signal-sdk' in your main JS entry file such as src/index.js or main.js
  • if your app has multiple HTML pages, each page can load its own bundled JS entry
  • call trackPage() when each page loads or when the visible state changes
import { Analytics } from 'analytics-signal-sdk';

Analytics.init({
  matomo: {
    serverUrl: 'https://analytics.example.com',
    siteId: 1,
  },
  hotjar: {
    siteId: 123456,
  },
  consent: {
    mode: 'manual',
  },
});

Analytics.trackPage(window.location.pathname, {
  title: document.title,
});

document.getElementById('buy-btn')?.addEventListener('click', () => {
  Analytics.trackEvent({
    category: 'Shop',
    name: 'buy_clicked',
  });
});

Grant consent:

Analytics.grantConsent();

Plain JavaScript Without npm Bundling

Use this when you want a simple browser script include.

Global name:

window.AnalyticsSignal.Analytics

CDN example:

<script src="https://cdn.jsdelivr.net/npm/analytics-signal-sdk/dist/umd/analytics.js"></script>
<script>
  const { Analytics } = window.AnalyticsSignal;

  Analytics.init({
    hotjar: { siteId: 123456 },
    consent: { mode: 'manual' }
  });

  Analytics.trackPage('/home', {
    title: document.title
  });
<\/script>

Local file example:

<script src="./dist/umd/analytics.js"></script>

Full HTML page example:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Analytics Demo</title>
</head>
<body>
  <button id="play-btn">Play</button>

  <script src="https://cdn.jsdelivr.net/npm/analytics-signal-sdk/dist/umd/analytics.js"></script>
  <script>
    const { Analytics } = window.AnalyticsSignal;

    Analytics.init({
      matomo: {
        serverUrl: 'https://analytics.example.com',
        siteId: 1
      },
      consent: {
        mode: 'manual'
      }
    });

    Analytics.trackPage('/home', {
      title: document.title
    });

    document.getElementById('play-btn').addEventListener('click', function () {
      Analytics.trackEvent({
        category: 'Player',
        name: 'play_clicked'
      });
    });
  <\/script>
</body>
</html>

If your site has multiple HTML pages:

  • call Analytics.init() once on each page after the SDK script loads
  • call Analytics.trackPage('/page-name') on each page
  • call Analytics.trackEvent() anywhere you handle clicks, form submits, playback, QR scans, or other actions

BrightSign And Digital Signage

This SDK can work for digital signage projects if your app is running as HTML/JavaScript on the player.

Recommended usage:

  1. Initialize analytics once when the signage app starts.
  2. Use trackPage() for each screen, state, scene, route, or playlist step.
  3. Use trackEvent() for user interaction, playback milestones, sensor input, or custom business events.
  4. Prefer Matomo first if you want the most predictable signage telemetry.
  5. Test on the exact BrightSign model and BOS version you deploy.

Example:

Analytics.trackPage('/signage/home');

Analytics.trackEvent({
  category: 'Playback',
  name: 'video_started',
  label: 'promo_loop'
});

Important:

  • trackPage() is virtual tracking, not browser navigation tracking
  • on signage players, you decide where to call it
  • if the screen changes, call trackPage() there
  • if a playlist item changes, call trackPage() there
  • if a user touches the screen or scans a QR code, call trackEvent() there

BrightSign HTML page example:

<!doctype html>
<html>
<head>
  <meta charset="utf-8" />
  <title>Signage Screen</title>
</head>
<body>
  <div id="screen">Welcome Screen</div>

  <script src="./analytics.js"></script>
  <script>
    const { Analytics } = window.AnalyticsSignal;

    Analytics.init({
      matomo: {
        serverUrl: 'https://analytics.example.com',
        siteId: 1
      },
      consent: {
        mode: 'manual'
      }
    });

    Analytics.trackPage('/signage/welcome');

    function onPlaylistItemChanged(name) {
      Analytics.trackPage('/signage/' + name);
    }

    function onTouchTriggered() {
      Analytics.trackEvent({
        category: 'Touch',
        name: 'screen_tapped'
      });
    }
  <\/script>
</body>
</html>

Common API

Analytics.init(config)

Initialize the SDK once when your app starts.

Analytics.init({
  matomo: {
    serverUrl: 'https://analytics.example.com',
    siteId: 1,
  },
  consent: {
    mode: 'manual',
  },
});

Analytics.trackPage(path, options)

Use this for page views and route changes.

Analytics.trackPage('/checkout/step-1', {
  title: 'Checkout - Step 1',
  meta: { flow: 'checkout', step: 1 },
});

Analytics.trackEvent(event)

Use this for button clicks, form submissions, or business events.

Analytics.trackEvent({
  category: 'Checkout',
  name: 'continue_clicked',
  label: 'step_1',
});

Analytics.trackScreen(screen)

Useful when your app is more screen-based than page-based.

Analytics.trackScreen({
  name: 'checkout-payment',
  title: 'Checkout - Payment',
  path: '/checkout/payment',
});

Analytics.trackTiming(timing)

Use this for API latency or performance timings.

Analytics.trackTiming({
  category: 'Checkout',
  variable: 'payment_api_ms',
  duration: 842,
  label: 'submit_order',
});

Analytics.trackError(error)

Use this for handled runtime or business errors.

Analytics.trackError({
  name: 'checkout_failure',
  message: 'Payment authorization failed',
  code: 'PAYMENT_401',
  fatal: false,
});

Analytics.identify(userId, traits)

Use this only if your analytics policy allows user identification.

Analytics.identify('user-123', {
  plan: 'pro',
  region: 'india',
});

Analytics.setContext(context)

Set shared values that should go with future events.

Analytics.setContext({
  app: 'storefront',
  region: 'india',
});

Analytics.grantConsent() and Analytics.revokeConsent()

Control tracking after the user accepts or rejects cookies.

Analytics.grantConsent();
Analytics.revokeConsent();

Analytics.getStatus()

Check runtime status for debugging or health checks.

Analytics.getStatus();

Config Reference

consent

  • mode: 'manual': recommended for production
  • mode: 'auto': starts tracking immediately
  • storageKey: custom localStorage key for consent state

queue

  • maxSize: max queued events before init or consent

script

  • nonce: CSP nonce for injected provider scripts
  • timeoutMs: script load timeout
  • allowInsecureUrls: allow http URLs for local or internal setups only

security

  • redactKeys: extra field names to redact before data is sent
  • maxStringLength: trims long strings before dispatch

Security Notes

  • The SDK blocks unsafe remote script URLs by default
  • Common sensitive keys like token, password, authorization, cookie, and email are redacted automatically
  • Prefer consent.mode: 'manual' in production
  • Avoid sending secrets or private personal data in event payloads
  • Initialize only in the browser for SSR apps

Updating the npm Package

When you change code and want to publish a new version:

  1. Update the source files.
  2. Run type checking.
  3. Build the package.
  4. Bump the version.
  5. Publish to npm.

Commands:

npm run typecheck
npm run build
npm version patch --no-git-tag-version
npm login
npm publish --access public

Version help:

  • use patch for small fixes
  • use minor for backward-compatible features
  • use major for breaking changes

If you prefer:

npm run typecheck
npm run build
npm run publish:pkg

Note:

  • npm does not allow publishing the same version twice
  • bump the version before every publish
  • prepublishOnly already runs the build step again during publish