@fingerly/angular provides the JavaScript SDK to your application and reads the shared identification as read-only signals.
Requirements
- Angular 19 or newer, with standalone bootstrap.
- A public key with your site in its allowed origins.
Install
npm install @fingerly/angular
Provide it
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
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
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.