@pure-tools/slushalka
v0.1.0
Published
Provider-agnostic product analytics for Angular apps — PostHog, Plausible, Umami adapters, consent, page views, click and error tracking
Maintainers
Readme
@pure-tools/slushalka
Provider-agnostic product analytics for Angular. One API, fan-out to PostHog, Plausible, Umami (or your own adapter). Consent queue, Do-Not-Track, page views, click tracking, error reporting. Zero provider SDKs bundled.
npm i @pure-tools/slushalkaSetup
// app.config.ts
import { isDevMode } from '@angular/core';
import {
provideSlushalka, providePageViewTracking, provideErrorTracking,
umamiAdapter, consoleAdapter,
} from '@pure-tools/slushalka';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes, withHashLocation()),
provideSlushalka({
adapters: isDevMode() ? [consoleAdapter()] : [umamiAdapter()],
superProps: { app: 'cuefade', version: '1.4.0' },
requireConsent: false,
}),
providePageViewTracking(), // page view on every NavigationEnd
provideErrorTracking(), // $exception events for browser errors
],
};Load the provider script in index.html:
| Provider | Script |
|----------|--------|
| Umami | <script defer src="https://cloud.umami.is/script.js" data-website-id="…" data-auto-track="false"></script> |
| Plausible | <script defer data-domain="app.com" data-manual src="https://plausible.io/js/script.manual.js"></script> |
| PostHog | official snippet, or posthogAdapter(posthog) with posthog-js |
Disable the provider's own auto page views — providePageViewTracking() handles SPA/hash routes.
Usage
private readonly analytics = inject(AnalyticsService);
this.analytics.track('crossfade_started', { durationMs: 8000 });
this.analytics.identify(user.id); // opaque id, never email
this.analytics.setSuperProps({ plan: 'pro' }); // after upgrade
this.analytics.reset(); // on logout<button slTrack="export_clicked" [slTrackProps]="{ format: 'mp3' }">Export</button>Import TrackClickDirective in the standalone component.
Consent
provideSlushalka({ adapters: [...], requireConsent: true })Events queue in memory (max maxQueueSize) until grantConsent(); revokeConsent() drops the queue and resets adapters. Decision persists in localStorage. consent() is a signal for your banner.
Config
| Option | Default | |
|--------|---------|--|
| adapters | [] | Backends to send to |
| enabled | true | Master switch |
| requireConsent | false | Queue until grantConsent() |
| respectDoNotTrack | true | Honour DNT / Global Privacy Control |
| consentStorageKey | 'slushalka:consent' | |
| maxQueueSize | 50 | |
| superProps | {} | Merged into every event |
| debug | false | Log calls and adapter failures |
Custom adapter
const myAdapter: AnalyticsAdapter = {
name: 'mine',
track: (event, props) => fetch('/api/events', { method: 'POST', body: JSON.stringify({ event, props }) }),
};Adapter errors are caught — analytics never breaks the app.
License
MIT
