Closed natalie-o-perret closed 1 year ago
Hi @natalie-o-perret
Could you share your configuration please ? So I can take a deeper look
If you are using NgxMatomoModule.forRoot(...)
, it should work as-is.
If you are using provideMatomo(...)
, then you must either import each directive individually or import MATOMO_DIRECTIVES
(to import them all at once)
Hi @natalie-o-perret
Could you share your configuration please ? So I can take a deeper look
If you are using
NgxMatomoModule.forRoot(...)
, it should work as-is.If you are using
provideMatomo(...)
, then you must either import each directive individually or importMATOMO_DIRECTIVES
(to import them all at once)
Hey there @EmmanuelRoux, thanks your comment,
So I created the module below:
import { NgModule } from "@angular/core";
import { NgxMatomoModule, MatomoInitializationMode, NgxMatomoRouterModule } from "ngx-matomo-client";
import { MatomoSsoUserRouterInterceptor } from "./interceptors/matomo-sso-user-router.interceptor";
@NgModule({
declarations: [
],
imports: [
NgxMatomoModule.forRoot({
mode: MatomoInitializationMode.AUTO_DEFERRED,
}),
NgxMatomoRouterModule.forRoot({
interceptors: [
MatomoSsoUserRouterInterceptor,
]
}),
],
})
export class MatomoModule {}
as well as this service:
import { Injectable } from "@angular/core";
import { MatomoInitializerService } from "ngx-matomo-client";
import { ConfigurationService } from "../../config/services/configuration.service";
@Injectable()
export class MatomoInitializationService {
constructor(
private readonly _matomoInitializerService: MatomoInitializerService,
private readonly _configurationService: ConfigurationService)
{}
public init() {
this._matomoInitializerService.initializeTracker({
trackerUrl: this._configurationService.config.matomoTrackerUrl,
scriptUrl: this._configurationService.config.matomoScriptUrl,
siteId: this._configurationService.config.matomoId,
})
}
}
and the interceptor I've mentioned before:
import { Injectable } from '@angular/core';
import { NavigationEnd } from '@angular/router';
import { MatomoRouterInterceptor, MatomoTracker } from 'ngx-matomo-client';
import { AuthenticationService } from '../../auth/services/authentication.service';
@Injectable()
export class MatomoSsoUserRouterInterceptor implements MatomoRouterInterceptor {
constructor(
private readonly _authenticationService: AuthenticationService,
private readonly _matomoTracker: MatomoTracker
) {}
beforePageTrack(_: NavigationEnd): void {
if (this._authenticationService.isAuthenticated()) {
const identityClaims = this._authenticationService.getIdentityClaims();
if (identityClaims) {
this._matomoTracker.setUserId(identityClaims.email);
}
}
}
}
in my app.module.ts
, I roughly have something like that:
export const appInitFactory =
(
injector: Injector,
configurationService: ConfigurationService,
authenticationService: AuthenticationService,
translateService: TranslateService,
translateStorageService: TranslateStorageService,
matomoInitializationService: MatomoInitializationService
) =>
async (): Promise<void> => {
await configurationService['load']();
await authenticationService['load']();
await injector.get(LOCATION_INITIALIZED, Promise.resolve(null));
translateService.setDefaultLang('en');
translateService.addLangs(['fr', 'es']);
await firstValueFrom(
translateStorageService.getStoreAndUseOrDefaultBrowserLang(
translateService.defaultLang as Language
)
);
matomoInitializationService.init();
return;
};
function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
@NgModule({
declarations: [AppComponent, HomePageComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
TranslateModule.forRoot({
defaultLanguage: 'en',
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient],
},
missingTranslationHandler: {
provide: MissingTranslationHandler,
useClass: MissingTranslationHandlerDefault,
},
}),
AppRoutingModule,
OAuthModule.forRoot(),
MatomoModule,
CoreModule,
AppLayoutModule,
ToastModule,
ButtonModule,
LayoutModule,
],
providers: [
ConfigurationService,
MatomoInitializationService,
AuthenticationService,
{
provide: APP_INITIALIZER,
useFactory: appInitFactory,
deps: [
Injector,
ConfigurationService,
AuthenticationService,
TranslateService,
TranslateStorageService,
MatomoInitializationService,
],
multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: AuthBearerTokenInterceptor,
multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: HttpErrorInterceptorService,
multi: true,
},
{
// Processes all errors
provide: ErrorHandler,
useClass: GlobalErrorHandlerService,
},
MessageService,
],
bootstrap: [AppComponent],
})
export class AppModule { }
Try adding exports: [NgxMatomoModule]
to your MatomoModule
.
This is related to how NgModules work in Angular (see https://angular.io/guide/ngmodules)
I already tried that before for the same reason but I'm getting the same exact error.
Can you share a reproduction of the error ? (Stackblitz, repo...)
Can you share a reproduction of the error ? (Stackblitz, repo...)
I just managed to get it work, my bad, there was another export missing π€¦ββοΈ.
Tbs, not sure to fully understand the behaviour, because my MatomoModule
was already part of the AppModule
AppRoutingModule,
OAuthModule.forRoot(),
MatomoModule,
CoreModule,
AppLayoutModule,
ToastModule,
ButtonModule,
LayoutModule,
Even tried different orderings, so ended up doing adding my MatomoModule
straight to the CoreModule
exports
and there it started to work, not sure why it doesn't flow accordingly without itπ€. I guess my assumptions were wrong π
[EDIT 1]
The problem doing so, is that there are now multiple initializations. π€
I see why now, hmmmph, that's a bit of a bugger to architect that one properly π€
[EDIT 2]
Gotcha, so I wanted to wrap everything in my MatomoModule
including the init part which was called again and again upon import in another module, ended up discarding that wrapping MatomoModule
and flatten the module structure with the NgxMatomoModule
directly:
@NgModule({
declarations: [AppComponent, HomePageComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
TranslateModule.forRoot({
defaultLanguage: 'en',
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient],
},
missingTranslationHandler: {
provide: MissingTranslationHandler,
useClass: MissingTranslationHandlerDefault,
},
}),
AppRoutingModule,
OAuthModule.forRoot(),
CoreModule,
AppLayoutModule,
ToastModule,
ButtonModule,
LayoutModule,
NgxMatomoModule.forRoot({
mode: MatomoInitializationMode.AUTO_DEFERRED,
}),
NgxMatomoRouterModule.forRoot({
interceptors: [
MatomoSsoUserRouterInterceptor,
]
})
],
providers: [
ConfigurationService,
MatomoInitializationService,
AuthenticationService,
{
provide: APP_INITIALIZER,
useFactory: appInitFactory,
deps: [
Injector,
ConfigurationService,
AuthenticationService,
TranslateService,
TranslateStorageService,
MatomoInitializationService,
],
multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: AuthBearerTokenInterceptor,
multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: HttpErrorInterceptorService,
multi: true,
},
{
// Processes all errors
provide: ErrorHandler,
useClass: GlobalErrorHandlerService,
},
MessageService,
],
bootstrap: [AppComponent],
exports: []
})
export class AppModule { }
and in my core module:
exports: [
//...
NgxMatomoModule
],
Sorry about all that noise, and thanks for the pointers! πββοΈ
Hello
Thanks for your hard work! Love that your package provides some capabilities for async initialization.
I've set up Matomo and it works to some extent. I have some application in Angular using PrimeNG and I get the routing events, as well as the customized bits I'm passing (SSO user) with the interceptor. So far, so good, except when I'm using the directives in component templates like described in https://github.com/EmmanuelRoux/ngx-matomo#tracking-events, e.g.,
=>
I'm wondering if you have some hints about why this would be the case?
When using for instance something like, the other approach, event-based:
*.ts
code:*.html
template code:It works.
Notes: