# Angular

> Identify visitors in Angular 19 and newer with environment providers and signal-based injection functions. Zoneless and server-rendering safe.

Last updated: 2026-09-17

`@fingerly/angular` provides the [JavaScript SDK](https://docs.fingerly.io/docs/sdks/javascript) to your application and reads the shared identification as read-only signals.

## Requirements

- Angular 19 or newer, with standalone bootstrap.
- A [public key](https://docs.fingerly.io/docs/api-keys) with your site in its allowed origins.

## Install

```bash npm
npm install @fingerly/angular
```

```bash pnpm
pnpm add @fingerly/angular
```

```bash yarn
yarn add @fingerly/angular
```

## Provide it

```ts app.config.ts
import { ApplicationConfig } from '@angular/core'
import { provideFingerly } from '@fingerly/angular'

export const appConfig: ApplicationConfig = {
  providers: [provideFingerly({ apiKey: 'fly_pk_us_production_…' })],
}
```

Add it where the application or a route is bootstrapped, not in component providers. The state is created lazily, once per application.

## Identify on an action

```ts checkout.component.ts
import { Component, input } from '@angular/core'
import { injectIdentify } from '@fingerly/angular'

@Component({
  selector: 'app-checkout',
  template: `
    <button (click)="submit()" [disabled]="fingerly.isLoading()">
      {{ fingerly.isLoading() ? 'Checking…' : 'Pay now' }}
    </button>
    @if (fingerly.error(); as failure) { <p>{{ failure.message }}</p> }
  `,
})
export class CheckoutComponent {
  readonly orderId = input.required<string>()
  readonly fingerly = injectIdentify({ tag: () => 'checkout:' + this.orderId() })

  async submit() {
    const { requestId } = await this.fingerly.identify()
    await submitOrder(this.orderId(), requestId)
  }
}
```

## injectIdentify

Call it in an injection context: a field initialiser, a constructor, or `runInInjectionContext`. Options are `immediate` (identify in `afterNextRender`) and `tag` (a string, a getter or a signal). Every state field is a `Signal`, including the computed `isReady` and `isSuspicious`.

## injectVerdict

```ts notice.component.ts
readonly automation = injectVerdict('automation', { min: 'high' })

// template: @if (automation.matched()) { … }
```

Returns `matched`, `verdict`, `confidence` and `reasons` as signals. Verdict names are `incognito`, `shields`, `tor`, `emulator`, `automation` and `farm`.

## Server rendering

`afterNextRender` callbacks never run on the server, and the state is inert without a window. Calling `identify()` during server rendering rejects with `FingerlyServerError`.
