analytics-signal-sdk
v1.0.2
Published
Browser analytics SDK for Matomo, ContentSquare, and Hotjar with consent-aware virtual path tracking
Maintainers
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-sdkWhat this package ships:
main: CommonJS build for tools that userequire()module: ES module build for modern bundlers like Vite, Webpack, Rollupbrowser: browser-focused module entry for frontend toolingtypes: TypeScript definitions for editor autocomplete and type safetyexports: safe package entry mapping for modern toolingdist/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/andREADME.mdare published to npm - source files and local
node_modulesare 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
windowanddocument
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:
- Pure JavaScript with npm and a bundler
Use this in Vite, Webpack, Parcel, or similar tools. Your file can still be plain
.js. - Pure JavaScript without npm bundling
Use the UMD build with a normal
<script>tag and accesswindow.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.serverUrlandmatomo.siteIdhotjar.siteIdcontentSquare.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-sdkQuick 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
- Install the package.
- Initialize it once in your app root.
- Track route changes.
- 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()insrc/main.jsx,src/main.tsx,src/App.jsx, orsrc/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
- Install the package.
- Create one analytics service.
- Initialize it in the root component.
- Track navigation with
Router. - Grant consent after user approval.
Install command:
npm install analytics-signal-sdkWhere to put this code:
- install in the Angular app root with
npm install analytics-signal-sdk - create an
analytics.service.tsfile - call
init()fromapp.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 methodssrc/app/app.component.ts: callanalyticsService.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
Routersubscription insideanalytics.service.ts - this will automatically track page changes for every route
- use component-level
trackEvent()for button clicks and user actions
Vue
- Install the package.
- Initialize it in
main.tsormain.js. - Track route changes with Vue Router.
- 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()insrc/main.jsorsrc/main.ts - put page tracking in
router.afterEach() - your
index.htmlusually 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.
- Install the package.
- Import and initialize it once.
- Call tracking methods where needed.
- Grant consent after approval.
Where to put this code:
- put
import { Analytics } from 'analytics-signal-sdk'in your main JS entry file such assrc/index.jsormain.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.AnalyticsCDN 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:
- Initialize analytics once when the signage app starts.
- Use
trackPage()for each screen, state, scene, route, or playlist step. - Use
trackEvent()for user interaction, playback milestones, sensor input, or custom business events. - Prefer Matomo first if you want the most predictable signage telemetry.
- 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 productionmode: 'auto': starts tracking immediatelystorageKey: custom localStorage key for consent state
queue
maxSize: max queued events before init or consent
script
nonce: CSP nonce for injected provider scriptstimeoutMs: script load timeoutallowInsecureUrls: allowhttpURLs for local or internal setups only
security
redactKeys: extra field names to redact before data is sentmaxStringLength: trims long strings before dispatch
Security Notes
- The SDK blocks unsafe remote script URLs by default
- Common sensitive keys like
token,password,authorization,cookie, andemailare 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:
- Update the source files.
- Run type checking.
- Build the package.
- Bump the version.
- Publish to npm.
Commands:
npm run typecheck
npm run build
npm version patch --no-git-tag-version
npm login
npm publish --access publicVersion help:
- use
patchfor small fixes - use
minorfor backward-compatible features - use
majorfor breaking changes
If you prefer:
npm run typecheck
npm run build
npm run publish:pkgNote:
- npm does not allow publishing the same version twice
- bump the version before every publish
prepublishOnlyalready runs the build step again during publish
