ngx-boomerangjs

June 1, 2026 · View on GitHub

An Angular 21+ wrapper for boomerangjs that provides automatic script loading and Real User Monitoring (RUM) support via Angular's dependency injection system.

Features

  • Automatic boomerang script loading with ordered sequence support
  • Angular signal-based service for RUM metrics
  • APP_INITIALIZER integration for zero-boilerplate setup
  • Full TypeScript types for boomerang configuration
  • SPA-friendly with History and SPA plugin support
  • Configurable timeout and script integrity (SRI)

Requirements

PackageVersion
@angular/core^21.0.0
@angular/common^21.0.0
boomerangjs^1.815.1

Installation

As ngx-boomerangjs has a peer dependency on boomerangjs, you need to install both packages:

npm install ngx-boomerangjs boomerangjs

Quick Start

1. Provide the configuration in app.config.ts

Minimal example with boomerang core config:

import { ApplicationConfig } from '@angular/core';
import { provideBoomerangMetrics } from 'ngx-boomerangjs';

export const appConfig: ApplicationConfig = {
  providers: [
    provideBoomerangMetrics({
      enabled: true,
      boomerangConfig: {
        beacon_url: 'https://your-beacon-endpoint.example.com/beacon',
        Errors: { enabled: true, sendInterval: 1000, maxErrors: 20 },
        History: { enabled: true },
      },
    }),
  ],
};

Extended configuration example with custom script source, timeout, and source IP variable:

import { ApplicationConfig } from '@angular/core';
import { provideBoomerangMetrics } from 'ngx-boomerangjs';

export const appConfig: ApplicationConfig = {
  providers: [
    provideBoomerangMetrics({
      enabled: true,
      boomerangConfig: {
        beacon_url: 'https://your-beacon-endpoint.example.com/beacon',
        Errors: { enabled: true, sendInterval: 1000, maxErrors: 20 },
        History: { enabled: true },
      },
      scriptBaseUrl: '/assets/boomerang',
      scriptLoadTimeoutMs: 15000,
      sourceIpVarName: 'my_ip',
      sourceIpFactory: async () => {
        const ipService = inject(IpService);
        const result = await firstValueFrom(ipService.getIpAddress());
        return result.clientHost;
      },
      fixXhrTResp: true,
    }),
  ],
};

Set the needed assets for boomerangjs

In angular.json, in projects.<app>.architect.build.options.assets, add the following entries to map the boomerang core and plugin scripts from node_modules to your assets folder during build:

Short version (take care to not separate with space the list of plugins, will not be found if separated):

  {
    "glob": "boomerang.js",
    "input": "node_modules/boomerangjs/",
    "output": "assets/boomerang/"
  },
  {
    "glob": "{rt.js,auto-xhr.js,errors.js,history.js,memory.js,painttiming.js,spa.js,navtiming.js,zzz-last-plugin.js}",
    "input": "node_modules/boomerangjs/plugins/",
    "output": "assets/boomerang/plugins/"
  }

Script per script version:

  {
    "glob": "boomerang.js",
    "input": "node_modules/boomerangjs/",
    "output": "assets/boomerang/"
  },
  {
    "glob": "rt.js",
    "input": "node_modules/boomerangjs/plugins/",
    "output": "assets/boomerang/plugins/"
  },
  {
    "glob": "auto-xhr.js",
    "input": "node_modules/boomerangjs/plugins/",
    "output": "assets/boomerang/plugins/"
  },
  {
    "glob": "history.js",
    "input": "node_modules/boomerangjs/plugins/",
    "output": "assets/boomerang/plugins/"
  },
  {
    "glob": "spa.js",
    "input": "node_modules/boomerangjs/plugins/",
    "output": "assets/boomerang/plugins/"
  },
  {
    "glob": "errors.js",
    "input": "node_modules/boomerangjs/plugins/",
    "output": "assets/boomerang/plugins/"
  },
  {
    "glob": "memory.js",
    "input": "node_modules/boomerangjs/plugins/",
    "output": "assets/boomerang/plugins/"
  },
  {
    "glob": "painttiming.js",
    "input": "node_modules/boomerangjs/plugins/",
    "output": "assets/boomerang/plugins/"
  },
  {
    "glob": "navtiming.js",
    "input": "node_modules/boomerangjs/plugins/",
    "output": "assets/boomerang/plugins/"
  },
  {
    "glob": "zzz-last-plugin.js",
    "input": "node_modules/boomerangjs/plugins/",
    "output": "assets/boomerang/plugins/"
  }

Important behavior note:

  • The library loads boomerang scripts dynamically at runtime (inside APP_INITIALIZER), so Angular build phase does not inject those script tags into index.html automatically.
  • If you need build-time <script> tags in index.html, use projects.<app>.architect.build.options.scripts in angular.json instead of only assets.
  • Default script base path is assets/boomerang (relative path). If your app uses a different base/deploy URL, set scriptBaseUrl explicitly.

Optional additions to standard boomerangjs

