> ## Documentation Index
> Fetch the complete documentation index at: https://docs.outlit.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Outlit is the product that monitors customers and completes approved customer work. The customer context interfaces are the API, CLI, MCP server, and skills. Canonical references on this site: /api-reference/introduction for API concepts and authentication, /openapi.json for the public API contract, /cli/overview for the CLI, /ai-integrations/mcp for MCP. Prefer the `outlit` CLI or MCP tools for agent tasks; cite page sources when answering.

# Angular

> Integrate Outlit tracking with Angular applications.

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install --save @outlit/browser
  ```

  ```bash pnpm theme={null}
  pnpm add @outlit/browser
  ```

  ```bash yarn theme={null}
  yarn add @outlit/browser
  ```

  ```bash bun theme={null}
  bun add @outlit/browser
  ```
</CodeGroup>

## Quick start

Initialize Outlit using an `APP_INITIALIZER`:

```typescript theme={null}
// src/app/app.config.ts
import { ApplicationConfig, APP_INITIALIZER } from '@angular/core'
import outlit from '@outlit/browser'
import { environment } from '../environments/environment'

function initializeOutlit() {
  return () => {
    outlit.init({
      publicKey: environment.outlitPublicKey,
      trackPageviews: true,
    })
  }
}

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: initializeOutlit,
      multi: true
    }
  ]
}
```

Configure your environment:

```typescript theme={null}
// src/environments/environment.ts
export const environment = {
  production: false,
  outlitPublicKey: 'pk_your_public_key_here'
}
```

For production, create `environment.prod.ts` with your production key.

## Creating a service

Create a service for a shorter setup:

```typescript theme={null}
// src/app/services/outlit.service.ts
import { Injectable } from '@angular/core'
import outlit from '@outlit/browser'

@Injectable({
  providedIn: 'root'
})
export class OutlitService {
  track(eventName: string, properties?: Record<string, any>): void {
    outlit.track(eventName, properties)
  }

  identify(email: string, traits?: Record<string, any>): void {
    outlit.identify({ email, traits })
  }

  setUser(identity: { email?: string; userId?: string; traits?: Record<string, any> }): void {
    outlit.setUser(identity)
  }

  clearUser(): void {
    outlit.clearUser()
  }

  getVisitorId(): string | null {
    return outlit.getInstance().getVisitorId()
  }
}
```

## Tracking events

Inject and use the service in components:

```typescript theme={null}
// src/app/components/pricing/pricing.component.ts
import { Component } from '@angular/core'
import { OutlitService } from '../../services/outlit.service'

@Component({
  selector: 'app-pricing',
  templateUrl: './pricing.component.html'
})
export class PricingComponent {
  constructor(private outlit: OutlitService) {}

  handleCheckout(plan: string): void {
    this.outlit.track('checkout_started', {
      plan,
      amount: 99
    })
  }
}
```

```html theme={null}
<!-- src/app/components/pricing/pricing.component.html -->
<button (click)="handleCheckout('pro')">
  Start Free Trial
</button>
```

## Identifying users

Identify users after authentication:

```typescript theme={null}
// src/app/components/login/login.component.ts
import { Component } from '@angular/core'
import { Router } from '@angular/router'
import { OutlitService } from '../../services/outlit.service'
import { AuthService } from '../../services/auth.service'

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html'
})
export class LoginComponent {
  email = ''
  password = ''

  constructor(
    private auth: AuthService,
    private outlit: OutlitService,
    private router: Router
  ) {}

  async handleLogin(): Promise<void> {
    const user = await this.auth.login(this.email, this.password)

    this.outlit.identify(user.email, {
      name: user.name,
      plan: user.plan
    })

    this.router.navigate(['/dashboard'])
  }
}
```

## Router integration

Track navigation with Angular Router:

```typescript theme={null}
// src/app/app.config.ts
import { ApplicationConfig, APP_INITIALIZER } from '@angular/core'
import { provideRouter, Router, NavigationEnd } from '@angular/router'
import { OutlitService } from './services/outlit.service'
import { routes } from './app.routes'

