Skip to content

Instantly share code, notes, and snippets.

@AVatch
Created January 31, 2018 16:27
Show Gist options
  • Save AVatch/7800945368b24842b07719c0310976c2 to your computer and use it in GitHub Desktop.
Save AVatch/7800945368b24842b07719c0310976c2 to your computer and use it in GitHub Desktop.
Google Analytics (Or any other analytics) + Angular / NGRX
/**
* src/effects/auth.ts
* Similiar pattern for all other Effects
*/
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import { Injectable } from '@angular/core';
import { Location } from '@angular/common';
import { Action } from '@ngrx/store';
import { Effect, Actions } from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { AuthProvider } from '../providers/auth/auth';
import { GaProvider } from '../providers/ga/ga';
import * as auth from '../actions/auth';
@Injectable()
export class AuthEffects {
constructor(
private actions$: Actions,
private ga: GaProvider,
private authProvider: AuthProvider,
) { }
/**
* LOGIN EFFECTS
*/
@Effect()
login$: Observable<Action> = this.actions$
.ofType(auth.LOGIN)
.map((action:auth.LoginAction) => action.payload)
.switchMap((payload) =>
this.authProvider.login$({username:payload.username, password:payload.password})
.map((res) => new auth.LoginSuccessAction(res))
.catch((err) => of(new auth.LoginFailAction(err)))
);
/**
* REGISTER EFFECTS
*/
@Effect()
register$:Observable<Action> = this.actions$
.ofType(auth.REGISTER)
.map((action:auth.RegisterAction) => action.payload)
.switchMap((payload) =>
this.authProvider.register$(payload)
.map((res) => new auth.RegisterSuccessAction({username:payload.username, password:payload.password}))
.catch((err) => of(new auth.RegisterFailAction(err)))
);
@Effect()
onRegisterSuccessDoLogin$:Observable<Action> = this.actions$
.ofType(auth.REGISTER_SUCCESS)
.map((action:auth.RegisterSuccessAction) => action.payload)
.map((payload) => new auth.LoginAction(payload));
/**
* LOGOUT EFFECTS
*/
@Effect()
logout$:Observable<Action> = this.actions$
.ofType(auth.LOGOUT)
.map(() => new auth.LogoutSuccessAction());
/**
* Google Analytics
*/
@Effect({dispatch:false})
logEvent$ = this.actions$
.ofType(
auth.LOGIN_SUCCESS,
auth.LOGIN_FAIL,
auth.REGISTER_SUCCESS,
auth.REGISTER_FAIL,
auth.PASSWORD_RESET,
auth.LOGOUT_SUCCESS,
auth.LOGOUT_FAIL
)
.do((action) => this.ga.logEvent('auth', action.type));
}
/**
* src/providers/ga/ga.ts
*/
// You can obtain this from your Google Analytics Tracking JS Code
import { GAtrackingId } from '../../environments/keys';
import { Injectable } from '@angular/core';
import { Location } from '@angular/common';
@Injectable()
export class GaProvider {
constructor(private location:Location) { }
private useGA() : boolean {
return GAtrackingId && typeof ga !== undefined;
}
/**
* We have a method which injects the Google Analytics Tracking Snipper
* with optional override for the userId
*/
initGA(userId:string='auto'):void {
if (!GAtrackingId) return;
let scriptId = 'google-analytics';
if (document.getElementById(scriptId)) {
return;
}
var el = document.createElement('script') as any;
el.type = "text/javascript";
el.id = scriptId;
el.innerText = `
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', '${GAtrackingId}', '${userId}');
`.replace(/\r?\n|\r/g, '');
document.getElementsByTagName("body")[0].appendChild(el);
}
/**
* Wrapper around the pageview call. We strip id's (in this case numbers)
* from the urls
*/
logPageView(stripIds:boolean=true):void {
if(!this.useGA()) { return; }
const path:string = this.location.path();
const cleanedPath:string = stripIds ? path.replace(/\d+/g, '<id>') : path;
ga('send', 'pageview', cleanedPath);
}
/**
* Wrapper around the event call. This get's called any time we want to
* register an event
*/
logEvent(category:string, action:string):void {
if(!this.useGA()) { return; }
ga('send', 'event', category, action);
}
}
/**
* src/actions/platform.ts
*/
import { Action } from '@ngrx/store';
export const INIT_APP = '[Platform] Init Application';
export const INIT_GA = '[Platform] Init Google Analytics';
export class InitAppAction implements Action {
readonly type = INIT_APP;
constructor() { }
}
export class InitGAAction implements Action {
readonly type = INIT_GA;
constructor() { }
}
export type All
= InitAppAction
| InitGAAction;
/**
* src/pages/somePage/somePage.ts (Ionic)
* Example of tracking events in page when you are not using router
* which is the case w/ Ionic
*/
import { Component } from '@angular/core';
import { GaProvider } from '../../providers/ga/ga';
@Component({
selector: 'page',
templateUrl: 'page.html',
})
export class SomePage {
constructor(
private ga: GaProvider,
) { }
/**
* On entry lifecycle hook, this is the case w/ Ionic,
* but something like ngOnInit is also good place to log
* the page if you can't use the router
*/
ionViewDidLoad():void {
this.ga.logPageView();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment