1
1
import { Injectable , Inject , Optional , NgZone , InjectionToken } from '@angular/core' ;
2
- import { Observable , from , of } from 'rxjs' ;
3
- import { map , switchMap , tap , filter } from 'rxjs/operators' ;
2
+ import { Observable , from } from 'rxjs' ;
3
+ import { map , tap , filter , withLatestFrom } from 'rxjs/operators' ;
4
4
import { FirebaseAppConfig , FirebaseOptions , runOutsideAngular } from '@angular/fire' ;
5
- import { Router , NavigationEnd } from '@angular/router' ;
5
+ import { Router , NavigationEnd , ActivationEnd } from '@angular/router' ;
6
6
import { FirebaseAnalytics , FIREBASE_OPTIONS , FIREBASE_APP_NAME , _firebaseAppFactory } from '@angular/fire' ;
7
7
8
8
export const AUTOMATICALLY_SET_CURRENT_SCREEN = new InjectionToken < boolean > ( 'angularfire2.analytics.setCurrentScreen' ) ;
9
9
export const ANALYTICS_COLLECTION_ENABLED = new InjectionToken < boolean > ( 'angularfire2.analytics.analyticsCollectionEnabled' ) ;
10
10
export const AUTOMATICALLY_TRACK_USER_IDENTIFIER = new InjectionToken < boolean > ( 'angularfire2.analytics.trackUserIdentifier' ) ;
11
+ export const APP_VERSION = new InjectionToken < string > ( 'angularfire2.analytics.appVersion' ) ;
12
+ export const APP_NAME = new InjectionToken < string > ( 'angularfire2.analytics.appName' ) ;
13
+
14
+ export const DEFAULT_APP_VERSION = '?' ;
15
+ export const DEFAULT_APP_NAME = 'Angular App' ;
11
16
12
17
@Injectable ( )
13
18
export class AngularFireAnalytics {
@@ -24,45 +29,46 @@ export class AngularFireAnalytics {
24
29
@Optional ( ) @Inject ( AUTOMATICALLY_SET_CURRENT_SCREEN ) automaticallySetCurrentScreen :boolean | null ,
25
30
@Optional ( ) @Inject ( ANALYTICS_COLLECTION_ENABLED ) analyticsCollectionEnabled :boolean | null ,
26
31
@Optional ( ) @Inject ( AUTOMATICALLY_TRACK_USER_IDENTIFIER ) automaticallyTrackUserIdentifier :boolean | null ,
27
- private zone : NgZone
32
+ @Optional ( ) @Inject ( APP_VERSION ) providedAppVersion :string | null ,
33
+ @Optional ( ) @Inject ( APP_NAME ) providedAppName :string | null ,
34
+ zone : NgZone
28
35
) {
29
36
// @ts -ignore zapping in the UMD in the build script
30
37
const requireAnalytics = from ( import ( 'firebase/analytics' ) ) ;
38
+ const app = _firebaseAppFactory ( options , nameOrConfig ) ;
31
39
32
40
this . analytics = requireAnalytics . pipe (
33
- map ( ( ) => _firebaseAppFactory ( options , nameOrConfig ) ) ,
34
- map ( app => app . analytics ( ) ) ,
41
+ map ( ( ) => app . analytics ( ) ) ,
35
42
tap ( analytics => {
36
- if ( analyticsCollectionEnabled == false ) { analytics . setAnalyticsCollectionEnabled ( false ) }
43
+ if ( analyticsCollectionEnabled === false ) { analytics . setAnalyticsCollectionEnabled ( false ) }
37
44
} ) ,
38
45
runOutsideAngular ( zone )
39
46
) ;
40
47
41
48
if ( router && automaticallySetCurrentScreen !== false ) {
42
- this . analytics . pipe (
43
- switchMap ( analytics =>
44
- router . events . pipe (
45
- filter < NavigationEnd > ( e => e instanceof NavigationEnd ) ,
46
- tap ( e => console . log ( e ) ) ,
47
- tap ( e => analytics . setCurrentScreen ( e . url ) )
48
- )
49
- )
49
+ const app_name = providedAppName || DEFAULT_APP_NAME ;
50
+ const app_version = providedAppVersion || DEFAULT_APP_VERSION ;
51
+ const activationEndEvents = router . events . pipe ( filter < ActivationEnd > ( e => e instanceof ActivationEnd ) ) ;
52
+ const navigationEndEvents = router . events . pipe ( filter < NavigationEnd > ( e => e instanceof NavigationEnd ) ) ;
53
+ navigationEndEvents . pipe (
54
+ withLatestFrom ( activationEndEvents , this . analytics ) ,
55
+ tap ( ( [ navigationEnd , activationEnd , analytics ] ) => {
56
+ const url = navigationEnd . url ;
57
+ const screen_name = activationEnd . snapshot . routeConfig && activationEnd . snapshot . routeConfig . path || undefined ;
58
+ const outlet = activationEnd . snapshot . outlet ;
59
+ analytics . logEvent ( "screen_view" , { app_name, app_version, screen_name, outlet, url } ) ;
60
+ // TODO when is screen_name undefined?
61
+ analytics . setCurrentScreen ( screen_name || url , { global : outlet == "primary" } )
62
+ } ) ,
63
+ runOutsideAngular ( zone )
50
64
) . subscribe ( ) ;
51
65
}
52
66
53
- if ( automaticallyTrackUserIdentifier !== false ) {
54
- this . analytics . pipe (
55
- switchMap ( analytics => {
56
- if ( analytics . app . auth ) {
57
- const auth = analytics . app . auth ( ) ;
58
- return new Observable < firebase . User | null > ( auth . onAuthStateChanged . bind ( auth ) ) . pipe (
59
- tap ( user => console . log ( "uid" , user && user . uid ) ) ,
60
- tap ( user => user ? analytics . setUserId ( user . uid ) : analytics . setUserId ( null ! ) )
61
- )
62
- } else {
63
- return of ( )
64
- }
65
- } ) ,
67
+ // TODO do something other than just check auth presence, what if it's lazy loaded?
68
+ if ( app . auth && automaticallyTrackUserIdentifier !== false ) {
69
+ new Observable < firebase . User | null > ( app . auth ( ) . onAuthStateChanged . bind ( app . auth ( ) ) ) . pipe (
70
+ withLatestFrom ( this . analytics ) ,
71
+ tap ( ( [ user , analytics ] ) => analytics . setUserId ( user ? user . uid : null ! , { global : true } ) ) ,
66
72
runOutsideAngular ( zone )
67
73
) . subscribe ( )
68
74
}
0 commit comments