Frameworks · 3 min setup

How to add analytics to an Angular app

To add VisitTrack to Angular, paste the script tag into the <head> of src/index.html. With the default PathLocationStrategy, every Angular Router navigation is counted as a pageview; no Router.events subscription is needed.

Updated

src/index.html is the document every Angular route renders into — for a browser-only build and for @angular/ssr, which uses it as the template. Adding the tag there keeps it outside Angular's change detection and out of your bundles, and guarantees it loads exactly once.

Angular at a glance

Where the tag goes
src/index.html, inside <head>
Route changes
Tracked with PathLocationStrategy (the default)
Hash routing
withHashLocation() / useHash: true → events per screen
SSR
Works with @angular/ssr; guard event calls with isPlatformBrowser
Custom events
A small injectable service around window.visitrack

How to install VisitTrack on Angular

  1. Step 1: Copy your site id

    Copy your snippet from VisitTrack's install step (or Settings → General). SITE_ID below is the placeholder.

  2. Step 2: Add the tag to src/index.html

    Inside <head>, after <base href>.

    src/index.html
    <!doctype html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <title>MyApp</title>
      <base href="/">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <script defer data-site="SITE_ID" src="https://visitrack.app/tracker.js"></script>
    </head>
    <body>
      <app-root></app-root>
    </body>
    </html>
  3. Step 3: Optional: production-only index file

    To keep staging builds out, point the production configuration at its own index file in angular.json ("index": { "input": "src/index.prod.html", "output": "index.html" }) and put the tag only there. Or simply save your production hosts in Settings → General → Allowed hostnames.

  4. Step 4: Build, deploy and browse

    ng serve runs on localhost and is ignored. Deploy a production build and navigate around the live app.

How to check VisitTrack is working on Angular

  1. Navigate between two routes with routerLinks on the deployed app.
  2. The VisitTrack live view shows you within seconds; the Pages tab lists both paths.
  3. DevTools → Network shows one POST to visitrack.app/api/collect per navigation.
  4. If you enabled autoCsp or another CSP, confirm the tracker request isn't blocked in the console.

Angular's default PathLocationStrategy updates the URL with history.pushState/replaceState, both of which the tracker wraps, and back/forward fire popstate. Each pathname change is one pageview; query-param-only changes (queryParamsHandling, filter state) aren't counted again.

HashLocationStrategy (withHashLocation() or RouterModule.forRoot(routes, { useHash: true })) keeps routes after #, so the pathname never changes and only the first load is a pageview. Switch to path routing (your server must serve index.html for deep links), or send an event per navigation:

app.component.ts (hash routing only)
// Only for hash routing: one event per screen.
router.events.pipe(filter((e) => e instanceof NavigationEnd)).subscribe((e) => {
  (window as any).visitrack?.("screen_view", { screen: (e as NavigationEnd).urlAfterRedirects });
});

How to track custom events and goals in Angular

Wrap the global in a service so components stay testable and SSR never touches window:

analytics.service.ts
import { Injectable, PLATFORM_ID, inject } from "@angular/core";
import { isPlatformBrowser } from "@angular/common";

type Props = Record<string, string | number | boolean>;

@Injectable({ providedIn: "root" })
export class AnalyticsService {
  private browser = isPlatformBrowser(inject(PLATFORM_ID));

  track(name: string, props?: Props) {
    if (this.browser) (window as any).visitrack?.(name, props);
  }

  identify(userId: string, traits?: Props) {
    if (this.browser) (window as any).visitrack?.identify?.(userId, traits);
  }
}

// usage: this.analytics.track("signup", { plan: "pro" }) after the API call succeeds

In templates, data-vt-goal="cta_click" and data-vt-scroll="pricing_viewed" are plain attributes Angular passes through. Turn any event name into a goal in Settings → Goals.

Script options you might need on Angular

All optional — add them to the same tag. Full reference: script configuration.

AttributeWhat it does
data-cookielessStore nothing in the browser; the server derives a daily-rotating id. See cookieless mode.
data-exclude="/app/*"Never track these paths (comma-separated, * wildcard). Checked on every navigation.
data-allow-localTrack on localhost and *.local — for testing an install only.
data-debugLog every event the script sends, and why it skipped one, to the console.
data-auto="false"Turn off automatic events (downloads, contact clicks, form submits, rage clicks, JS errors, 404s).

Angular troubleshooting

Only the first page is tracked

You're using hash routing. Switch to PathLocationStrategy or use the NavigationEnd event above.

ReferenceError: window is not defined on the server

A component called window.visitrack during SSR. Route calls through the service above, which checks isPlatformBrowser.

The script is blocked by CSP

Add https://visitrack.app to script-src and connect-src. With a nonce- or hash-based policy using 'strict-dynamic', verify on the built app that the tag still loads.

No data from ng serve

Localhost is ignored. Add data-allow-local temporarily, or test on a deployment.

Angular analytics FAQ

Do I need to subscribe to Router events to track pageviews in Angular?

No. VisitTrack's script listens to the History API that Angular's router uses with the default PathLocationStrategy, so every navigation is a pageview automatically. Router events are only needed for hash routing.

Is there an Angular library for VisitTrack?

No. One tag in src/index.html plus an optional ten-line service covers pageviews, events and identify.

Does VisitTrack work with Angular SSR and prerendering?

Yes. The tag is part of the index.html template, so it's in the server-rendered HTML. Just keep event calls behind isPlatformBrowser.

Can I track Angular form submissions?

Yes. Automatic events record a form_submit event (with the form's id, name or action) for any submitted form. For a confirmed conversion, call track() after your API responds.

Is VisitTrack a Google Analytics alternative for Angular apps?

Yes, for teams that want cookie-free, privacy-first numbers and revenue attribution without gtag and consent-mode setup. See VisitTrack vs Google Analytics.

Keep going

Add VisitTrack to your Angular site

Cookie-free analytics with revenue attribution, live visitors, funnels and session replays. One script tag, every feature on every plan. 14 days free, no card required.

Not on Angular? See all 29 integration guides.