For my own needs, I added a few, and completely optional, features to the standard boomerangjs behavior that I found useful in my Angular applications. You will not probably need it:

  • sourceIpVarName and sourceIpFactory options to add a custom variable with the client's source IP address to each beacon. The factory function can be async to support fetching the IP from an external service.
  • fixXhrTResp option to automatically calculate t_resp for XHR initiators when it is missing. This is useful for Angular applications where t_resp may not be populated consistently due to various reasons, like race conditions.

API

provideBoomerangMetrics(config: NgxBoomerangjsConfig)

Registers boomerang as an Angular environment provider. Runs script loading and initialization during APP_INITIALIZER.

NgxBoomerangjsConfig

export interface NgxBoomerangjsConfig {
  enabled: boolean;
  boomerangConfig: BoomrConfig;
  scripts?: ScriptDescriptor[];
  scriptBaseUrl?: string;
  scriptLoadTimeoutMs?: number;
  sourceIpVarName?: string;
  sourceIpFactory?: () => Promise<string>;
  fixXhrTResp?: boolean;
}
PropertyTypeDescription
enabledbooleanEnables or disables boomerang initialization.
boomerangConfigBoomrConfigBoomerang BOOMR.init() configuration.
scriptsScriptDescriptor[]Optional ordered script list. If omitted, defaults are created from scriptBaseUrl.
scriptBaseUrlstringOptional Base URL used by internal createDefaultBoomerangScripts() instead of default 'assets/boomerang' path
scriptLoadTimeoutMsnumberOptional Timeout in milliseconds for each script load.
sourceIpVarNamestringOptional beacon variable name used to store source IP.
sourceIpFactory() => Promise<string>Optional async function that resolves the source IP value.
fixXhrTRespbooleanOptional fallback for XHR/Fetch beacons that computes t_resp when boomerang leaves it empty. Defaults to false.

Load custom scripts instead default ones

By default, the library creates a list of scripts to load based on the known boomerang core and plugin scripts. However, if you want to have full control over the script loading process, you can provide your own list of scripts via the scripts property in the configuration.

With this option, you can replace the default script loading behavior with your own custom script list. Thus is an example of a configuration that uses a custom script list:

provideBoomerangMetrics({
  enabled: true,
  scripts: [
    { src: `assets/boomerang/boomerang.js` },
    { src: `assets/boomerang/plugins/auto-xhr.js` },
    { src: `assets/boomerang/plugins/history.js` },
    { src: `assets/boomerang/plugins/spa.js` },
  ],
  boomerangConfig: {
    beacon_url: URL_METRICS.METRICS_FT,
    beacon_type: 'POST',
    log: (_msg: unknown, level: string) => {
      if (level === 'error') {
        console.error('[Boomerang]', _msg);
      }
    },
    autorun: false,
    instrument_xhr: true,
    AutoXHR: {
      enabled: true,
      monitorFetch: true, // Important to capture fetch requests, since Angular HttpClient uses fetch under the hood in modern browsers
      alwaysSendXhr: true,
      xhrRequireChanges: false,
    },
    History: {
      enabled: true,
    },
  },
});

Configuration Reference

The boomerangConfig property maps directly to boomerang's BOOMR.init() options. See the boomerangjs documentation for the full list of supported plugins and settings.

Contributing

Contributions are welcome, and pull requests are encouraged.

If you want to propose a fix, improvement, or new feature, feel free to open an issue for discussion or submit a PR directly.

Development notes

Building the library

This library is packaged using ng-packagr in Angular Ivy partial compilation mode, which is the standard format for distributing Angular libraries on npm.

Partial compilation produces output that Angular's linker processes at the application build time, making it compatible with AOT and enabling tree-shaking.

The build is driven by two config files:

  • ng-package.json — tells ng-packagr where the entry point is (src/public-api.ts) and where to write the output (dist/).
  • tsconfig.lib.json — extends the base tsconfig.json and sets "compilationMode": "partial" under angularCompilerOptions.

To build the library:

npm run build

The output in dist/ follows the Angular Package Format (APF):

  • fesm2022/ngx-boomerangjs.mjs — flat ES module bundle.
  • types/ngx-boomerangjs.d.ts — consolidated type declarations.
  • package.json — generated manifest with correct exports, module, and typings fields.

Testing locally before publishing

To install the library in another project without publishing to npm, pack it as a tarball:

npm run build
npm run pack:local

This generates ngx-boomerangjs-1.0.0.tgz in the root. Install it in the consuming project:

npm install ../ngx-boomerangjs/ngx-boomerangjs-1.0.0.tgz
# or with pnpm:
pnpm add ../ngx-boomerangjs/ngx-boomerangjs-1.0.0.tgz

Note: after any source change, rebuild and repack before reinstalling in the consumer project.

Publishing to npm

Authentication uses a project-scoped .npmrc with an NPM_TOKEN environment variable. Set the token before publishing.

.npmrc file content should be:

registry=https://registry.npmjs.org/
//registry.npmjs.org/:_authToken=${NPM_TOKEN}

Then run the publish script:

set NPM_TOKEN=your_token_here # Windows
export NPM_TOKEN=your_token_here # Unix

npm run publish:dist

The publish:dist script runs npm publish ./dist, so only the compiled output is uploaded — source files are never included.

License

MIT © 2026