Skip to main content

Angular wiring

Install (substitute the target repo's own package manager — see invariant 3):

npm install @idhub/identity-core @idhub/identity-adapter-angular \
@idhub/identity-provider-segment @idhub/identity-provider-launchdarkly @idhub/identity-provider-fullstory

Drop any provider line the user did not select in step 2. If none were selected, install @idhub/identity-core @idhub/identity-adapter-angular only and pass providers: [] to forRoot() below.

AppModule — register IdentityModule.forRoot()

Write-if-absent for the IdentityModule.forRoot() block specifically — if app.module.ts already exists (it almost always will), report the exact imports: [...] insertion point rather than rewriting the file, and add only this entry:

// app.module.ts
import { NgModule } from '@angular/core'
import { IdentityModule } from '@idhub/identity-adapter-angular'
// Import only the providers the user selected in step 2:
import { segmentProvider } from '@idhub/identity-provider-segment'
import { launchDarklyProvider } from '@idhub/identity-provider-launchdarkly'
import { fullStoryProvider } from '@idhub/identity-provider-fullstory'

@NgModule({
imports: [
IdentityModule.forRoot({
providers: [
// one entry per selected provider only — see references/provider-env-vars.md
segmentProvider({ client: analytics, writeKey: environment.segmentWriteKey }),
launchDarklyProvider({ clientSideId: environment.launchDarklyClientId }),
fullStoryProvider({ orgId: environment.fullStoryOrgId }),
],
cookie: { name: '_anon_id' /* domain: <value chosen in step 3, or omit for host-only> */ },
enableHttpInterceptor: true, // optional: adds X-Identity-Id to every HttpClient request
}),
],
})
export class AppModule {}

forRoot() must be called exactly once, in the root module only — a lazy feature module should import bare IdentityModule (no forRoot()), which registers nothing, so a second competing IdentityClient/anonymous id can't get created by accident.

segmentProvider needs a caller-supplied analytics/analytics-node client instance (client: analytics above) — this skill does not create that instance; the target repo must already have (or add) its own Segment client module and import it here.

Where identify()/reset() go (surface only — do not auto-edit)

import { Component, Inject } from '@angular/core'
import { IdentityService } from '@idhub/identity-adapter-angular'

@Component({ /* ... */ })
export class ExampleComponent {
constructor(@Inject(IdentityService) private readonly identity: IdentityService) {}

// identity.identify(userId, traits) belongs at the login handler found in step 4
// identity.reset() belongs at the logout handler found in step 4
}

SSR caveat: Angular Universal needs the companion Express middleware

APP_INITIALIZER only guarantees the anonymous id exists before the first route renders in the browser — Angular has no request-time middleware equivalent to Next.js's Edge middleware, so a server-rendered (Angular Universal) app's first request has nothing to mint the cookie before that first response goes out, without which the server render and the client bootstrap that follows can each mint a different anonymous id. If the target is Angular Universal, this is a required wiring step, not an edge case to skip:

// server.ts (Angular Universal Express server) — write-if-absent
import { identityExpressMiddleware } from '@idhub/identity-adapter-angular/server'

server.use(identityExpressMiddleware({ cookie: { name: '_anon_id' } }))
// downstream: req.anonymousId is set, and Set-Cookie is appended (not
// replaced, so it composes with session/auth cookies set by other middleware)