File

libs/ngx-pfe/tracking/tracking.service.ts

Description

The PfeTrackingService makes it easier to use the Tracking Library (https://github.developer.allianz.io/ilt/tracking) in combination with the pfe.

It automatically initializes trackify with the configuration from the NgxPfeModuleConfiguration. Page change events are automatically pushed.

The tracking service also provides the functionality to track values in the state. This can be configured in the appConfiguration.

Index

Properties
Methods

Constructor

constructor(ngxPfeModuleConfiguration: NgxPfeModuleConfiguration, pfeBusinessService: PfeBusinessService, pfeNavigationService: PfeNavigationService, pfeConfigurationService: PfeConfigurationService, pfeUtilService: PfeUtilService)
Parameters :
Name Type Optional
ngxPfeModuleConfiguration NgxPfeModuleConfiguration No
pfeBusinessService PfeBusinessService No
pfeNavigationService PfeNavigationService No
pfeConfigurationService PfeConfigurationService No
pfeUtilService PfeUtilService No

Methods

Public ngOnDestroy
ngOnDestroy()
Returns : void
pushEvent
pushEvent(event: string, value, ignorePageId?: boolean)
Parameters :
Name Type Optional
event string No
value No
ignorePageId boolean Yes
Returns : void
trackifyPageChange
trackifyPageChange(pageId: string)
Parameters :
Name Type Optional
pageId string No
Returns : void

Properties

componentDestroyed$
Default value : new Subject<void>()
import {
  NGX_PFE_CONFIGURATION,
  NgxPfeModuleConfiguration,
  PfeBusinessService,
  PfeConfigurationService,
  PfeNavigationService,
  PfeUserInputState,
  PfeUtilService,
  StateValueTracking,
} from '@allianz/ngx-pfe';
import { pushEvent, trackifyInit, trackifyPageChange } from '@allianz/tracking';
import { TrackifyWindow } from '@allianz/tracking/models/trackify.model';
import { Inject, Injectable, NgZone, OnDestroy, inject } from '@angular/core';
import { OperatorFunction, Subject } from 'rxjs';
import { debounceTime, filter, takeUntil } from 'rxjs/operators';

/**
 * The PfeTrackingService makes it easier to use the Tracking Library
 * (https://github.developer.allianz.io/ilt/tracking) in combination with the pfe.
 *
 * It automatically initializes trackify with the configuration from the NgxPfeModuleConfiguration.
 * Page change events are automatically pushed.
 *
 * The tracking service also provides the functionality to track values in the state.
 * This can be configured in the appConfiguration.
 *
 */
@Injectable()
export class PfeTrackingService implements OnDestroy {
  componentDestroyed$ = new Subject<void>();

  private didFirstNavigationHappen = false;
  private preInitEventBuffer: { event: string; value: unknown; ignorePageId: boolean | undefined }[] = [];

  private ngZone = inject(NgZone);

  constructor(
    @Inject(NGX_PFE_CONFIGURATION)
    private ngxPfeModuleConfiguration: NgxPfeModuleConfiguration,
    private pfeBusinessService: PfeBusinessService,
    private pfeNavigationService: PfeNavigationService,
    private pfeConfigurationService: PfeConfigurationService,
    private pfeUtilService: PfeUtilService
  ) {
    if (this.ngxPfeModuleConfiguration.tracking) {
      this.pfeUtilService.trackingEvents$.pipe(takeUntil(this.componentDestroyed$)).subscribe((event) => {
        this.pushEvent(event.event, event.value, event.ignorePageId);
      });
      this.pfeUtilService.trackingStateRestored$.pipe(takeUntil(this.componentDestroyed$)).subscribe((restoredState) => {
        this.pushStateRestoreTrackingEvent(restoredState);
      });

      this.pfeNavigationService.currentPageId$
        .pipe(
          takeUntil(this.componentDestroyed$), //
          filter((pageID) => pageID !== undefined) as OperatorFunction<string | undefined, string>
        )
        .subscribe((pageID) => {
          this.didFirstNavigationHappen = true;
          if (!(window as unknown as TrackifyWindow).trackifyInitialized) {
            this.trackifyInit();
            this.emptyTrackingEventsBuffer();
          } else {
            this.trackifyPageChange(pageID);
            this.emptyTrackingEventsBuffer();
          }
        });

      this.initializeStateValueTracking();
    }
  }

  trackifyPageChange(pageId: string) {
    if (pageId) {
      this.ngZone.runOutsideAngular(() => {
        trackifyPageChange(pageId);
      });
    }
  }

  public ngOnDestroy() {
    this.componentDestroyed$.next();
    this.componentDestroyed$.complete();
  }

  pushEvent(event: string, value: unknown, ignorePageId?: boolean) {
    if (!this.didFirstNavigationHappen) {
      this.preInitEventBuffer.push({ event, value, ignorePageId });
      return;
    }
    this.ngZone.runOutsideAngular(() => {
      pushEvent(event, value, ignorePageId);
    });
  }

  private trackifyInit() {
    const trackifyConfig = {
      production: this.ngxPfeModuleConfiguration.production,
      appName: this.ngxPfeModuleConfiguration.tracking?.appName || this.ngxPfeModuleConfiguration.applicationId,
      googleId: this.ngxPfeModuleConfiguration.tracking?.googleId,
      adobeUrl: this.ngxPfeModuleConfiguration.tracking?.adobeUrl,
      customScript: this.ngxPfeModuleConfiguration.tracking?.customScript,
      pageId: this.pfeNavigationService.currentPageId$.value,
    };

    this.ngZone.runOutsideAngular(() => {
      trackifyInit(trackifyConfig);
    });
  }

  private emptyTrackingEventsBuffer() {
    for (const event of this.preInitEventBuffer) {
      this.pushEvent(event.event, event.value, event.ignorePageId);
    }

    this.preInitEventBuffer = [];
  }

  private initializeStateValueTracking() {
    this.pfeConfigurationService.getConfig().then((pfeConfig) => {
      if (pfeConfig?.appConfiguration?.pfeConfig?.trackingConfig?.stateTracking) {
        pfeConfig.appConfiguration.pfeConfig.trackingConfig.stateTracking.forEach((stateTrackingConfig) => {
          const eventName = this.determineStateTrackingEventName(stateTrackingConfig);

          this.pfeBusinessService
            .getObservableForExpressionKey(stateTrackingConfig.stateKeyExpression, true)
            .pipe(debounceTime(200), takeUntil(this.componentDestroyed$))
            .subscribe((value) => {
              this.pushEvent(eventName, value, stateTrackingConfig.ignorePageId);
            });
        });
      }
    });
  }

  private async pushStateRestoreTrackingEvent(restoredState: PfeUserInputState) {
    const config = await this.pfeConfigurationService.getConfig();
    if (!config?.appConfiguration?.pfeConfig?.trackingConfig?.stateTracking) {
      return;
    }
    // eslint-disable-next-line @typescript-eslint/ban-types
    const eventData: Record<string, unknown> = {};

    config.appConfiguration.pfeConfig.trackingConfig.stateTracking.forEach((stateTrackingConfig) => {
      const eventName = this.determineStateTrackingEventName(stateTrackingConfig);
      const value = PfeUtilService.getValueOrList(restoredState, stateTrackingConfig.stateKeyExpression);

      eventData[eventName] = value;
    });

    this.pushEvent(
      `${this.ngxPfeModuleConfiguration.tracking?.appName || this.ngxPfeModuleConfiguration.applicationId}.restoringPFEState`,
      eventData
    );
  }

  private determineStateTrackingEventName(stateTrackingConfig: StateValueTracking) {
    return stateTrackingConfig.event ? stateTrackingConfig.event : stateTrackingConfig.stateKeyExpression.replace(/^(\$\.)/, '');
  }
}

results matching ""

    No results matching ""