Frameworks · 3 min setup
How to add analytics to an Angular app
<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 withisPlatformBrowser - Custom events
- A small injectable service around
window.visitrack
How to install VisitTrack on Angular
Step 1: Copy your site id
Copy your snippet from VisitTrack's install step (or Settings → General).
SITE_IDbelow is the placeholder.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>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.Step 4: Build, deploy and browse
ng serveruns on localhost and is ignored. Deploy a production build and navigate around the live app.
How to check VisitTrack is working on Angular
- Navigate between two routes with
routerLinks on the deployed app. - The VisitTrack live view shows you within seconds; the Pages tab lists both paths.
- DevTools → Network shows one
POSTtovisitrack.app/api/collectper navigation. - If you enabled
autoCspor another CSP, confirm the tracker request isn't blocked in the console.
Does VisitTrack track Angular page navigation?
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:
// 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:
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 succeedsIn 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.
| Attribute | What it does |
|---|---|
data-cookieless | Store 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-local | Track on localhost and *.local — for testing an install only. |
data-debug | Log 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
- React analyticsAdd VisitTrack to a React single-page app (Vite, Create React App) through index.html — React Router navigations are tracked automatically.
- Vue analyticsAdd VisitTrack to a Vue 3 app built with Vite by adding one tag to index.html — Vue Router history-mode navigations are tracked automatically.
- Next.js analyticsAdd VisitTrack to a Next.js App Router or Pages Router app with next/script — client-side route changes are tracked automatically.
- Netlify analyticsAdd VisitTrack on Netlify with Snippet injection (no code) or in your framework, keep deploy previews out, and set CSP in _headers.
- Install the tracking scriptThe reference tag, CSP notes and how to check it's working.
- Custom events and signupsvisitrack(), data-vt-goal, scroll events and server-side signups.
- Use casesHow SaaS teams, indie hackers, stores and agencies use VisitTrack.
- VisitTrack vs Google AnalyticsCookie-free analytics with revenue attribution, compared honestly.
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.