{"id":51820544,"url":"https://github.com/mcvendrell/ngx-boomerangjs","last_synced_at":"2026-07-24T14:00:38.686Z","repository":{"id":350263446,"uuid":"1205880404","full_name":"mcvendrell/ngx-boomerangjs","owner":"mcvendrell","description":"An Angular 21+ wrapper for boomerangjs","archived":false,"fork":false,"pushed_at":"2026-04-28T10:26:16.000Z","size":60,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-28T12:27:22.107Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mcvendrell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-09T11:21:05.000Z","updated_at":"2026-04-28T10:26:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mcvendrell/ngx-boomerangjs","commit_stats":null,"previous_names":["mcvendrell/ngx-boomerangjs"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/mcvendrell/ngx-boomerangjs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcvendrell%2Fngx-boomerangjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcvendrell%2Fngx-boomerangjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcvendrell%2Fngx-boomerangjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcvendrell%2Fngx-boomerangjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mcvendrell","download_url":"https://codeload.github.com/mcvendrell/ngx-boomerangjs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcvendrell%2Fngx-boomerangjs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35844578,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-24T02:00:07.870Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-22T05:00:25.539Z","updated_at":"2026-07-24T14:00:38.677Z","avatar_url":"https://github.com/mcvendrell.png","language":"TypeScript","funding_links":[],"categories":["Framework Interoperability"],"sub_categories":["Wrappers"],"readme":"# ngx-boomerangjs\n\nAn Angular 21+ wrapper for [boomerangjs](https://github.com/akamai/boomerang) that provides automatic script loading and Real User Monitoring (RUM) support via Angular's dependency injection system.\n\n## Features\n\n- Automatic boomerang script loading with ordered sequence support\n- Angular signal-based service for RUM metrics\n- `APP_INITIALIZER` integration for zero-boilerplate setup\n- Full TypeScript types for boomerang configuration\n- SPA-friendly with History and SPA plugin support\n- Configurable timeout and script integrity (SRI)\n\n## Requirements\n\n| Package           | Version    |\n| ----------------- | ---------- |\n| `@angular/core`   | `^21.0.0`  |\n| `@angular/common` | `^21.0.0`  |\n| `boomerangjs`     | `^1.815.1` |\n\n## Installation\n\nAs ngx-boomerangjs has a peer dependency on boomerangjs, you need to install both packages:\n\n```bash\nnpm install ngx-boomerangjs boomerangjs\n```\n\n## Quick Start\n\n### 1. Provide the configuration in `app.config.ts`\n\nMinimal example with boomerang core config:\n\n```ts\nimport { ApplicationConfig } from '@angular/core';\nimport { provideBoomerangMetrics } from 'ngx-boomerangjs';\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideBoomerangMetrics({\n      enabled: true,\n      boomerangConfig: {\n        beacon_url: 'https://your-beacon-endpoint.example.com/beacon',\n        Errors: { enabled: true, sendInterval: 1000, maxErrors: 20 },\n        History: { enabled: true },\n      },\n    }),\n  ],\n};\n```\n\nExtended configuration example with custom script source, timeout, and source IP variable:\n\n```ts\nimport { ApplicationConfig } from '@angular/core';\nimport { provideBoomerangMetrics } from 'ngx-boomerangjs';\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideBoomerangMetrics({\n      enabled: true,\n      boomerangConfig: {\n        beacon_url: 'https://your-beacon-endpoint.example.com/beacon',\n        Errors: { enabled: true, sendInterval: 1000, maxErrors: 20 },\n        History: { enabled: true },\n      },\n      scriptBaseUrl: '/assets/boomerang',\n      scriptLoadTimeoutMs: 15000,\n      sourceIpVarName: 'my_ip',\n      sourceIpFactory: async () =\u003e {\n        const ipService = inject(IpService);\n        const result = await firstValueFrom(ipService.getIpAddress());\n        return result.clientHost;\n      },\n      fixXhrTResp: true,\n    }),\n  ],\n};\n```\n\n### Set the needed assets for boomerangjs\n\nIn `angular.json`, in `projects.\u003capp\u003e.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:\n\nShort version (take care to _not separate with space_ the list of plugins, will not be found if separated):\n\n```json\n  {\n    \"glob\": \"boomerang.js\",\n    \"input\": \"node_modules/boomerangjs/\",\n    \"output\": \"assets/boomerang/\"\n  },\n  {\n    \"glob\": \"{rt.js,auto-xhr.js,errors.js,history.js,memory.js,painttiming.js,spa.js,navtiming.js,zzz-last-plugin.js}\",\n    \"input\": \"node_modules/boomerangjs/plugins/\",\n    \"output\": \"assets/boomerang/plugins/\"\n  }\n```\n\nScript per script version:\n\n```json\n  {\n    \"glob\": \"boomerang.js\",\n    \"input\": \"node_modules/boomerangjs/\",\n    \"output\": \"assets/boomerang/\"\n  },\n  {\n    \"glob\": \"rt.js\",\n    \"input\": \"node_modules/boomerangjs/plugins/\",\n    \"output\": \"assets/boomerang/plugins/\"\n  },\n  {\n    \"glob\": \"auto-xhr.js\",\n    \"input\": \"node_modules/boomerangjs/plugins/\",\n    \"output\": \"assets/boomerang/plugins/\"\n  },\n  {\n    \"glob\": \"history.js\",\n    \"input\": \"node_modules/boomerangjs/plugins/\",\n    \"output\": \"assets/boomerang/plugins/\"\n  },\n  {\n    \"glob\": \"spa.js\",\n    \"input\": \"node_modules/boomerangjs/plugins/\",\n    \"output\": \"assets/boomerang/plugins/\"\n  },\n  {\n    \"glob\": \"errors.js\",\n    \"input\": \"node_modules/boomerangjs/plugins/\",\n    \"output\": \"assets/boomerang/plugins/\"\n  },\n  {\n    \"glob\": \"memory.js\",\n    \"input\": \"node_modules/boomerangjs/plugins/\",\n    \"output\": \"assets/boomerang/plugins/\"\n  },\n  {\n    \"glob\": \"painttiming.js\",\n    \"input\": \"node_modules/boomerangjs/plugins/\",\n    \"output\": \"assets/boomerang/plugins/\"\n  },\n  {\n    \"glob\": \"navtiming.js\",\n    \"input\": \"node_modules/boomerangjs/plugins/\",\n    \"output\": \"assets/boomerang/plugins/\"\n  },\n  {\n    \"glob\": \"zzz-last-plugin.js\",\n    \"input\": \"node_modules/boomerangjs/plugins/\",\n    \"output\": \"assets/boomerang/plugins/\"\n  }\n```\n\nImportant behavior note:\n\n- 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.\n- If you need build-time `\u003cscript\u003e` tags in `index.html`, use `projects.\u003capp\u003e.architect.build.options.scripts` in `angular.json` instead of only `assets`.\n- Default script base path is `assets/boomerang` (relative path). If your app uses a different base/deploy URL, set `scriptBaseUrl` explicitly.\n\n## Optional additions to standard boomerangjs\n\nFor 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:\n\n- `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.\n- `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.\n\n## API\n\n### `provideBoomerangMetrics(config: NgxBoomerangjsConfig)`\n\nRegisters boomerang as an Angular environment provider. Runs script loading and initialization during `APP_INITIALIZER`.\n\n### `NgxBoomerangjsConfig`\n\n```ts\nexport interface NgxBoomerangjsConfig {\n  enabled: boolean;\n  boomerangConfig: BoomrConfig;\n  scripts?: ScriptDescriptor[];\n  scriptBaseUrl?: string;\n  scriptLoadTimeoutMs?: number;\n  sourceIpVarName?: string;\n  sourceIpFactory?: () =\u003e Promise\u003cstring\u003e;\n  fixXhrTResp?: boolean;\n}\n```\n\n| Property              | Type                    | Description                                                                                                         |\n| --------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------- |\n| `enabled`             | `boolean`               | Enables or disables boomerang initialization.                                                                       |\n| `boomerangConfig`     | `BoomrConfig`           | Boomerang `BOOMR.init()` configuration.                                                                             |\n| `scripts`             | `ScriptDescriptor[]`    | Optional ordered script list. If omitted, defaults are created from `scriptBaseUrl`.                                |\n| `scriptBaseUrl`       | `string`                | Optional Base URL used by internal `createDefaultBoomerangScripts()` instead of default 'assets/boomerang' path     |\n| `scriptLoadTimeoutMs` | `number`                | Optional Timeout in milliseconds for each script load.                                                              |\n| `sourceIpVarName`     | `string`                | Optional beacon variable name used to store source IP.                                                              |\n| `sourceIpFactory`     | `() =\u003e Promise\u003cstring\u003e` | Optional async function that resolves the source IP value.                                                          |\n| `fixXhrTResp`         | `boolean`               | Optional fallback for XHR/Fetch beacons that computes `t_resp` when boomerang leaves it empty. Defaults to `false`. |\n\n### Load custom scripts instead default ones\n\nBy 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.\n\nWith 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:\n\n```ts\nprovideBoomerangMetrics({\n  enabled: true,\n  scripts: [\n    { src: `assets/boomerang/boomerang.js` },\n    { src: `assets/boomerang/plugins/auto-xhr.js` },\n    { src: `assets/boomerang/plugins/history.js` },\n    { src: `assets/boomerang/plugins/spa.js` },\n  ],\n  boomerangConfig: {\n    beacon_url: URL_METRICS.METRICS_FT,\n    beacon_type: 'POST',\n    log: (_msg: unknown, level: string) =\u003e {\n      if (level === 'error') {\n        console.error('[Boomerang]', _msg);\n      }\n    },\n    autorun: false,\n    instrument_xhr: true,\n    AutoXHR: {\n      enabled: true,\n      monitorFetch: true, // Important to capture fetch requests, since Angular HttpClient uses fetch under the hood in modern browsers\n      alwaysSendXhr: true,\n      xhrRequireChanges: false,\n    },\n    History: {\n      enabled: true,\n    },\n  },\n});\n```\n\n## Configuration Reference\n\nThe `boomerangConfig` property maps directly to boomerang's `BOOMR.init()` options. See the [boomerangjs documentation](https://github.com/akamai/boomerang) for the full list of supported plugins and settings.\n\n## Contributing\n\nContributions are welcome, and pull requests are encouraged.\n\nIf you want to propose a fix, improvement, or new feature, feel free to open an issue for discussion or submit a PR directly.\n\n## Development notes\n\n### Building the library\n\nThis library is packaged using [ng-packagr](https://github.com/ng-packagr/ng-packagr) in **Angular Ivy partial compilation mode**, which is the standard format for distributing Angular libraries on npm.\n\nPartial compilation produces output that Angular's linker processes at the application build time, making it compatible with AOT and enabling tree-shaking.\n\nThe build is driven by two config files:\n\n- `ng-package.json` — tells ng-packagr where the entry point is (`src/public-api.ts`) and where to write the output (`dist/`).\n- `tsconfig.lib.json` — extends the base `tsconfig.json` and sets `\"compilationMode\": \"partial\"` under `angularCompilerOptions`.\n\nTo build the library:\n\n```bash\nnpm run build\n```\n\nThe output in `dist/` follows the Angular Package Format (APF):\n\n- `fesm2022/ngx-boomerangjs.mjs` — flat ES module bundle.\n- `types/ngx-boomerangjs.d.ts` — consolidated type declarations.\n- `package.json` — generated manifest with correct `exports`, `module`, and `typings` fields.\n\n### Testing locally before publishing\n\nTo install the library in another project without publishing to npm, pack it as a tarball:\n\n```bash\nnpm run build\nnpm run pack:local\n```\n\nThis generates `ngx-boomerangjs-1.0.0.tgz` in the root. Install it in the consuming project:\n\n```bash\nnpm install ../ngx-boomerangjs/ngx-boomerangjs-1.0.0.tgz\n# or with pnpm:\npnpm add ../ngx-boomerangjs/ngx-boomerangjs-1.0.0.tgz\n```\n\n\u003e Note: after any source change, rebuild and repack before reinstalling in the consumer project.\n\n### Publishing to npm\n\nAuthentication uses a project-scoped `.npmrc` with an `NPM_TOKEN` environment variable. Set the token before publishing.\n\n.npmrc file content should be:\n\n```\nregistry=https://registry.npmjs.org/\n//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n```\n\nThen run the publish script:\n\n```bash\nset NPM_TOKEN=your_token_here # Windows\nexport NPM_TOKEN=your_token_here # Unix\n\nnpm run publish:dist\n```\n\nThe `publish:dist` script runs `npm publish ./dist`, so only the compiled output is uploaded — source files are never included.\n\n## License\n\nMIT © 2026\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcvendrell%2Fngx-boomerangjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmcvendrell%2Fngx-boomerangjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcvendrell%2Fngx-boomerangjs/lists"}