🛠 How to Integrate TrackJS with Angular 9 SSR for Robust Frontend Error Monitoring
Monitoring frontend errors is crucial for delivering high-quality user experiences in modern web applications. TrackJS is a powerful JavaScript error tracking tool that helps developers capture, diagnose, and resolve frontend issues in real-time.
In this blog, you’ll learn how to integrate TrackJS into an Angular 9 application with Server-Side Rendering (SSR). We’ll walk through installation, configuration, and usage—including optional server-side error handling techniques.
✅ Prerequisites
Make sure you are using Node.js 12, which is compatible with Angular 9:
nvm use 12
Install TrackJS using:
npm install trackjs --save --legacy-peer-deps
🛠️ Step 1: Configure TrackJS in main.ts
In your Angular project’s main.ts, initialize TrackJS before bootstrapping the app:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { TrackJS } from 'trackjs';
if (environment.TrackJS) {
TrackJS.install(environment.TrackJS);
}
if (environment.production) {
enableProdMode();
}
document.addEventListener('DOMContentLoaded', () => {
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
});
🌍 Step 2: Add TrackJS Config in environment.prod.ts
export const environment = {
production: true,
TrackJS: {
token: 'YOUR_TRACKJS_TOKEN',
enabled: true,
application: 'front-end',
console: { display: true },
},
};
⚠️ Step 3: Implement Global Error Handling
Create a custom global error handler to send errors to TrackJS:
// _services/global-error-handler.ts
import { ErrorHandler, Injectable } from '@angular/core';
import { TrackJS } from 'trackjs';
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
handleError(error: any): void {
console.warn(error.message);
TrackJS.track(error.originalError || error);
}
}
Register this in your AppModule:
providers: [
{ provide: ErrorHandler, useClass: GlobalErrorHandler }
],
👤 Step 4: Add User Context with TrackingService
// _services/tracking.service.ts
import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
declare const TrackJS: any;
@Injectable({ providedIn: 'root' })
export class TrackingService {
constructor(@Inject(PLATFORM_ID) private platformId: Object) {}
configureUser(userId: string): void {
if (isPlatformBrowser(this.platformId) && typeof TrackJS !== 'undefined') {
TrackJS.configure({ userId });
}
}
clearUser(): void {
if (isPlatformBrowser(this.platformId) && typeof TrackJS !== 'undefined') {
TrackJS.configure({ userId: null });
}
}
}
Use this in your authentication service:
// _services/auth.service.ts
import { Injectable } from '@angular/core';
import { TrackingService } from './tracking.service';
@Injectable({ providedIn: 'root' })
export class AuthService {
constructor(private trackingService: TrackingService) {}
login(user: { id: string }) {
this.trackingService.configureUser(user.id);
}
logout() {
this.trackingService.clearUser();
}
}
🧪 Step 5: Test with a Simple Component
Create a test component to simulate errors:
// app/simple-form.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-simple-form',
templateUrl: './simple-form.component.html',
})
export class SimpleFormComponent {
inputValue: string = '';
result: number | null = null;
onSubmit() {
try {
const numberValue = parseInt(this.inputValue);
if (isNaN(numberValue)) {
throw new Error('Invalid number input');
}
this.result = numberValue * 10;
} catch (error) {
throw error;
}
}
}
<!-- app/simple-form.component.html -->
<div class="container">
<h1>Simple Error Handler Example</h1>
<p>Enter a number and see the result multiplied by 10.</p>
<form (ngSubmit)="onSubmit()">
<label for="number">Enter a number:</label>
<input type="text" [(ngModel)]="inputValue" name="number" />
<button type="submit">Submit</button>
</form>
<p *ngIf="result !== null">Result: {{ result }}</p>
</div>
🧰 Optional: Server-Side Error Reporting (Advanced)
TrackJS only works on the browser side. For full-stack error visibility in SSR apps, use server-side logging:
// _services/server-error-reporter.service.ts
import { Injectable } from '@nestjs/common'; // Use @angular/core if Angular Universal
import axios from 'axios';
@Injectable()
export class ServerErrorReporterService {
private readonly trackJsToken = 'YOUR_TRACKJS_TOKEN';
async reportError(error: any, context: any = {}) {
try {
await axios.post('https://api.trackjs.com/v1/client/log', {
token: this.trackJsToken,
userId: context.userId || 'server',
message: error.message || 'Unknown Server Error',
stack: error.stack || '',
url: 'server',
console: [],
network: [],
session: [],
timestamp: new Date().toISOString(),
});
} catch (e) {
console.error('Failed to send error to TrackJS:', e);
}
}
}
Then, in your server.ts (Express or SSR entry point):
import { ServerErrorReporterService } from './src/app/services/server-error-reporter.service';
app.use(async (err, req, res, next) => {
const reporter = new ServerErrorReporterService();
await reporter.reportError(err, {
userId: req?.user?.id || 'anonymous',
});
res.status(500).send('Internal Server Error');
});
⚡ Final Note: TrackJS is Frontend Only
TrackJS only tracks client-side errors. If you’re building a full-stack Angular SSR application, consider using alternatives like Sentry, which supports both frontend and backend tracking out of the box.
📌 Conclusion
Integrating TrackJS with Angular 9 and SSR provides visibility into browser-side errors, making it easier to monitor production issues. With a global error handler, user context, and optional server-side reporting, you can deliver a more stable user experience.
If you need complete stack visibility (frontend + backend), explore tools like Sentry or LogRocket.