{"id":13806357,"url":"https://github.com/EmmanuelRoux/ngx-matomo-client","last_synced_at":"2025-05-13T21:32:57.837Z","repository":{"id":37423528,"uuid":"363512690","full_name":"EmmanuelRoux/ngx-matomo-client","owner":"EmmanuelRoux","description":"Matomo analytics client for Angular applications","archived":false,"fork":false,"pushed_at":"2025-01-15T09:43:50.000Z","size":8466,"stargazers_count":84,"open_issues_count":5,"forks_count":15,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-12T01:07:44.018Z","etag":null,"topics":["analytics","analytics-tracking","angular","consent","matomo","matomo-analytics","matomo-script","matomo-tracking","matomo-web-analytics","ngx-matomo","ngx-matomo-client","piwik","piwik-tracking"],"latest_commit_sha":null,"homepage":"https://matomo.org/","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/EmmanuelRoux.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"EmmanuelRoux","custom":"https://www.buymeacoffee.com/emmanuelroux"}},"created_at":"2021-05-01T21:42:31.000Z","updated_at":"2025-05-10T23:07:30.000Z","dependencies_parsed_at":"2024-04-04T09:03:12.955Z","dependency_job_id":"aef145f2-319c-47f1-a8bb-976f3d8b6d33","html_url":"https://github.com/EmmanuelRoux/ngx-matomo-client","commit_stats":{"total_commits":173,"total_committers":4,"mean_commits":43.25,"dds":"0.017341040462427793","last_synced_commit":"b55e57c29f8a9a9a0b19dcbbad342754a4ea377c"},"previous_names":["emmanuelroux/ngx-matomo"],"tags_count":69,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EmmanuelRoux%2Fngx-matomo-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EmmanuelRoux%2Fngx-matomo-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EmmanuelRoux%2Fngx-matomo-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EmmanuelRoux%2Fngx-matomo-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EmmanuelRoux","download_url":"https://codeload.github.com/EmmanuelRoux/ngx-matomo-client/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254031420,"owners_count":22002759,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["analytics","analytics-tracking","angular","consent","matomo","matomo-analytics","matomo-script","matomo-tracking","matomo-web-analytics","ngx-matomo","ngx-matomo-client","piwik","piwik-tracking"],"created_at":"2024-08-04T01:01:10.691Z","updated_at":"2025-05-13T21:32:57.818Z","avatar_url":"https://github.com/EmmanuelRoux.png","language":"TypeScript","funding_links":["https://github.com/sponsors/EmmanuelRoux","https://www.buymeacoffee.com/emmanuelroux"],"categories":["Development Utilities"],"sub_categories":["Analytics"],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cdiv\u003e\u003cimg src=\"https://github.com/EmmanuelRoux/ngx-matomo-client/blob/ef38fdae3a5e5b1d1cdb1c9ba9d3a753117b7d80/logo-small.png\" alt=\"matomo-logo\" style=\"height: 24px; vertical-align: middle;\" /\u003e ngx-matomo-client\u003c/div\u003e\n  \u003cdiv\u003eMatomo Analytics client for Angular\u003c/div\u003e\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://angular.io/\"\u003e\u003cimg src=\"https://img.shields.io/badge/Angular-19-limegreen.svg?logo=angular\" alt=\"Angular 19\"\u003e\u003c/a\u003e\u0026nbsp;\n  \u003ca href=\"https://www.npmjs.com/package/ngx-matomo-client\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/ngx-matomo-client/latest.svg?logo=npm\u0026logoColor=fff\u0026label=NPM+package\u0026color=limegreen\" alt=\"NPM latest version\"\u003e\u003c/a\u003e\u0026nbsp;\n  \u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-limegreen.svg\" alt=\"MIT license\"\u003e\u003c/a\u003e\u0026nbsp;\n  \u003ca href=\"https://github.com/semantic-release/semantic-release\"\u003e\u003cimg src=\"https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-limegreen.svg\" alt=\"semantic-release\"\u003e\u003c/a\u003e\u0026nbsp;\n  \u003ca href=\"https://www.buymeacoffee.com/emmanuelroux\"\u003e\u003cimg src=\"https://img.shields.io/badge/-buy_me_a%C2%A0coffee-gray?logo=buy-me-a-coffee\" alt=\"Sponsorship\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cbr\u003e\n \u003cdiv\u003e\u003cimg src=\"https://github.com/EmmanuelRoux/ngx-matomo-client/blob/ef38fdae3a5e5b1d1cdb1c9ba9d3a753117b7d80/logo-large.png\" alt=\"matomo-logo\" style=\"height: 24px; vertical-align: middle;\" /\u003e\n \u003c/div\u003e\n  \u003ci\u003e\n    Matomo is the Google Analytics alternative that protects your data and your customers' privacy.\n    \u003cbr\u003e\n    Matomo is exempt from consent to tracking \u003ca href=\"https://fr.matomo.org/blog/2021/10/matomo-exempt-from-tracking-consent-in-france/\"\u003ein some countries\u003c/a\u003e (recommended by the CNIL in France).\n    \u003cbr\u003e\n    \u003cbr\u003e\n    https://matomo.org/\n  \u003c/i\u003e\n  \u003cbr\u003e\n\u003c/div\u003e\n\n\u003chr\u003e\n\n**Note: this library was previously distributed as `@ngx-matomo/tracker` and `@ngx-matomo/router` packages. Since\nversion 5, it is now distributed as a single package `ngx-matomo-client`.\nFollow [instructions below](#migration-from-ngx-matomotracker-and-ngx-matomorouter-version--4) for how to\neasily migrate.**\n\n[![NPM version](https://img.shields.io/npm/v/@ngx-matomo/tracker/latest.svg?logo=npm\u0026logoColor=fff\u0026label=Legacy+NPM+package\u0026color=limegreen)](https://www.npmjs.com/package/@ngx-matomo/tracker)\n\n\u003chr\u003e\n\n**Compatibility table:**\n\n| Matomo    | Angular | ngx-matomo-client                                                                  | @ngx-matomo/tracker \u003cbr\u003e @ngx-matomo/router                                                       |\n| --------- | ------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |\n| 3 or 4    | 9 to 12 |                                                                                    | 1.x ([docs](https://github.com/EmmanuelRoux/ngx-matomo-client/blob/1.x/README.md))                |\n| 3 or 4    | 13      |                                                                                    | 2.x ([docs](https://github.com/EmmanuelRoux/ngx-matomo-client/blob/2.x/README.md))                |\n| 3 or 4    | 14      |                                                                                    | 3.x ([docs](https://github.com/EmmanuelRoux/ngx-matomo-client/blob/3.x/README.md))                |\n| 3 or 4    | 15      | 5.x ([docs](https://github.com/EmmanuelRoux/ngx-matomo-client/blob/5.x/README.md)) | 4.0.x ([docs](https://github.com/EmmanuelRoux/ngx-matomo-client/blob/4.0.x/README.md))            |\n| 3, 4 or 5 | 16      | 5.x ([docs](https://github.com/EmmanuelRoux/ngx-matomo-client/blob/5.x/README.md)) | 4.x ([docs](https://github.com/EmmanuelRoux/ngx-matomo-client/blob/4.x/README.md)) _(deprecated)_ |\n| 3, 4 or 5 | 17      | 6.x                                                                                |                                                                                                   |\n| 3, 4 or 5 | 18      | 6.2.x or above                                                                     |                                                                                                   |\n| 3, 4 or 5 | 19      | 7.x                                                                                |                                                                                                   |\n\n[![build](https://github.com/EmmanuelRoux/ngx-matomo-client/actions/workflows/main.yml/badge.svg)](https://github.com/EmmanuelRoux/ngx-matomo-client/actions/workflows/main.yml)\n[![CodeQL](https://github.com/EmmanuelRoux/ngx-matomo-client/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/EmmanuelRoux/ngx-matomo-client/actions/workflows/github-code-scanning/codeql)\n[![Coverage Status](https://coveralls.io/repos/github/EmmanuelRoux/ngx-matomo-client/badge.svg?branch=main)](https://coveralls.io/github/EmmanuelRoux/ngx-matomo-client?branch=main)\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-limegreen.svg?logo=prettier)](https://github.com/prettier/prettier)\n\n\u003c!-- prettier-ignore-start --\u003e\n\n\u003c!-- toc --\u003e\n\n- [Installation](#installation)\n- [Usage](#usage)\n  * [Tracking page views](#tracking-page-views)\n  * [Adding info or customizing automatic page view tracking](#adding-info-or-customizing-automatic-page-view-tracking)\n  * [Tracking events](#tracking-events)\n  * [Managing user consent: opt-in/opt-out for tracking \u0026 cookies](#managing-user-consent-opt-inopt-out-for-tracking--cookies)\n  * [Tracker API](#tracker-api)\n- [Plugins](#plugins)\n  * [Form analytics](#form-analytics)\n- [Migration from `@ngx-matomo/tracker` and `@ngx-matomo/router` (version \u003c= 4)](#migration-from-ngx-matomotracker-and-ngx-matomorouter-version--4)\n- [Configuration reference](#configuration-reference)\n- [FAQ](#faq)\n  * [How to use `ngx-matomo-client` without `@angular/router`?](#how-to-use-ngx-matomo-client-without-angularrouter)\n  * [How to set page title?](#how-to-set-page-title)\n  * [Should I include the tracking code provided by Matomo?](#should-i-include-the-tracking-code-provided-by-matomo)\n  * [How to disable tracking in some environments?](#how-to-disable-tracking-in-some-environments)\n  * [How to exclude some routes from tracking](#how-to-exclude-some-routes-from-tracking)\n  * [How can I customize the inserted script tag?](#how-can-i-customize-the-inserted-script-tag)\n  * [Can I use `ngx-matomo-client` with Server-side rendering (SSR) / Angular Universal?](#can-i-use-ngx-matomo-client-with-server-side-rendering-ssr--angular-universal)\n  * [Can I use `ngx-matomo-client` with Tag Manager?](#can-i-use-ngx-matomo-client-with-tag-manager)\n  * [How to define configuration asynchronously? (HTTP fetch...)](#how-to-define-configuration-asynchronously-http-fetch)\n  * [How can I test my components which uses `MatomoTracker` or other Matomo features?](#how-can-i-test-my-components-which-uses-matomotracker-or-other-matomo-features)\n- [Roadmap](#roadmap)\n- [Contributing](#contributing)\n- [Launch demo app](#launch-demo-app)\n\n\u003c!-- tocstop --\u003e\n\n\u003c!-- prettier-ignore-end --\u003e\n\n## Installation\n\nRun `ng add ngx-matomo-client`\n\nThis will prompt you for some information such as your Matomo's server address and site ID. You can find your site ID in\nMatomo admin panel.\n\nThis command will set up basic configuration into your root `AppModule`\n(use `ng add ngx-matomo-client --module [module]` to specify a different root module). You can then take a look\nat [configuration reference](#configuration-reference) for fine-grained set-up.\n\n\u003cdetails\u003e\n  \u003csummary\u003eIf you're not using Angular CLI, follow these instructions instead\u003c/summary\u003e\n\nRun `npm install --save ngx-matomo-client` or `yarn add ngx-matomo-client` then\nmanually import Matomo into your Angular application:\n\n```ts\nimport { provideMatomo } from 'ngx-matomo-client';\n\nawait bootstrapApplication(RootComponent, {\n  providers: [\n    provideMatomo({\n      siteId: 1,\n      trackerUrl: 'http://my-matomo-instance',\n    }),\n  ],\n});\n```\n\nOr, if you use `@NgModule`:\n\n```ts\nimport { MatomoModule } from 'ngx-matomo-client';\n\n@NgModule({\n  imports: [\n    MatomoModule.forRoot({\n      siteId: 1,\n      trackerUrl: 'http://my-matomo-instance',\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\nTake a look at [configuration reference](#configuration-reference) for all available configuration properties.\n\n\u003c/details\u003e\n\n\u003e **Note:** in this documentation, all code examples use imports from `ngx-matomo-client` because this is the most\n\u003e common use case.\n\u003e **If you don't have `@angular/router` in you application, you must import from `ngx-matomo-client/core` instead.**\n\u003e\n\u003e See [FAQ](#how-to-use-ngx-matomo-client-without-angularrouter) for more details.\n\n## Usage\n\n### Tracking page views\n\nEnable automatic page view tracking by adding `withRouter()` feature to `provideMatomo()`:\n\n```ts\nimport { provideMatomo, withRouter } from 'ngx-matomo-client';\n\nawait bootstrapApplication(RootComponent, {\n  providers: [\n    provideMatomo(\n      {\n        siteId: 1,\n        trackerUrl: 'http://my-matomo-instance',\n      },\n      withRouter(),\n    ),\n  ],\n});\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee equivalent configuration with \u003ccode\u003e@NgModule\u003c/code\u003e\u003c/summary\u003e\n\n```ts\nimport { MatomoModule, MatomoRouterModule } from 'ngx-matomo-client';\n\n@NgModule({\n  imports: [\n    MatomoModule.forRoot({\n      siteId: 1,\n      trackerUrl: 'http://my-matomo-instance',\n    }),\n    MatomoRouterModule,\n  ],\n})\nexport class AppModule {}\n```\n\n\u003c/details\u003e\n\nThis will track every page view using Angular Router.\n\nIf you wish to manually track page views instead, inject `MatomoTracker` and call `trackPageView()` or other\ndesired methods (`setCustomUrl`, `setReferrerUrl`...):\n\n```typescript\nimport { MatomoTracker } from 'ngx-matomo-client';\n\n@Component({\n  selector: 'app-example',\n  templateUrl: './example.component.html',\n  styleUrls: ['./example.component.scss'],\n})\nexport class ExampleComponent implements OnInit {\n  private readonly tracker = inject(MatomoTracker);\n\n  ngOnInit() {\n    this.tracker.trackPageView();\n  }\n}\n```\n\n### Adding info or customizing automatic page view tracking\n\nBy default, Matomo detects page title and url. Page title is read from Angular's `Title` service (which itself is filled with route's `'title'` key) if available, or from document title. You may override defaults as described below.\n\n#### Using route data\n\n1. Configure `ngx-matomo-client` to read from route data:\n\n```ts\nimport { provideMatomo, withRouter, withRouteData } from 'ngx-matomo-client';\n\nawait bootstrapApplication(RootComponent, {\n  providers: [\n    provideMatomo(\n      {\n        /* ... */\n      },\n      withRouter(),\n      withRouteData(), // Add this feature\n    ),\n  ],\n});\n```\n\nBy default, Matomo properties are looked-up at `matomo` key of Angular route data.\nYou may define another key by providing it as an argument to `withRouteData`:\n\n```ts\n// provideMatomo()\nwithRouteData('myCustomKey');\n\n// Route data:\nconst routes: Routes = [\n  {\n    path: 'hello',\n    component: HelloComponent,\n    data: {\n      myCustomKey: {\n        ecommerce: {\n          productSKU: '12345',\n        },\n      } as MatomoRouteData,\n    },\n  },\n];\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee equivalent configuration with \u003ccode\u003e@NgModule\u003c/code\u003e\u003c/summary\u003e\n\n```ts\nimport { MatomoModule, MatomoRouterModule, MatomoRouteDataInterceptor } from 'ngx-matomo-client';\n\n@NgModule({\n  imports: [\n    MatomoModule.forRoot({\n      /* ... */\n    }),\n    MatomoRouterModule.forRoot({\n      interceptors: [MatomoRouteDataInterceptor], // Add this configuration\n    }),\n  ],\n  providers: [\n    // Optionally, define another key to look-up at:\n    {\n      provide: MATOMO_ROUTE_DATA_KEY,\n      useValue: 'myCustomKey',\n    },\n  ],\n})\nexport class AppModule {}\n```\n\n\u003c/details\u003e\n\n2. Then, declare route data under `matomo` key:\n\n```ts\nimport { MatomoRouteData } from './route-data-interceptor';\n\nconst routes: Routes = [\n  {\n    path: '',\n    component: HomeComponent,\n    title: 'My home page', // \u003c-- Matomo will use this title by default, if available\n    data: {\n      matomo: {\n        title: 'My home page title for Matomo', // \u003c-- You can override the title sent to Matomo\n      } as MatomoRouteData,\n    },\n  },\n  {\n    path: 'hello',\n    component: HelloComponent,\n    title: 'My home page', // \u003c-- Matomo will use this title if available\n    data: {\n      matomo: {\n        ecommerce: {\n          productSKU: '12345',\n          productName: 'French baguette',\n        },\n      } as MatomoRouteData,\n    },\n  },\n\n  // Data can also be retrieve asynchronously using 'resolve':\n  {\n    path: ':productId',\n    component: ProductComponent,\n    resolve: {\n      matomo: async (route: ActivatedRouteSnapshot): Promise\u003cMatomoRouteData\u003e =\u003e {\n        // Load any asynchronous data\n        const product = await inject(MyProductService).loadProductData(route.params.productId);\n\n        return {\n          ecommerce: {\n            productSKU: product.sku,\n          },\n        };\n      },\n    },\n  },\n];\n```\n\nFollowing properties are available:\n\n| Property                    | Type     |\n| --------------------------- | -------- |\n| `title`                     | `string` |\n| `ecommerce.productSKU`      | `string` |\n| `ecommerce.productName`     | `string` |\n| `ecommerce.productCategory` | `string` |\n| `ecommerce.price`           | `number` |\n| `ecommerce.quantity`        | `number` |\n\n#### Using custom interceptor\n\nIf you need custom logic to extract data, define a custom interceptor implementation.\nAn interceptor may be either a _function_ or a _class_:\n\n```ts\nimport {\n  MatomoRouterInterceptor,\n  MatomoRouterInterceptorFn,\n  MatomoRouteInterceptorBase,\n} from 'ngx-matomo-client';\n\n/** A simple functional interceptor */\nconst myInterceptorFn: MatomoRouterInterceptorFn = (event: NavigationEnd) =\u003e {\n  const tracker = inject(MatomoTracker);\n\n  tracker.setDocumentTitle('My title');\n  tracker.setEcommerceView(/* ... */);\n};\n\n/** A class interceptor must implement `MatomoRouterInterceptor` */\n@Injectable()\nexport class MySimpleInterceptor implements MatomoRouterInterceptor {\n  private readonly tracker = inject(MatomoTracker);\n\n  beforePageTrack(event: NavigationEnd): void {\n    this.tracker.setDocumentTitle('My title');\n    this.tracker.setEcommerceView(/* ... */);\n  }\n}\n\n/**\n * For interceptors that need access to ActivatedRouteSnapshot, you may extend\n * `MatomoRouteInterceptorBase` built-in class.\n */\n@Injectable()\nexport class MyAsyncInterceptor extends MatomoRouteInterceptorBase\u003cstring\u003e {\n  private readonly tracker = inject(MatomoTracker);\n\n  protected extractRouteData(route: ActivatedRouteSnapshot): string {\n    return route.paramMap.get('productId');\n  }\n\n  protected async processRouteData(productId: string): Promise\u003cvoid\u003e {\n    const product = await this.loadProductData(productId);\n\n    this.tracker.setEcommerceView(productId, product.name);\n  }\n}\n```\n\nAnd provide it in your application:\n\n```typescript\nimport { withRouterInterceptors, MatomoRouterInterceptor } from 'ngx-matomo-client';\n\nawait bootstrapApplication(RootComponent, {\n  providers: [\n    provideMatomo(\n      {\n        /* ... */\n      },\n      withRouter(),\n\n      // Add interceptors here:\n      withRouterInterceptors([myInterceptorFn, MySimpleInterceptor, MyAsyncInterceptor]),\n    ),\n  ],\n});\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee equivalent configuration with \u003ccode\u003e@NgModule\u003c/code\u003e\u003c/summary\u003e\n\n```ts\n@NgModule({\n  imports: [\n    MatomoModule.forRoot({\n      /* ... */\n    }),\n    MatomoRouterModule.forRoot({\n      // Add interceptors here:\n      interceptors: [myInterceptorFn, MySimpleInterceptor, MyAsyncInterceptor],\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n\u003c/details\u003e\n\n### Tracking events\n\nYou can track click events in templates using `[matomoClickAction]` directive:\n\n```html\n\u003cbutton\n  type=\"button\"\n  matomoClickCategory=\"myCategory\"\n  matomoClickAction=\"myAction\"\n  matomoClickName=\"myName\"\n  [matomoClickValue]=\"42\"\n\u003e\n  Example for tracking button clicks\n\u003c/button\u003e\n\u003c!-- Inputs [matomoClickName] and [matomoClickValue] are optional --\u003e\n```\n\nYou can also track any kind of events using `[matomoTracker]` directive:\n\n```html\n\u003c!-- Tracking \"change\" event on an input --\u003e\n\u003cinput\n  type=\"text\"\n  matomoTracker=\"change\"\n  matomoCategory=\"myCategory\"\n  matomoAction=\"myAction\"\n  matomoName=\"myName\"\n  [matomoValue]=\"myValue\"\n/\u003e\n\n\u003c!-- Tracking multiple events --\u003e\n\u003cinput\n  type=\"text\"\n  [matomoTracker]=\"['focus', 'blur']\"\n  matomoCategory=\"myCategory\"\n  matomoAction=\"myAction\"\n  matomoName=\"myName\"\n/\u003e\n\n\u003c!-- For advanced usage, you may export directive as a variable and call its 'trackEvent()' method --\u003e\n\u003cinput\n  type=\"text\"\n  matomoTracker\n  #tracker=\"matomo\"\n  matomoCategory=\"myCategory\"\n  matomoAction=\"myAction\"\n  matomoName=\"myName\"\n  [matomoValue]=\"myValue\"\n  (change)=\"tracker.trackEvent()\"\n/\u003e\n\n\u003c!-- You may also set default values and overwrite them in method call --\u003e\n\u003cinput\n  type=\"text\"\n  matomoTracker\n  #tracker=\"matomo\"\n  matomoCategory=\"myCategory\"\n  matomoAction=\"myAction\"\n  (focus)=\"tracker.trackEvent('focus')\"\n  (blur)=\"tracker.trackEvent('blur')\"\n/\u003e\n```\n\n_**Note for standalone components users:** all `ngx-matomo-client` components and directives are standalone\nand can be imported where you need them. You may also want to import all of them at once using `MATOMO_DIRECTIVES`._\n\n### Managing user consent: opt-in/opt-out for tracking \u0026 cookies\n\nMatomo supports multiple options to allow requiring user consent for tracking.\n\nTo identify whether you need to ask for any consent, you need to determine whether your lawful basis for processing\npersonal data is \"Consent\" or \"Legitimate interest\", or whether you can avoid collecting personal data altogether.\n\n#### Do not track\n\n_Do not track_ feature is supported, just set `acceptDoNotTrack` configuration option.\n\nPlease note that _do-not-track_ setting is also configured server-side! You should likely set this setting here to match\nyour server-side configuration. In case users opt-in for _do-not-track_:\n\n- If set to `true` here, users will not be tracked, independently of you server-side setting.\n- If set to `false` here (the default), users will be tracked depending on your server setting, **but tracking requests\n  and cookies will still be created!**\n\n[See official guide](https://fr.matomo.org/docs/privacy-how-to/#step-4-respect-donottrack-preference)\n\n#### Consent opt-in\n\nBy default, no consent is required. To manage consent opt-in, first set dedicated configuration option `requireConsent` to either `'cookie'` or `'tracking'`:\n\n- In the context of \u003cb\u003etracking consent\u003c/b\u003e no cookies will be used and no tracking request will be sent unless consent\n  was given. As soon as consent was given, tracking requests will be sent and cookies will be used.\n- In the context of \u003cb\u003ecookie consent\u003c/b\u003e tracking requests will be always sent. However, cookies will be only used if\n  consent for storing and using cookies was given by the user.\n\n[See official guide](https://developer.matomo.org/guides/tracking-consent)\n\nFor integration with a consent opt-in form, you may want to use following `MatomoTracker` methods:\n\n- `isConsentRequired()`\n- `setConsentGiven()` / `setCookieConsentGiven()`\n- `rememberConsentGiven(hoursToExpire?: number)` / `rememberCookieConsentGiven(hoursToExpire?: number)`\n- `forgetConsentGiven()` / `forgetCookieConsentGiven()`\n- `hasRememberedConsent()` / `areCookiesEnabled()`\n- `getRememberedConsent()` / `getRememberedCookieConsent()`\n\nSee also example below on how to create a consent form. Example below is about creating an opt-out form, but it may be\neasily adapted using methods listed above.\n\n#### Consent opt-out\n\nTo manage consent opt-out, use dedicated methods `MatomoTracker.optUserOut()` and `MatomoTracker.forgetUserOptOut()`.\n\nA (very) simple form is provided through `\u003cmatomo-opt-out-form\u003e` component.\n\nFor more advanced integration with a custom form, you may want to define your own component and use `MatomoTracker`\nmethods:\n\n```html\n\u003cp\u003eTo opt-out, please activate the checkbox below to receive an opt-out cookie.\u003c/p\u003e\n\u003cp\u003e\n  \u003clabel\u003e\n    \u003cinput type=\"checkbox\" [ngModel]=\"optedOut$ | async\" (ngModelChange)=\"handleChange($event)\" /\u003e\n    \u003cng-container *ngIf=\"optedOut$ | async; else: optedIn\"\u003e\n      You are currently opted out. Click here to opt in.\n    \u003c/ng-container\u003e\n    \u003cng-template #optedIn\u003eYou are currently opted in. Click here to opt out.\u003c/ng-template\u003e\n  \u003c/label\u003e\n\u003c/p\u003e\n```\n\n```typescript\n@Component({\n  selector: 'my-opt-out-form',\n  templateUrl: '...',\n})\nexport class MatomoOptOutFormComponent {\n  optedOut$: Promise\u003cboolean\u003e;\n\n  constructor(private readonly tracker: MatomoTracker) {\n    this.optedOut$ = tracker.isUserOptedOut();\n  }\n\n  handleChange(optOut: boolean) {\n    if (optOut) {\n      this.tracker.optUserOut();\n    } else {\n      this.tracker.forgetUserOptOut();\n    }\n\n    this.optedOut$ = this.tracker.isUserOptedOut();\n  }\n}\n```\n\nThis example is adapted from\n[official guide](https://developer.matomo.org/guides/tracking-javascript-guide#optional-creating-a-custom-opt-out-form)\nabout how to create a custom opt-out form\n\n### Tracker API\n\nAll Matomo tracking features are available through `MatomoTracker` service. Please refer\nto [Matomo documentation](https://fr.matomo.org/docs) for details.\n\n```typescript\nimport { Component, inject } from '@angular/core';\nimport { MatomoTracker } from 'ngx-matomo-client';\n\n@Component({\n  /* ... */\n})\nexport class ExampleComponent {\n  private readonly tracker = inject(MatomoTracker);\n\n  myMethod() {\n    // Example of using e-commerce features:\n    this.tracker.setEcommerceView('product-SKU', 'My product name', 'Product category', 999);\n    this.tracker.addEcommerceItem('product-SKU');\n    this.tracker.trackEcommerceCartUpdate(999);\n    this.tracker.trackEcommerceOrder('order-id', 999);\n\n    // ... many more methods are available\n  }\n}\n```\n\nPlease note that most features (such as `setEcommerceView`) must be called **before**\n`trackPageView`! You may want to take a look\nat [how to use interceptors](#adding-info-or-customizing-automatic-page-view-tracking).\n\n## Plugins\n\n### Form analytics\n\n**Form Analytics support is currently experimental. [Please report any bugs](https://github.com/EmmanuelRoux/ngx-matomo-client/issues), and pull requests are highly appreciated!**\n\n#### Configuration\n\nForm analytics plugin is supported out-of-the-box. Add `withFormAnalytics()` feature to `provideMatomo()`:\n\n```ts\nimport { withFormAnalytics } from 'ngx-matomo-client/form-analytics';\n\nawait bootstrapApplication(RootComponent, {\n  providers: [\n    provideMatomo(\n      {}, // Your base configuration\n      withFormAnalytics(), // Add this feature\n    ),\n  ],\n});\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee equivalent configuration with \u003ccode\u003e@NgModule\u003c/code\u003e\u003c/summary\u003e\n\n```ts\nimport { MatomoFormAnalyticsModule } from 'ngx-matomo-client/form-analytics';\n\n@NgModule({\n  imports: [\n    NgxMatomoModule.forRoot({\n      /* ... */\n    }),\n    MatomoFormAnalyticsModule,\n  ],\n})\nexport class AppModule {}\n```\n\n\u003c/details\u003e\n\n#### Usage\n\nMatomo client will automatically scan for forms in your pages after each page tracking.\n\nIf some forms are dynamically added in your components on another timing, you can use `matomoTrackForm` or\n`matomoTrackForms` directives to track them:\n\n```html\n\u003c!-- Adding matomoTrackForm directive will ensure the form is always tracked --\u003e\n\u003cform id=\"myForm\" matomoTrackForm\u003e\u003c/form\u003e\n```\n\nIf the content of your form is dynamic, and you want to correctly track inner form controls, you will have to rescan the\nform after changes:\n\n```html\n\u003cform id=\"myForm\" matomoTrackForm\u003e\n  \u003c!-- Add matomoTrackFormField directive to ensure the form is tracked --\u003e\n  \u003cinput *ngIf=\"condition\" matomoTrackFormField /\u003e\n\u003c/form\u003e\n```\n\nIf a _container_ is dynamically toggled, you can track multiple descendant forms at once by using `matomoTrackForms` (note the final _s_) on the container:\n\n```html\n\u003cdiv *ngIf=\"showFormsCondition\" matomoTrackForms\u003e\n  \u003cform id=\"myForm1\"\u003e...\u003c/form\u003e\n  \u003cform id=\"myForm2\"\u003e...\u003c/form\u003e\n\u003c/div\u003e\n```\n\nTo automatically track a form submit when an element is clicked (for example a non-submit button), add `matomoTrackFormSubmit` on the button:\n\n```html\n\u003cform id=\"myForm\" matomoTrackForm\u003e\n  \u003cbutton type=\"button\" matomoTrackFormSubmit\u003eNon-native submit\u003c/button\u003e\n\u003c/form\u003e\n```\n\nYou can also inject `MatomoFormAnalytics` service in your components and use low-level api directly.\n\nSee official guide at https://developer.matomo.org/guides/form-analytics.\n\n## Migration from `@ngx-matomo/tracker` and `@ngx-matomo/router` (version \u003c= 4)\n\nStarting from version 5, this library is distributed as a single package named `ngx-matomo-client` instead\nof `@ngx-matomo/tracker` and `@ngx-matomo/router`.\n\n**Run `ng add ngx-matomo-client` to migrate your code automatically.**\n\nTo manually migrate your code:\n\n1. In your `package.json`, replace `@ngx-matomo/tracker` dependency with `ngx-matomo-client`\n2. In your `package.json`, remove `@ngx-matomo/router` dependency\n3. Replace all imports from `@ngx-matomo/tracker` or `@ngx-matomo/router` with imports from `ngx-matomo-client` instead.\n\nAlso, feel free to use the new `NgModule`-free way of providing `ngx-matomo-client` using `provideMatomo()` function\ninstead of importing `NgxMatomoModule` and `NgxMatomoRouterModule`.\n\n## Configuration reference\n\n[Find all options and features here](docs/configuration-reference.md)\n\n## FAQ\n\n### How to use `ngx-matomo-client` without `@angular/router`?\n\nIf you don't have `@angular/router` in your application, you will encounter errors when declaring imports\nfrom `ngx-matomo-client`.\n\n**Instead, you must use imports from `ngx-matomo-client/core`.**\n\n\u003e This is because `ngx-matomo-client` is composed of two entry points:\n\u003e\n\u003e - `ngx-matomo-client/core` which contains core features and doesn't depend on `@angular/router`\n\u003e - `ngx-matomo-client/router` which brings router features and depends on `@angular/router`\n\u003e\n\u003e For backward compatibility reasons, the global entrypoint `ngx-matomo-client` is a shorthand that re-exports both of them (thus depending on `@angular/router`).\n\n### How to set page title?\n\nIf automatic page view tracking is enabled, then you probably have nothing to do: the page title will be detected and\nsent to Matomo.\n\n- Customizing page title by setting `title` property of Angular route config is natively supported.\n  See Angular tutorial here: [Setting the page title](https://angular.io/guide/router#setting-the-page-title).\n  Please note this will not work if you set Matomo router `delay` option to `-1`.\n- For more complex logic, you may also define an interceptor that will call `tracker.setDocumentTitle(title)`.\n  See [dedicated section](#adding-info-or-customizing-automatic-page-view-tracking).\n\nIf you're not using automatic page view tracking, then you should manually call `tracker.setDocumentTitle(title)`\nor `tracker.trackPageView(title)`.\n\n### Should I include the tracking code provided by Matomo?\n\nNo, by default `ngx-matomo-client` includes Matomo's tracking script for you, so **you don't need to copy/paste the\ntracking code into your application**.\n\nIf you are not using the default configuration and set the initialization mode to `'manual'`, then you must include the tracking code yourself [as explained on official guide](https://developer.matomo.org/guides/tracking-javascript-guide).\n\n### How to disable tracking in some environments?\n\nYou may want to disable tracker in dev environments to avoid tracking some unwanted usage: local dev usage, end-to-end\ntests...\n\nTo do so just set the `disabled` property to `true` in your main configuration:\n\n```typescript\nawait bootstrapApplication(RootComponent, {\n  providers: [\n    provideMatomo({\n      /* ... */\n      disabled: !environment.production,\n    }),\n  ],\n});\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee equivalent configuration with \u003ccode\u003e@NgModule\u003c/code\u003e\u003c/summary\u003e\n\n```typescript\n@NgModule({\n  imports: [\n    MatomoModule.forRoot({\n      /* ... */\n      disabled: !environment.production,\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n\u003c/details\u003e\n\n### How to exclude some routes from tracking\n\nIf you are using automatic route tracking and want to ignore some routes, use\nthe `exclude` option of router configuration:\n\n```ts\nawait bootstrapApplication(RootComponent, {\n  providers: [\n    provideMatomo(\n      {\n        /* ... */\n      },\n      withRouter({\n        exclude: [/some-pattern$/],\n      }),\n    ),\n  ],\n});\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee equivalent configuration with \u003ccode\u003e@NgModule\u003c/code\u003e\u003c/summary\u003e\n\n```ts\n@NgModule({\n  imports: [\n    MatomoModule.forRoot({\n      /* ... */\n    }),\n    MatomoRouterModule.forRoot({\n      exclude: [/some-pattern$/],\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n\u003c/details\u003e\n\n### How can I customize the inserted script tag?\n\nBy default, Matomo's script is injected using a basic script tag looking\nlike `\u003cscript src=\"...\" defer async type=\"text/javascript\"\u003e`.\n\nTo customize this script tag, define a custom script factory function:\n\n```ts\nimport { createDefaultMatomoScriptElement } from 'ngx-matomo-client';\n\nconst myScriptFactory: MatomoScriptFactory = (\n  scriptUrl: string,\n  document: Document,\n): HTMLScriptElement =\u003e {\n  // Option 1: create using default built-in factory\n  const script = createDefaultMatomoScriptElement(scriptUrl, document);\n\n  // Option 2: Manually create a script element\n  const script = document.createElement('script');\n  script.url = scriptUrl;\n\n  // Customize what you want\n  script.setAttribute('data-cookieconsent', 'statistics');\n\n  return script;\n};\n```\n\nAnd provide it to your application:\n\n```ts\nimport { withScriptFactory } from 'ngx-matomo-client';\n\nawait bootstrapApplication(RootComponent, {\n  providers: [\n    provideMatomo(\n      {\n        /* ... */\n      },\n      withScriptFactory(myScriptFactory),\n    ),\n  ],\n});\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee equivalent configuration with \u003ccode\u003e@NgModule\u003c/code\u003e\u003c/summary\u003e\n\n```ts\nimport { MATOMO_SCRIPT_FACTORY } from 'ngx-matomo-client';\n\n@NgModule({\n  imports: [\n    MatomoModule.forRoot({\n      /* ... */\n    }),\n  ],\n  providers: [\n    {\n      provide: MATOMO_SCRIPT_FACTORY,\n      useValue: myScriptFactory,\n    },\n  ],\n})\nexport class AppModule {}\n```\n\n\u003c/details\u003e\n\n### Can I use `ngx-matomo-client` with Server-side rendering (SSR) / Angular Universal?\n\nYes. `ngx-matomo-client` automatically disables itself on non-browser platforms.\n\n### Can I use `ngx-matomo-client` with Tag Manager?\n\nYes.\n\nIn such case, you don't have to set yourself the `trackerUrl` and `siteId`.\nDuring install with `ng add`, leave `serverUrl` and `siteId` blank and provide a value for `scriptUrl`.\n\nYour configuration may look like that:\n\n```ts\nimport { withScriptFactory } from 'ngx-matomo-client';\n\nawait bootstrapApplication(RootComponent, {\n  providers: [\n    provideMatomo({\n      /* ... */\n      scriptUrl: 'YOUR_MATOMO_SCRIPT_URL', // your Matomo's script url\n    }),\n  ],\n});\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee equivalent configuration with \u003ccode\u003e@NgModule\u003c/code\u003e\u003c/summary\u003e\n\n```ts\n@NgModule({\n  imports: [\n    MatomoModule({\n      /* ... */\n      scriptUrl: 'YOUR_MATOMO_SCRIPT_URL', // your Matomo's script url\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n\u003c/details\u003e\n\n### How to define configuration asynchronously? (HTTP fetch...)\n\nIn some case, you may want to load your trackers configuration asynchronously. To do so, set the configuration mode\nto `'deferred'` and manually call `MatomoInitializerService.initializeTracker(config)` when you are ready:\n\n```ts\nawait bootstrapApplication(RootComponent, {\n  providers: [\n    provideMatomo({\n      /* ... */\n      mode: 'deferred',\n    }),\n\n    // Example: use an APP_INITIALIZER\n    {\n      provide: APP_INITIALIZER,\n      useFactory: () =\u003e {\n        const http = inject(HttpClient);\n        const matomoInitializer = inject(MatomoInitializerService);\n\n        return () =\u003e\n          http.get('/my-config').pipe(tap(config =\u003e matomoInitializer.initializeTracker(config)));\n      },\n      multi: true,\n    },\n  ],\n});\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee equivalent configuration with \u003ccode\u003e@NgModule\u003c/code\u003e\u003c/summary\u003e\n\n```ts\n@NgModule({\n  imports: [\n    MatomoModule.forRoot({\n      /* ... */\n      mode: 'deferred',\n    }),\n  ],\n  providers: [\n    // Example: use an APP_INITIALIZER\n    {\n      provide: APP_INITIALIZER,\n      useFactory: () =\u003e {\n        const http = inject(HttpClient);\n        const matomoInitializer = inject(MatomoInitializerService);\n\n        return () =\u003e\n          http.get('/my-config').pipe(tap(config =\u003e matomoInitializer.initializeTracker(config)));\n      },\n      multi: true,\n    },\n  ],\n})\nexport class AppModule {}\n```\n\n\u003c/details\u003e\n\nAll tracking instructions before `initializeTracker` will be queued locally and sent only when this method is called.\n**Don't forget to call it!**\n\nIf you need to asynchronously load more configuration properties, then\nconsider [the solution described in this issue](https://github.com/EmmanuelRoux/ngx-matomo-client/issues/31) instead (which has\nsome drawbacks, such as delaying the whole application startup).\n\n_Side note: only the **trackers** configuration can be deferred, not all configuration properties.\nThis is required because some properties require to be set **before** any other action is tracked. For\nexample: `requireConsent` must be set before any other tracking call, `trackAppInitialLoad` should be set before\nany navigation occurs._\n\n### How can I test my components which uses `MatomoTracker` or other Matomo features?\n\nMatomo can be easily mocked and tested by declaring either `provideMatomoTesting()` providers or `MatomoTestingModule` in `TestBed`.\n\nAll these symbols can be imported from `ngx-matomo-client/testing`.\n\n## Roadmap\n\n[See roadmap here](docs/roadmap.md)\n\n## Contributing\n\n[See guide here](./CONTRIBUTING.md)\n\n## Launch demo app\n\n1. Clone this repository\n2. Update `matomoSiteId` and `matomoTrackerUrl` in `projects/demo/src/environments/environment.ts`\n3. Launch the app using `npm run demo`. This will build and launch the app on `http://localhost:4200`\n\nNote: if you can't bind to an existing Matomo server, see https://github.com/matomo-org/docker to set-up a local Matomo\ninstance\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEmmanuelRoux%2Fngx-matomo-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FEmmanuelRoux%2Fngx-matomo-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEmmanuelRoux%2Fngx-matomo-client/lists"}