├── src
├── assets
│ └── .gitkeep
├── styles.css
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── typings.d.ts
├── tsconfig.app.json
├── main.ts
├── app
│ ├── routeone
│ │ └── routeone.component.ts
│ ├── routetwo
│ │ └── routetwo.component.ts
│ ├── app.module.ts
│ └── app.component.ts
├── index.html
└── polyfills.ts
├── tsconfig.json
├── .gitignore
├── package.json
├── LICENSE
├── README.md
└── .angular-cli.json
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/src/typings.d.ts:
--------------------------------------------------------------------------------
1 | /* SystemJS module definition */
2 | declare var module: NodeModule;
3 | interface NodeModule {
4 | id: string;
5 | }
6 | interface window {
7 | ga: any;
8 | }
9 |
--------------------------------------------------------------------------------
/src/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "baseUrl": "./",
6 | "module": "es2015",
7 | "types": []
8 | },
9 | "exclude": [
10 | "test.ts",
11 | "**/*.spec.ts"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule);
12 |
--------------------------------------------------------------------------------
/src/app/routeone/routeone.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-routeone',
5 | template: `
6 |
7 | routeone Works!
8 |
9 | RouteTwo
10 | `,
11 | styles: []
12 | })
13 | export class RouteoneComponent implements OnInit {
14 |
15 | constructor() { }
16 |
17 | ngOnInit() {
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/routetwo/routetwo.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-routetwo',
5 | template: `
6 |
7 | routetwo Works!
8 |
9 | RouteOne
10 | `,
11 | styles: []
12 | })
13 | export class RoutetwoComponent implements OnInit {
14 |
15 | constructor() { }
16 |
17 | ngOnInit() {
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // The file contents for the current environment will overwrite these during build.
2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do
3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead.
4 | // The list of which env maps to which file can be found in `.angular-cli.json`.
5 |
6 | export const environment = {
7 | production: false
8 | };
9 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "outDir": "./dist/out-tsc",
5 | "sourceMap": true,
6 | "declaration": false,
7 | "moduleResolution": "node",
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "target": "es5",
11 | "typeRoots": [
12 | "node_modules/@types"
13 | ],
14 | "lib": [
15 | "es2016",
16 | "dom"
17 | ]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | /node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.sass-cache
29 | /connect.lock
30 | /coverage
31 | /libpeerconnection.log
32 | npm-debug.log
33 | testem.log
34 | /typings
35 |
36 | # e2e
37 | /e2e/*.js
38 | /e2e/*.map
39 |
40 | # System Files
41 | .DS_Store
42 | Thumbs.db
43 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule } from '@angular/platform-browser';
2 | import { NgModule } from '@angular/core';
3 | import {RouterModule} from '@angular/router';
4 |
5 | import { AppComponent } from './app.component';
6 | import { RouteoneComponent } from './routeone/routeone.component';
7 | import { RoutetwoComponent } from './routetwo/routetwo.component';
8 |
9 | @NgModule({
10 | declarations: [
11 | AppComponent,
12 | RouteoneComponent,
13 | RoutetwoComponent
14 | ],
15 | imports: [
16 | BrowserModule,
17 | RouterModule.forRoot(
18 | [
19 | { path: 'routeone', component: RouteoneComponent },
20 | { path: 'routetwo', component: RoutetwoComponent },
21 | { path: '**', redirectTo: '/routetwo' }
22 | ]
23 | )
24 | ],
25 | providers: [],
26 | bootstrap: [AppComponent]
27 | })
28 | export class AppModule { }
29 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | GoogleAnalyticsWithAngular
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import {Router, NavigationEnd} from "@angular/router";
3 |
4 | @Component({
5 | selector: 'app-root',
6 | template: `
7 |
8 | Welcome to {{title}}!!
9 |
10 |
11 |
12 | `,
13 | styles: []
14 | })
15 | export class AppComponent {
16 | title = 'app';
17 | constructor(private router: Router) {
18 | this.router.events.subscribe(event => {
19 | if (event instanceof NavigationEnd) {
20 | (window).ga('set', 'page', event.urlAfterRedirects);
21 | (window).ga('send', 'pageview');
22 | }
23 | });
24 | }
25 |
26 | sendEvent = () => {
27 | (window).ga('send', 'event', {
28 | eventCategory: 'eventCategory',
29 | eventLabel: 'eventLabel',
30 | eventAction: 'eventAction',
31 | eventValue: 10
32 | });
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "google-analytics-with-angular",
3 | "version": "0.0.0",
4 | "license": "MIT",
5 | "scripts": {
6 | "ng": "ng",
7 | "start": "ng serve",
8 | "build": "ng build",
9 | "test": "echo \"Error: no test... minimal project\" && exit 1",
10 | "lint": "echo \"Error: no lint... minimal project\" && exit 1",
11 | "e2e": "echo \"Error: no e2e... minimal project\" && exit 1"
12 | },
13 | "private": true,
14 | "dependencies": {
15 | "@angular/animations": "^4.0.0",
16 | "@angular/common": "^4.0.0",
17 | "@angular/compiler": "^4.0.0",
18 | "@angular/core": "^4.0.0",
19 | "@angular/forms": "^4.0.0",
20 | "@angular/http": "^4.0.0",
21 | "@angular/platform-browser": "^4.0.0",
22 | "@angular/platform-browser-dynamic": "^4.0.0",
23 | "@angular/router": "^4.0.0",
24 | "core-js": "^2.4.1",
25 | "rxjs": "^5.4.1",
26 | "zone.js": "^0.8.14"
27 | },
28 | "devDependencies": {
29 | "@angular/cli": "1.2.4",
30 | "@angular/compiler-cli": "^4.0.0",
31 | "@angular/language-service": "^4.0.0",
32 | "typescript": "~2.3.3"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Chidume Nnamdi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Using Google Analytics with Angular
2 |
3 | This app demonstrates how to track and record pageview events in an Angular (SPA) application.
4 |
5 | * View the Medium article at [Using Google Analytics with Angular](https://medium.com/@kurtwanger40/using-google-analytics-with-angular-25c93bffaa18)
6 |
7 | # Technologies
8 | - Angular
9 | - Google Analytics
10 |
11 | # Setup and Usage
12 | 1. Setup up a Google Analytics account.
13 | 1. Clone this repo:
14 |
15 | git clone https://github.com/philipszdavido/google-analytics-with-angular.git
16 |
17 | 1. Move into the `google-analytics-with-angular` directory from the terminal:
18 |
19 | cd google-analytics-with-angular
20 |
21 | 1. Install the dependencies: `npm install`
22 | 1. Open `index.html` in your editor, and change the `UA-109919601-1` code to yours.
23 | 1. Run the app:
24 |
25 | ng serve
26 |
27 | 1. Navigate to `localhost:4200` in your browser.
28 | 1. Click on the links `routeOne` `routeTwo` and the button `Click Me` to see Google Analytics record the events.
29 |
30 | ## How can I thank You
31 | Why not star the github repo? The attention would be appreciated! How about sharing the link for this repo on Twitter?
32 |
33 | Dont forget to [follow me on Twitter!](https://twitter.com/ngArchangel)
34 |
35 | Thanks! Chidume Nnamdi
36 |
--------------------------------------------------------------------------------
/.angular-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "project": {
4 | "name": "google-analytics-with-angular"
5 | },
6 | "apps": [
7 | {
8 | "root": "src",
9 | "outDir": "dist",
10 | "assets": [
11 | "assets",
12 | "favicon.ico"
13 | ],
14 | "index": "index.html",
15 | "main": "main.ts",
16 | "polyfills": "polyfills.ts",
17 | "test": "test.ts",
18 | "tsconfig": "tsconfig.app.json",
19 | "testTsconfig": "tsconfig.spec.json",
20 | "prefix": "app",
21 | "styles": [
22 | "styles.css"
23 | ],
24 | "scripts": [],
25 | "environmentSource": "environments/environment.ts",
26 | "environments": {
27 | "dev": "environments/environment.ts",
28 | "prod": "environments/environment.prod.ts"
29 | }
30 | }
31 | ],
32 | "e2e": {
33 | "protractor": {
34 | "config": "./protractor.conf.js"
35 | }
36 | },
37 | "lint": [
38 | {
39 | "project": "src/tsconfig.app.json",
40 | "exclude": "**/node_modules/**"
41 | },
42 | {
43 | "project": "src/tsconfig.spec.json",
44 | "exclude": "**/node_modules/**"
45 | },
46 | {
47 | "project": "e2e/tsconfig.e2e.json",
48 | "exclude": "**/node_modules/**"
49 | }
50 | ],
51 | "test": {
52 | "karma": {
53 | "config": "./karma.conf.js"
54 | }
55 | },
56 | "defaults": {
57 | "styleExt": "css",
58 | "component": {
59 | "spec": false,
60 | "inlineStyle": true,
61 | "inlineTemplate": true
62 | },
63 | "directive": {
64 | "spec": false
65 | },
66 | "class": {
67 | "spec": false
68 | },
69 | "guard": {
70 | "spec": false
71 | },
72 | "module": {
73 | "spec": false
74 | },
75 | "pipe": {
76 | "spec": false
77 | },
78 | "service": {
79 | "spec": false
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/
22 | // import 'core-js/es6/symbol';
23 | // import 'core-js/es6/object';
24 | // import 'core-js/es6/function';
25 | // import 'core-js/es6/parse-int';
26 | // import 'core-js/es6/parse-float';
27 | // import 'core-js/es6/number';
28 | // import 'core-js/es6/math';
29 | // import 'core-js/es6/string';
30 | // import 'core-js/es6/date';
31 | // import 'core-js/es6/array';
32 | // import 'core-js/es6/regexp';
33 | // import 'core-js/es6/map';
34 | // import 'core-js/es6/weak-map';
35 | // import 'core-js/es6/set';
36 |
37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
38 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
39 |
40 | /** Evergreen browsers require these. **/
41 | import 'core-js/es6/reflect';
42 | import 'core-js/es7/reflect';
43 |
44 |
45 | /**
46 | * Required to support Web Animations `@angular/animation`.
47 | * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
48 | **/
49 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
50 |
51 |
52 |
53 | /***************************************************************************************************
54 | * Zone JS is required by Angular itself.
55 | */
56 | import 'zone.js/dist/zone'; // Included with Angular CLI.
57 |
58 |
59 |
60 | /***************************************************************************************************
61 | * APPLICATION IMPORTS
62 | */
63 |
64 | /**
65 | * Date, currency, decimal and percent pipes.
66 | * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
67 | */
68 | // import 'intl'; // Run `npm install --save intl`.
69 | /**
70 | * Need to import at least one locale-data with intl.
71 | */
72 | // import 'intl/locale-data/jsonp/en';
73 |
--------------------------------------------------------------------------------