Angular
Integrate vTilt with Angular 16+ — npm package or inline script, Router pageviews, identify on every page load.
vTilt drops into Angular through an APP_INITIALIZER (or an inline script), plus a Router subscription that emits a pageview on every navigation. Works with both the classic NgModule setup and the standalone bootstrapApplication API.
#1. Install & initialise
Choose how you load the Browser SDK. npm boots the SDK from an APP_INITIALIZER; the inline script drops a stub in index.html with no package to install. Both expose the same window.vt global — the rest of this guide is identical either way.
Install the package:
npm install @v-tilt/browserProvide a function that runs on app boot and calls vt.init(). Read the token via environment.ts to keep it out of source:
// src/app/vtilt.ts
import { APP_INITIALIZER, Provider } from '@angular/core'
import { vt } from '@v-tilt/browser'
import { environment } from '../environments/environment'
export const VTILT_INIT: Provider = {
provide: APP_INITIALIZER,
multi: true,
useFactory: () => () => {
vt.init(environment.vtiltToken, {
api_host: environment.vtiltHost,
autocapture: true,
capture_pageview: false,
capture_pageleave: true,
})
},
}// src/environments/environment.ts
export const environment = {
vtiltToken: 'YOUR_PROJECT_TOKEN',
vtiltHost: 'https://www.vtilt.com',
}Register it on bootstrap:
// src/main.ts
import { bootstrapApplication } from '@angular/platform-browser'
import { provideRouter } from '@angular/router'
import { AppComponent } from './app/app.component'
import { VTILT_INIT } from './app/vtilt'
import { routes } from './app/routes'
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes), VTILT_INIT],
})For NgModule apps, add VTILT_INIT to the providers array of AppModule.
#2. Router pageviews
Subscribe to NavigationEnd events and emit $pageview so SPA navigation registers in vTilt.
// src/app/app.component.ts
import { Component, OnInit, inject } from '@angular/core'
import { Router, NavigationEnd, RouterOutlet } from '@angular/router'
import { filter } from 'rxjs/operators'
import { vt } from '@v-tilt/browser'
@Component({
standalone: true,
selector: 'app-root',
imports: [RouterOutlet],
template: '<router-outlet></router-outlet>',
})
export class AppComponent implements OnInit {
private router = inject(Router)
ngOnInit() {
this.router.events
.pipe(filter(e => e instanceof NavigationEnd))
.subscribe((e: NavigationEnd) => {
vt.capture('$pageview', {
$current_url: window.location.href,
$pathname: e.urlAfterRedirects,
})
})
}
}#3. Identify users
Identify whenever your auth service emits a user. The pattern below also identifies on app boot when the user is already logged in.
// src/app/auth.service.ts
import { Injectable } from '@angular/core'
import { BehaviorSubject } from 'rxjs'
import { vt } from '@v-tilt/browser'
@Injectable({ providedIn: 'root' })
export class AuthService {
user$ = new BehaviorSubject<{ id: string; email: string } | null>(null)
constructor() {
this.user$.subscribe(user => {
if (user) vt.identify(user.id, { email: user.email })
})
}
logout() {
vt.capture('user_logged_out')
vt.resetUser()
this.user$.next(null)
}
}#4. Capture events anywhere
import { vt } from '@v-tilt/browser'
@Component({
/* ... */
})
export class HeroComponent {
onCta() {
vt.capture('cta_clicked', { location: 'hero' })
}
}#Next steps
- Identify & alias — anonymous → known user merge.
- Autocapture — what's captured automatically.
- Reverse proxy — block-resistant ingestion.