Install Flawsnap in an Angular app

Add the widget to src/index.html, then wrap the few calls you need in an injectable service so components never touch window directly.

Steps

  1. 1

    Allow your hosts

    In Flawsnap, add your production and staging domains and localhost:4200 (the ng serve default) under Security → Allowed domains.

  2. 2

    Add the snippet to src/index.html

    Paste the snippet into the <head> of src/index.html.

  3. 3

    Create a FlawsnapService

    Add a service that calls window.Flawsnap only in the browser.

  4. 4

    Identify users after sign-in

    Call the service from your auth flow with the user’s name and email.

  5. 5

    Serve and test

    Run ng serve, open localhost:4200 and send a test report.

The snippet in src/index.html

index.html is the single page Angular boots into, so the widget loads once and stays for the session. It starts before Angular bootstraps, which means errors thrown while bootstrapping are in the report's console.

Do not add it to angular.json scripts. That bundles a copy of a file into your build, while this one is hosted and needs the data-key attribute on its own tag.

src/index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>MyApp</title>
  <base href="/">
  <script src="https://backend.flawsnap.com/widget.js" data-key="pk_…" async></script>
</head>
<body>
  <app-root></app-root>
</body>
</html>

The router and HttpClient

  • Router. With the default path location strategy, every navigation updates the URL with the History API. Flawsnap follows that by itself, so you do not call anything per route. With useHash: true (hash location), name screens from a NavigationEnd subscription with screen(url).
  • HttpClient. Angular's HttpClient makes XHR or fetch requests, and Flawsnap records the last 100 of both with method, URL, status and duration. Bodies are never captured, so tokens in request bodies stay out of reports.

A small service for the JS API

Keep window access in one place. The platform check makes the service safe under server-side rendering, where there is no window.

src/app/flawsnap.service.ts
import { Injectable, PLATFORM_ID, inject } from '@angular/core'
import { isPlatformBrowser } from '@angular/common'

@Injectable({ providedIn: 'root' })
export class FlawsnapService {
  private browser = isPlatformBrowser(inject(PLATFORM_ID))

  identify(name: string, email: string) {
    if (this.browser) window.Flawsnap?.identify({ name, email })
  }

  open() {
    if (this.browser) window.Flawsnap?.open()
  }

  screen(name: string) {
    if (this.browser) window.Flawsnap?.screen(name)
  }
}

Add the Window declaration from below to a .d.ts file in src, so this compiles.

The window declaration

src/flawsnap.d.ts
// flawsnap.d.ts (anywhere your tsconfig includes)
export {}

declare global {
  interface Window {
    Flawsnap?: {
      open(): void
      identify(reporter: { name?: string; email?: string }): void
      setMetadata(details: Record<string, unknown>): void
      screen(name: string): void
      track(name: string): void
      resetUser(): void
    }
  }
}

Opening the form from your own menu

Many Angular apps are internal tools with a help menu. Turn off Show on website (under Report a bug button) in the project settings and add a "Report a problem" item that calls flawsnap.open(). The form still captures the screenshot, console and network history of the page the user was on.

Troubleshooting

  • [flawsnap] widget disabled: on ng serve: add localhost:4200, or the port you pass with --port.
  • TypeScript error Property Flawsnap does not exist on type Window: the .d.ts file is outside the folders your tsconfig includes.
  • A CSP in your server or index.html meta tag: allow https://backend.flawsnap.com in script-src and connect-src.
  • Team sign-in popup cannot connect: the page’s Cross-Origin-Opener-Policy must not be same-origin.

Questions

Does Flawsnap work with Angular server-side rendering?
Yes. The script only runs in the browser. Guard your own calls with isPlatformBrowser, as in the service above.
Will zone.js interfere with the widget?
The widget runs as a separate script and does not depend on Angular. It records requests at the browser level, so it sees calls made inside or outside Angular’s zone.

Try it on your own site

7-day free trial, then $9 a month for Starter or $19 for Pro, per organization, with unlimited team members.

Updated