import { Inject , Injectable , InjectionToken , NgZone , Optional , PLATFORM_ID } from '@angular/core' ; import { EMPTY , of } from 'rxjs' ; import { isPlatformBrowser } from '@angular/common' ; import { map , shareReplay , switchMap , observeOn } from 'rxjs/operators' ; import { ɵAngularFireSchedulers } from '@angular/fire' ; import { ɵlazySDKProxy , ɵPromiseProxy , ɵapplyMixins , ɵcacheInstance } from '@angular/fire/compat' ; import { FirebaseApp } from '@angular/fire/compat' ; import firebase from 'firebase/compat/app' ; import { proxyPolyfillCompat } from './base' ; import { isSupported } from 'firebase/analytics' ; export interface Config { [ key ] : any ; } export const COLLECTION_ENABLED = new InjectionToken < boolean > ( 'angularfire2.analytics.analyticsCollectionEnabled' ) ; export const APP_VERSION = new InjectionToken < string > ( 'angularfire2.analytics.appVersion' ) ; export const APP_NAME = new InjectionToken < string > ( 'angularfire2.analytics.appName' ) ; export const DEBUG_MODE = new InjectionToken < boolean > ( 'angularfire2.analytics.debugMode' ) ; export const CONFIG = new InjectionToken < Config > ( 'angularfire2.analytics.config' ) ; const APP_NAME_KEY = 'app_name' ; const APP_VERSION_KEY = 'app_version' ; const DEBUG_MODE_KEY = 'debug_mode' ; const GTAG_CONFIG_COMMAND = 'config' ; const GTAG_FUNCTION_NAME = 'gtag' ; const DATA_LAYER_NAME = 'dataLayer' ; const SEND_TO_KEY = 'send_to' ; export interface AngularFireAnalytics extends ɵPromiseProxy < firebase . analytics . Analytics > { } @ Injectable ( { providedIn : 'any' } ) export class AngularFireAnalytics { private measurementId : string ; private analyticsInitialized : Promise < void > = new Promise ( ( ) => { } ) ; async updateConfig ( config ) { await this . analyticsInitialized ; window [ GTAG_FUNCTION_NAME ] ( GTAG_CONFIG_COMMAND , this . measurementId , { ... config , update : true } ) ; } constructor ( app , @ Optional ( ) @ Inject ( COLLECTION_ENABLED ) analyticsCollectionEnabled , @ Optional ( ) @ Inject ( APP_VERSION ) providedAppVersion , @ Optional ( ) @ Inject ( APP_NAME ) providedAppName , @ Optional ( ) @ Inject ( DEBUG_MODE ) debugModeEnabled , @ Optional ( ) @ Inject ( CONFIG ) providedConfig , @ Inject ( PLATFORM_ID ) platformId , zone , schedulers ) { if ( isPlatformBrowser ( platformId ) ) { window [ DATA_LAYER_NAME ] = window [ DATA_LAYER_NAME ] || [ ] ; const parseMeasurementId = ( ... args ) => { if ( args [ 0 ] === 'config' && args [ 2 ] . origin === 'firebase' ) { this . measurementId = args [ 1 ] ; return true ; } else { return false ; } } ; const patchGtag = ( fn ? ) => { window [ GTAG_FUNCTION_NAME ] = ( ... args ) => { if ( fn ) { fn ( ... args ) ; } if ( args [ 0 ] === 'event' && args [ 2 ] [ SEND_TO_KEY ] === this . measurementId ) { if ( providedAppName ) { args [ 2 ] [ APP_NAME_KEY ] = providedAppName ; } if ( providedAppVersion ) { args [ 2 ] [ APP_VERSION_KEY ] = providedAppVersion ; } } if ( debugModeEnabled && typeof console !== 'undefined' ) { console . info ( ... args ) ; } /**
                     * According to the gtag documentation, this function that defines a custom data layer cannot be
                     * an arrow function because 'arguments' is not an array. It is actually an object that behaves
                     * like an array and contains more information then just indexes. Transforming this into arrow function
                     * caused issue #2505 where analytics no longer sent any data.
                     */ ( function ( ... _args ) { window [ DATA_LAYER_NAME ] . push ( arguments ) ; } ) ( ... args ) ; } ; } ; const firebaseAnalyticsAlreadyInitialized = window [ DATA_LAYER_NAME ] . some ( parseMeasurementId ) ; if ( firebaseAnalyticsAlreadyInitialized ) { this . analyticsInitialized = Promise . resolve ( ) ; patchGtag ( ) ; } else { this . analyticsInitialized = new Promise ( resolve => { patchGtag ( ( ... args ) => { if ( parseMeasurementId ( ... args ) ) { resolve ( ) ; } } ) ; } ) ; } if ( providedConfig ) { this . updateConfig ( providedConfig ) ; } if ( debugModeEnabled ) { this . updateConfig ( { [ DEBUG_MODE_KEY ] : 1 } ) ; } } else { this . analyticsInitialized = Promise . resolve ( ) ; } const analytics = of ( undefined ) . pipe ( observeOn ( schedulers . outsideAngular ) , switchMap ( isSupported ) , switchMap ( supported => supported ? zone . runOutsideAngular ( ( ) => import ( 'firebase/compat/analytics' ) ) : EMPTY ) , map ( ( ) => { return ɵcacheInstance ( `analytics` , 'AngularFireAnalytics' , app . name , ( ) => { const analytics = app . analytics ( ) ; if ( analyticsCollectionEnabled === false ) { analytics . setAnalyticsCollectionEnabled ( false ) ; } return analytics ; } , [ app , analyticsCollectionEnabled , providedConfig , debugModeEnabled ] ) ; } ) , shareReplay ( { bufferSize : 1 , refCount : false } ) ) ; return ɵlazySDKProxy ( this , analytics , zone ) ; } } ɵapplyMixins ( AngularFireAnalytics , [ proxyPolyfillCompat ] ) ;