Angular SDK
@sentriq/angular wraps @sentriq/browser with a standalone provider and an injectable service — it never reimplements signal collection or transport. Targets Angular 20/21 (standalone APIs, no NgModules required). Angular 22 is not yet supported — see Version compatibility below.
Install
npm install @sentriq/angularProvider setup
import { ApplicationConfig } from '@angular/core';
import { provideSentriq } from '@sentriq/angular';
export const appConfig: ApplicationConfig = {
providers: [
provideSentriq({ publicKey: 'pub_test_xxx' }),
],
};provideSentriq() is a pure, synchronous configuration step — it never touches window/document/navigator itself. Actual initialization happens inside SentriqService's constructor, gated on Angular's own isPlatformBrowser(), which is what makes this safe to use in an SSR application (see Server-side rendering below). Does not call track()/identify() automatically; initialization and event execution are kept as two separate, explicit steps.
SentriqService
import { Component, inject } from '@angular/core';
import { SentriqService } from '@sentriq/angular';
@Component({ selector: 'app-login', template: '...' })
export class LoginComponent {
private readonly sentriq = inject(SentriqService);
async handleLogin(userId: string) {
if (!this.sentriq.ready()) return; // or queue the call — your choice
const result = await this.sentriq.track('login', { account: { id: userId } });
// result.risk.decision
}
}status() is a signal, one of 'idle' | 'initializing' | 'ready' | 'error'; ready() is a computed signal for status() === 'ready' — the same convenience @sentriq/vue exposes, on top of the exact same state @sentriq/react exposes. SentriqService is registered providedIn: 'root', so every injection point — eagerly- or lazily-loaded, any number of components/services — shares exactly one instance and therefore exactly one underlying client; this falls directly out of Angular's own root-injector singleton semantics, with no extra sharing logic in the package itself. Calling track()/identify() before provideSentriq() was configured, or before the client is ready, rejects with a clear SentriqConfigurationError naming the missing step — never a silent no-op.
track(event, { account: { id } }) takes your own opaque reference for the end user — never an email or other sensitive value, and never inferred automatically from Angular Router params or an auth store. There is no separate Angular-specific identity concept; this is the exact same AccountReference contract @sentriq/browser defines.Server-side rendering
Safe to use with Angular SSR/hydration (@angular/ssr, provideClientHydration()) — SentriqService never touches window/document/navigator/localStorage during a server render; it stays status: 'idle' on the server and transitions to 'ready' only after hydrating in the browser, with zero hydration mismatch — verified against a real Angular Universal build, a real production server response, and a real browser load.
Lazy-loaded routes
Injecting SentriqService from a lazy-loaded route or component resolves the same root-level singleton — it never creates a second Sentriq client. If two independent Angular applications are bootstrapped on the same page (two separate bootstrapApplication() calls), each gets its own root injector and therefore its own SentriqService instance — this is standard Angular DI behavior, not something this package changes.
Pageview tracking
@sentriq/browser has no automatic pageview tracking, so @sentriq/angular does not add Angular Router integration for one either. Call sentriq.track('page_view') from a Router NavigationEnd subscription yourself if you want this behavior.
Consent
Not applicable — @sentriq/browser has no consent-gating mechanism of any kind today, so none was invented for Angular either.
Errors
Same typed errors as @sentriq/browser — re-exported unchanged from @sentriq/angular.
Version compatibility
Angular ^20.0.0 || ^21.0.0 (peer range); Angular 21.2.x tested this phase, built with the real Angular Package Format (ng-packagr, partial Ivy compilation). Angular 22 is deliberately not yet supported: its toolchain (ng-packagr@22) requires TypeScript 6.0, which conflicts with the TypeScript 5.9 this monorepo's other packages and apps share — bumping the whole repository to an unreleased-at-the-time major TypeScript version was judged out of scope for this phase.