Skip to main content

Installation

npm install --save @outlit/browser

Quick Start

Initialize Outlit using an APP_INITIALIZER:
// 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:
// 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 better DX:
// 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()
  }

  activate(properties?: Record<string, any>): void {
    outlit.activate(properties)
  }

  engaged(properties?: Record<string, any>): void {
    outlit.engaged(properties)
  }

  paid(properties?: Record<string, any>): void {
    outlit.paid(properties)
  }

  churned(properties?: Record<string, any>): void {
    outlit.churned(properties)
  }

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

Tracking Events

Inject and use the service in components:
// 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
    })
  }
}
<!-- src/app/components/pricing/pricing.component.html -->
<button (click)="handleCheckout('pro')">
  Start Free Trial
</button>

Identifying Users

Identify users after authentication:
// 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:
// 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
    }
  ]
}
If you set trackPageviews: true during init, pageviews are tracked automatically. The above example is only needed for custom pageview logic.

Auth Guard Integration

Track authentication events:
// 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:
// 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:
// 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:
// 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:
// 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])
    )
  ]
}

Journey Stage Events

Track user lifecycle:
// 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.activate({
      flow: 'onboarding',
      step: 'completed'
    })

    this.router.navigate(['/dashboard'])
  }
}
Stage methods (activate, engaged, paid, churned) require the user to be identified first.
Handle user consent:
// 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)
  }
}
// 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:
// 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:
import outlit, { type OutlitOptions, type BrowserTrackOptions } from '@outlit/browser'

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

outlit.init(options)

Next Steps