Google Analytics

Transactions
Dan 2017-10-04 22:00:25 -06:00
parent efd886cd09
commit 4d0d5644dd
11 changed files with 220 additions and 15 deletions

15
.vscode/launch.json vendored 100644
View File

@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:4200",
"webRoot": "${workspaceRoot}"
}
]
}

View File

@ -1,4 +1,5 @@
import { EventService } from './services/event.service';
import { GoogleAnalyticsService } from './services/google-analytics.service';
import { WindowRefService } from './services/window-ref.service';
import { EmailService } from './services/email.service';
import { SermonService } from './services/sermon.service';
@ -156,7 +157,7 @@ const Routes =
RouterModule.forRoot(Routes)
],
providers: [LoginService,SermonService,EventService,ProgressService,EmailService,WindowRefService,{provide:BrowserXhr,useClass:ProgressXhr}],
providers: [LoginService,GoogleAnalyticsService,SermonService,EventService,ProgressService,EmailService,WindowRefService,{provide:BrowserXhr,useClass:ProgressXhr}],
entryComponents: [AddSermonPopupComponent,
LoginPopupComponent,
OkPopupComponent,

View File

@ -1,5 +1,6 @@
import { GoogleAnalyticsService } from './../../services/google-analytics.service';
import { Component, Inject, Injectable, HostListener } from '@angular/core';
import { Router, NavigationStart, Event } from '@angular/router';
import { Router, NavigationEnd, Event } from '@angular/router';
import { EventService } from '../../services/event.service';
import { AudioPlayerService } from '../../services/audio-player.service';
import { BibleVerseService } from '../../services/bible-verse.service';
@ -23,16 +24,21 @@ export class AppComponent {
lastScrollPos: number = 0;
showAudioPlayer: boolean = false;
constructor(private router: Router, private audioPlayerService: AudioPlayerService){
constructor(private router: Router,
private audioPlayerService: AudioPlayerService,
private googleAnalyticsService: GoogleAnalyticsService){
this.router.events.subscribe((event:Event) => {
if(event instanceof NavigationStart) {
if(event instanceof NavigationEnd) {
this.lastRoute = this.currRoute;
this.currRoute = event.url;
this.currRoute = event.urlAfterRedirects;
let doc = document.documentElement;
let scrollPos = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
if (event.url === '/home'){
let url = event.urlAfterRedirects;
if (url === '/home'){
this.fadeHeader = true;
this.headerOpacity = 0;
} else {
@ -46,6 +52,8 @@ export class AppComponent {
}
this.lastRoute = event.url;
this.lastScrollPos = scrollPos;
// Google Analytics
googleAnalyticsService.pageView(url.substr(1),url);
}
});

View File

@ -1,3 +1,4 @@
import { GoogleAnalyticsService } from './../../services/google-analytics.service';
import { Component, OnInit, OnDestroy, Output, EventEmitter } from '@angular/core';
import { AudioPlayerService } from '../../services/audio-player.service';
import { AudioStates } from '../../enum/audio-states';
@ -29,7 +30,8 @@ export class AudioPlayerComponent implements OnInit, OnDestroy {
@Output()
started: EventEmitter<string> = new EventEmitter();
constructor(private audioPlayerService: AudioPlayerService){
constructor(private audioPlayerService: AudioPlayerService,
private googleAnalyticsService: GoogleAnalyticsService){
}
@ -41,20 +43,44 @@ export class AudioPlayerComponent implements OnInit, OnDestroy {
this.audioDuration = this.audioPlayerService.getDuration();
this.currentTime = this.audioPlayerService.getCurrentTime();
if (this.audioState == AudioStates.Loading){
this.started.emit("loading");
this.started.emit("loading");
}
if (this.audioState == AudioStates.Playing){
this.started.emit("playing");
this.interval = setInterval(()=>{
this.audioDuration = this.audioPlayerService.getDuration();
this.currentTime = this.audioPlayerService.getCurrentTime();
},1000);
},1000);
} else {
clearInterval(this.interval);
}
this.sendGoogleAnalytics(state,error);
});
}
sendGoogleAnalytics(state: AudioStates, error: any){
switch (state) {
case AudioStates.Error:
this.googleAnalyticsService.audioError(this.audioFileId, this.audioFileTitle, error)
break;
case AudioStates.Loading:
this.googleAnalyticsService.loadingSermon(this.audioFileId,this.audioFileTitle);
break;
case AudioStates.Paused:
this.googleAnalyticsService.pauseSermon(this.audioFileId,this.audioFileTitle,this.audioPlayerService.getCurrentTime())
break;
case AudioStates.Playing:
this.googleAnalyticsService.playSermon(this.audioFileId,this.audioFileTitle,this.audioPlayerService.getCurrentTime())
break;
default:
break;
}
}
play(): void{
this.audioPlayerService.resume();
}

View File

@ -1,3 +1,4 @@
import { GoogleAnalyticsService } from './../../services/google-analytics.service';
import { MdDialog, MdDialogConfig, MdSnackBar } from '@angular/material';
import { ActivatedRoute, Params } from '@angular/router';
import { EventService } from './../../services/event.service';
@ -28,7 +29,8 @@ export class EventsPageComponent implements OnInit {
private dialog: MdDialog,
private snackbar: MdSnackBar,
private activatedRoute: ActivatedRoute,
private audioPlayerService: AudioPlayerService) {
private audioPlayerService: AudioPlayerService,
private googleAnalyticsService: GoogleAnalyticsService) {
this.loginService.isLoggedIn(true).subscribe(is => { this.loggedIn = is; });
this.loginService.onLogin().subscribe(is => { this.loggedIn = is.isLoggedIn; });
this.audioPlayerService.onAudioPlayerOpenClose.subscribe(is => this.audioPlayerOpen = is);
@ -41,7 +43,7 @@ export class EventsPageComponent implements OnInit {
id = Number.isNaN(id) ? -1 : id;
if (id > -1){
this.getSingleEvent(id);
this.showAllButtonVisible = true;
this.showAllButtonVisible = true;
} else {
this.getEvents(true);
this.showAllButtonVisible = false;
@ -71,6 +73,7 @@ export class EventsPageComponent implements OnInit {
this.eventService.getSingleEvent(id).subscribe(event => {
this.events.push(event);
this.loading = false;
this.googleAnalyticsService.shareEventConversion(event.id,event.title);
});
}

View File

@ -1,6 +1,6 @@
<div md-dialog-title>Share</div>
<div md-dialog-content>
<a [href]="facebookIframeUrl | safeUrl" target="_blank">
<a (click)="facebookShare()" [href]="facebookIframeUrl | safeUrl" target="_blank">
<div class="social-wrapper facebook" data-network="facebook" draggable="false" style="display: inline-block;">
<svg fill="#fff" preserveAspectRatio="xMidYMid meet" height="1.2em" width="1.2em" viewBox="0 0 40 40">
<g>
@ -10,7 +10,7 @@
<span class="st-label">Share</span>
</div>
</a>
<a [href]="twitterUrl | safeUrl" target="_blank">
<a (click)="twitterShare()" [href]="twitterUrl | safeUrl" target="_blank">
<div class="social-wrapper twitter" data-network="facebook" draggable="false" style="display: inline-block;">
<svg fill="#fff" preserveAspectRatio="xMidYMid meet" height="1.2em" width="1.2em" viewBox="0 0 40 40">
<g>

View File

@ -1,3 +1,4 @@
import { GoogleAnalyticsService } from './../../../services/google-analytics.service';
import { MdDialogRef, MdSnackBar } from '@angular/material';
import { DOCUMENT } from '@angular/platform-browser';
import { MD_DIALOG_DATA } from '@angular/material';
@ -24,7 +25,8 @@ export class SharePopupComponent implements OnInit {
constructor(@Inject(MD_DIALOG_DATA) public data: any,
@Inject(DOCUMENT) private document,
private mdDialogRef: MdDialogRef<SharePopupComponent>,
private snackbar: MdSnackBar) {
private snackbar: MdSnackBar,
private googleAnalyticsService: GoogleAnalyticsService) {
this.id = data.id;
let port = this.document.location.port ? ":"+this.document.location.port : "";
this.shareUrl = this.document.location.protocol +'//'+ this.document.location.hostname + port + this.shareBaseUrl + data.prefix + this.id;
@ -48,8 +50,25 @@ export class SharePopupComponent implements OnInit {
let s = this.snackbar.open("Link Copied","OK");
s.onAction().subscribe(()=>{ s.dismiss(); });
s.afterOpened().subscribe(()=>{ setTimeout(()=>{ s.dismiss(); },3000); });
this.share("link");
} catch (err) {
console.error('Oops, unable to copy');
}
}
share(method: string){
if (this.data.prefix === 's'){
this.googleAnalyticsService.shareSermon(Number(this.id),this.data.title,method);
} else if (this.data.prefix === 'e'){
this.googleAnalyticsService.shareEvent(Number(this.id),this.data.title,method);
}
}
facebookShare(){
this.share('facebook');
}
twitterShare(){
this.share('twitter');
}
}

View File

@ -0,0 +1,15 @@
import { TestBed, inject } from '@angular/core/testing';
import { GoogleAnalyticsService } from './google-analytics.service';
describe('GoogleAnalyticsService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [GoogleAnalyticsService]
});
});
it('should be created', inject([GoogleAnalyticsService], (service: GoogleAnalyticsService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,106 @@
declare var gtag;
import { Injectable } from '@angular/core';
@Injectable()
export class GoogleAnalyticsService {
private trackingId: string = 'UA-107601801-1';
private baseUrl: string = 'https://ofbbutte.com';
private lastSermonId: number = 0;
private lastSermonStartPos: number = 0;
constructor() { }
public pageView(title: string, path: string){
gtag('config', this.trackingId, {
'page_title': title,
'page_location': this.baseUrl + path,
'page_path': path
});
}
public searchSermon(searchTerm: string){
gtag('event', 'search', {
'search_term': searchTerm
});
}
public shareSermon(id: number, title: string, method: string){
gtag('event', 'share', {
'method': method,
'content_type': 'audio',
'content_id': id,
'content_title': title
});
}
public shareEvent(id: number, title: string, method: string){
gtag('event', 'share', {
'method': method,
'content_type': 'event',
'content_id': id,
'content_title': title
});
}
public shareSermonConversion(id: number, title: string){
gtag('event', 'share_conversion', {
'content_type': 'audio',
'content_id': id,
'content_title': title
});
}
public shareEventConversion(id: number, title: string){
gtag('event', 'share_conversion', {
'content_type': 'event',
'content_id': id,
'content_title': title
});
}
public loadingSermon(id: number, title: string){
gtag('event', 'audio_loading', {
'audio_id': id,
'audio_title': title
});
}
public playSermon(id: number, title: string, position: number){
this.lastSermonId = id;
this.lastSermonStartPos = position;
gtag('event', 'audio_play', {
'audio_id': id,
'audio_title': title,
'audio_start_position': position
});
}
public pauseSermon(id: number, title: string, position: number){
let duration = null;
let lastStartPos = null;
if (id == this.lastSermonId){
duration = position - this.lastSermonStartPos;
lastStartPos = this.lastSermonStartPos;
} else {
}
gtag('event', 'audio_pause', {
'audio_id': id,
'audio_title': title,
'audio_start_position': lastStartPos,
'audio_pause_position': position,
'audio_listen_duration': duration
});
}
public audioError(id: number, title: string, error: string){
gtag('event', 'audio_error', {
'audio_id': id,
'audio_title': title,
'audio_error_message': error
});
}
}

View File

@ -4,6 +4,18 @@
<base href="/">
<meta charset="utf-8">
<title>Old Fashion Baptist Church</title>
<!-- Google Analytics -->
<!-- Global Site Tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-107601801-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-107601801-1', { 'send_page_view': false });
</script>
<!---->
<!-- Favicons -->
<link rel="apple-touch-icon" sizes="180x180" href="/web-app-files/apple-touch-icon.png?v=LbWKNzlwGb">

View File

@ -1,7 +1,7 @@
#!/bin/sh
BUILD_ANGULAR_ARG=$1
BUILD_ANGULAR=false
BUILD_ANGULAR=true
if [ "$BUILD_ANGULAR_ARG" = -ng ]; then
BUILD_ANGULAR=true
fi