function setupRouterTracking(router: Router, outlit: OutlitService) {
  return () => {
    router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
        outlit.track('pageview', {
          path: event.url
        })
      }
    })
  }
}

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    {
      provide: APP_INITIALIZER,
      useFactory: setupRouterTracking,
      deps: [Router, OutlitService],
      multi: true
    }
  ]
}
```

<Info>
  If you set `trackPageviews: true` during init, pageviews are tracked automatically. The above example is only needed for custom pageview logic.
</Info>

## Auth guard integration

Track authentication events:

```typescript theme={null}
// src/app/guards/auth.guard.ts
import { inject } from '@angular/core'
import { Router, CanActivateFn } from '@angular/router'
import { OutlitService } from '../services/outlit.service'
import { AuthService } from '../services/auth.service'

export const authGuard: CanActivateFn = (route, state) => {
  const auth = inject(AuthService)
  const outlit = inject(OutlitService)
  const router = inject(Router)

  if (auth.isLoggedIn()) {
    const user = auth.getUser()
    outlit.setUser({
      email: user.email,
      userId: user.id,
      traits: {
        name: user.name
      }
    })
    return true
  }

  outlit.track('auth_required', {
    path: state.url
  })

  return router.parseUrl('/login')
}
```

## RxJS integration

Track with observables:

```typescript theme={null}
// src/app/components/dashboard/dashboard.component.ts
import { Component, OnInit } from '@angular/core'
import { tap } from 'rxjs/operators'
import { OutlitService } from '../../services/outlit.service'
import { DashboardService } from '../../services/dashboard.service'

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html'
})
export class DashboardComponent implements OnInit {
  data$ = this.dashboard.getData().pipe(
    tap(() => this.outlit.track('dashboard_loaded'))
  )

  constructor(
    private dashboard: DashboardService,
    private outlit: OutlitService
  ) {}

  ngOnInit(): void {
    this.outlit.track('dashboard_viewed')
  }

  handleExport(): void {
    this.outlit.track('data_exported', {
      format: 'csv'
    })
  }
}
```

## Lifecycle hooks

Track component lifecycle events:

```typescript theme={null}
// src/app/components/feature/feature.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core'
import { OutlitService } from '../../services/outlit.service'

@Component({
  selector: 'app-feature',
  templateUrl: './feature.component.html'
})
export class FeatureComponent implements OnInit, OnDestroy {
  private startTime: number

  constructor(private outlit: OutlitService) {}

  ngOnInit(): void {
    this.startTime = Date.now()
    this.outlit.track('feature_viewed', {
      feature: 'export'
    })
  }

  ngOnDestroy(): void {
    const duration = Date.now() - this.startTime
    this.outlit.track('feature_time', {
      feature: 'export',
      duration
    })
  }
}
```

## Interceptor for API tracking

Track API calls:

```typescript theme={null}
// src/app/interceptors/tracking.interceptor.ts
import { HttpInterceptorFn, HttpEventType } from '@angular/common/http'
import { tap } from 'rxjs/operators'
import outlit from '@outlit/browser'

export const trackingInterceptor: HttpInterceptorFn = (req, next) => {
  return next(req).pipe(
    tap({
      next: (event) => {
        if (event.type === HttpEventType.Response) {
          outlit.track('api_success', {
            url: req.url,
            method: req.method
          })
        }
      },
      error: (error) => {
        outlit.track('api_error', {
          url: req.url,
          method: req.method,
          status: error.status
        })
      }
    })
  )
}
```

Register the interceptor:

```typescript theme={null}
// src/app/app.config.ts
import { ApplicationConfig } from '@angular/core'
import { provideHttpClient, withInterceptors } from '@angular/common/http'
import { trackingInterceptor } from './interceptors/tracking.interceptor'

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(
      withInterceptors([trackingInterceptor])
    )
  ]
}
```

## Activation event

Track your value milestone as an ordinary event once it succeeds:

```typescript theme={null}
// src/app/components/onboarding/onboarding.component.ts
import { Component } from '@angular/core'
import { Router } from '@angular/router'
import { OutlitService } from '../../services/outlit.service'

@Component({
  selector: 'app-onboarding',
  templateUrl: './onboarding.component.html'
})
export class OnboardingComponent {
  constructor(
    private outlit: OutlitService,
    private router: Router
  ) {}

  handleComplete(): void {
    this.outlit.track('onboarding_completed', {
      flow: 'onboarding',
      step: 'completed'
    })

    this.router.navigate(['/dashboard'])
  }
}
```

Choose this event as your activation event in Outlit. The first matching event records activation once for each eligible resolved person and company, independently. Billing status comes from verified integrations such as Stripe. See [Customer journey](/concepts/customer-journey).

## Consent management

The default `autoTrack: "auto"` mode already keeps tracking off for visitors in regions that require opt-in consent (EEA, UK, Switzerland, or unknown); use `autoTrack: false` to wait for an explicit consent signal unless a previous opt-in is stored.

Handle user consent:

```typescript theme={null}
// src/app/services/consent.service.ts
import { Injectable } from '@angular/core'
import { BehaviorSubject } from 'rxjs'
import outlit from '@outlit/browser'

@Injectable({
  providedIn: 'root'
})
export class ConsentService {
  private consentGiven = new BehaviorSubject<boolean>(false)
  consent$ = this.consentGiven.asObservable()

  constructor() {
    const hasConsent = localStorage.getItem('tracking-consent') === 'true'
    if (hasConsent) {
      this.acceptTracking()
    }
  }

  acceptTracking(): void {
    localStorage.setItem('tracking-consent', 'true')
    outlit.enableTracking()
    this.consentGiven.next(true)
  }

  declineTracking(): void {
    localStorage.setItem('tracking-consent', 'false')
    this.consentGiven.next(false)
  }
}
```

```typescript theme={null}
// src/app/components/cookie-banner/cookie-banner.component.ts
import { Component } from '@angular/core'
import { ConsentService } from '../../services/consent.service'

@Component({
  selector: 'app-cookie-banner',
  templateUrl: './cookie-banner.component.html'
})
export class CookieBannerComponent {
  showBanner = true

  constructor(private consent: ConsentService) {
    this.consent.consent$.subscribe((hasConsent) => {
      this.showBanner = !hasConsent
    })
  }

  accept(): void {
    this.consent.acceptTracking()
  }

  decline(): void {
    this.consent.declineTracking()
  }
}
```

Initialize without auto-tracking:

```typescript theme={null}
// src/app/app.config.ts
function initializeOutlit() {
  return () => {
    outlit.init({
      publicKey: environment.outlitPublicKey,
      autoTrack: false, // Wait for consent
    })
  }
}
```

## TypeScript support

Full TypeScript support is included:

```typescript theme={null}
import outlit, { type OutlitOptions, type BrowserTrackOptions } from '@outlit/browser'

const options: OutlitOptions = {
  publicKey: environment.outlitPublicKey,
  trackPageviews: true,
  flushInterval: 5000
}

outlit.init(options)
```

## Next steps

<CardGroup cols={2}>
  <Card title="Server-side tracking" icon="server" href="/tracking/server/nodejs">
    Track events from your backend
  </Card>

  <Card title="Identity resolution" icon="fingerprint" href="/concepts/identity-resolution">
    Learn how visits and events link to people
  </Card>

  <Card title="npm package" icon="npm" href="/tracking/browser/npm">
    Full API reference
  </Card>

  <Card title="React integration" icon="react" href="/tracking/browser/react">
    Use Outlit with React
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.