Skip to content

Commit aca64c2

Browse files
authored
feat: adding ootb providers (#1128)
* feat: adding user telemetry config and service * feat: adding error handler and a track directive * feat: adding ootb providers * refactor: using abstract service approach * refactor: updating api for htTrack directive * revert: package-lock.json * revert: revert package.json * revert: revert package.json peer deps * refactor: adding tests and addressing commments * refactor: fix lint errors * refactor: adding packages and modifying code
1 parent 6ed8f86 commit aca64c2

File tree

11 files changed

+337
-2
lines changed

11 files changed

+337
-2
lines changed

package-lock.json

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@
6565
"rxjs": "~6.6.7",
6666
"tslib": "^2.3.1",
6767
"uuid": "^8.3.2",
68-
"zone.js": "~0.11.4"
68+
"zone.js": "~0.11.4",
69+
"@fullstory/browser": "^1.4.9",
70+
"mixpanel-browser": "^2.41.0"
6971
},
7072
"devDependencies": {
7173
"@angular-builders/jest": "^11.2.0",

projects/common/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
"zone.js": "~0.11.4",
2121
"lodash-es": "^4.17.21",
2222
"d3-interpolate": "^2.0.1",
23-
"d3-color": "^1.4.0"
23+
"d3-color": "^1.4.0",
24+
"@fullstory/browser": "^1.4.9",
25+
"mixpanel-browser": "^2.41.0"
2426
},
2527
"devDependencies": {
2628
"@hypertrace/test-utils": "^0.0.0"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Injectable } from '@angular/core';
2+
import { TelemetryProviderConfig, UserTelemetryProvider, UserTraits } from '../../telemetry';
3+
import { Dictionary } from './../../../utilities/types/types';
4+
import { FreshPaint, loadFreshPaint } from './load-snippet';
5+
6+
@Injectable({ providedIn: 'root' })
7+
export class FreshPaintTelemetry<InitConfig extends TelemetryProviderConfig>
8+
implements UserTelemetryProvider<InitConfig> {
9+
private freshPaint?: FreshPaint;
10+
11+
public initialize(config: InitConfig): void {
12+
this.freshPaint = loadFreshPaint();
13+
this.freshPaint.init(config.orgId);
14+
}
15+
16+
public identify(userTraits: UserTraits): void {
17+
this.freshPaint?.identify(userTraits.email, userTraits);
18+
this.freshPaint?.addEventProperties(userTraits);
19+
}
20+
21+
public trackEvent(name: string, properties: Dictionary<unknown>): void {
22+
this.freshPaint?.track(name, properties);
23+
}
24+
25+
public trackPage(name: string, eventData: Dictionary<unknown>): void {
26+
this.freshPaint?.page(name, name, eventData);
27+
}
28+
29+
public trackError(name: string, eventData: Dictionary<unknown>): void {
30+
this.freshPaint?.track(name, eventData);
31+
}
32+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export function loadFreshPaint(): FreshPaint;
2+
3+
export interface FreshPaint {
4+
init(orgId: string): void;
5+
identify(uid?: string, userVars?: UserVars): void;
6+
identify(userVars?: UserVars): void;
7+
track(eventName: string, properties?: {}): void;
8+
addEventProperties(userVars?: UserVars): void;
9+
page(category?: string, name?: string, userVars?: UserVars): void;
10+
}
11+
12+
interface UserVars {
13+
displayName?: string;
14+
email?: string;
15+
[key: string]: any;
16+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// tslint:disable
2+
3+
export const loadFreshPaint = () => {
4+
if (window.freshpaint) {
5+
return window.freshpaint;
6+
}
7+
(function (c, a) {
8+
if (!a.__SV) {
9+
var b = window;
10+
try {
11+
var d,
12+
m,
13+
j,
14+
k = b.location,
15+
f = k.hash;
16+
d = function (a, b) {
17+
return (m = a.match(RegExp(b + '=([^&]*)'))) ? m[1] : null;
18+
};
19+
f &&
20+
d(f, 'fpState') &&
21+
((j = JSON.parse(decodeURIComponent(d(f, 'fpState')))),
22+
'fpeditor' === j.action &&
23+
(b.sessionStorage.setItem('_fpcehash', f),
24+
history.replaceState(j.desiredHash || '', c.title, k.pathname + k.search)));
25+
} catch (n) {}
26+
var l, h;
27+
window.freshpaint = a;
28+
a._i = [];
29+
a.init = function (b, d, g) {
30+
function c(b, i) {
31+
var a = i.split('.');
32+
2 == a.length && ((b = b[a[0]]), (i = a[1]));
33+
b[i] = function () {
34+
b.push([i].concat(Array.prototype.slice.call(arguments, 0)));
35+
};
36+
}
37+
var e = a;
38+
'undefined' !== typeof g ? (e = a[g] = []) : (g = 'freshpaint');
39+
e.people = e.people || [];
40+
e.toString = function (b) {
41+
var a = 'freshpaint';
42+
'freshpaint' !== g && (a += '.' + g);
43+
b || (a += ' (stub)');
44+
return a;
45+
};
46+
e.people.toString = function () {
47+
return e.toString(1) + '.people (stub)';
48+
};
49+
l = 'disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove people group page alias ready addEventProperties addInitialEventProperties removeEventProperty addPageviewProperties'.split(
50+
' '
51+
);
52+
for (h = 0; h < l.length; h++) c(e, l[h]);
53+
var f = 'set set_once union unset remove delete'.split(' ');
54+
e.get_group = function () {
55+
function a(c) {
56+
b[c] = function () {
57+
call2_args = arguments;
58+
call2 = [c].concat(Array.prototype.slice.call(call2_args, 0));
59+
e.push([d, call2]);
60+
};
61+
}
62+
for (var b = {}, d = ['get_group'].concat(Array.prototype.slice.call(arguments, 0)), c = 0; c < f.length; c++)
63+
a(f[c]);
64+
return b;
65+
};
66+
a._i.push([b, d, g]);
67+
};
68+
a.__SV = 1.4;
69+
b = c.createElement('script');
70+
b.type = 'text/javascript';
71+
b.async = !0;
72+
b.src =
73+
'undefined' !== typeof FRESHPAINT_CUSTOM_LIB_URL
74+
? FRESHPAINT_CUSTOM_LIB_URL
75+
: '//perfalytics.com/static/js/freshpaint.js';
76+
(d = c.getElementsByTagName('script')[0]) ? d.parentNode.insertBefore(b, d) : c.head.appendChild(b);
77+
}
78+
})(document, window.freshpaint || []);
79+
80+
return freshpaint;
81+
};
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Injectable } from '@angular/core';
2+
import * as FullStory from '@fullstory/browser';
3+
import { Dictionary } from '../../../utilities/types/types';
4+
import { TelemetryProviderConfig, UserTelemetryProvider, UserTraits } from './../../telemetry';
5+
6+
@Injectable({ providedIn: 'root' })
7+
export class FullStoryTelemetry<InitConfig extends TelemetryProviderConfig>
8+
implements UserTelemetryProvider<InitConfig> {
9+
public initialize(config: InitConfig): void {
10+
FullStory.init({
11+
orgId: config.orgId,
12+
devMode: false
13+
});
14+
}
15+
16+
public identify(userTraits: UserTraits): void {
17+
FullStory.setUserVars({
18+
displayName: userTraits.name ?? `${userTraits.givenName as string} ${userTraits.familyName as string}`,
19+
email: userTraits.email,
20+
companyName: userTraits.companyName,
21+
licenseTier: userTraits.licenseTier,
22+
licenseExpiration: userTraits.licenseExpiration,
23+
isPlayground: userTraits.isPlayground,
24+
accountEmail: userTraits.accountEmail
25+
});
26+
}
27+
28+
public trackEvent(name: string, eventData: Dictionary<unknown>): void {
29+
FullStory.event(name, eventData);
30+
}
31+
32+
public trackPage(name: string, eventData: Dictionary<unknown>): void {
33+
FullStory.event(name, eventData);
34+
}
35+
36+
public trackError(name: string, eventData: Dictionary<unknown>): void {
37+
FullStory.event(name, eventData);
38+
}
39+
40+
public shutdown(): void {
41+
FullStory.shutdown();
42+
}
43+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Dictionary } from './../../../utilities/types/types';
2+
import { TelemetryProviderConfig, UserTelemetryProvider, UserTraits } from '../../telemetry';
3+
import { loadGA } from './load-snippet';
4+
5+
export class GoogleAnalyticsTelemetry<InitConfig extends TelemetryProviderConfig>
6+
implements UserTelemetryProvider<InitConfig> {
7+
public initialize(config: InitConfig): void {
8+
const ga = loadGA();
9+
ga('create', config.orgId, 'auto');
10+
ga('send', 'pageview');
11+
}
12+
13+
public identify(userTraits: UserTraits): void {
14+
ga('set', 'userId', userTraits.email);
15+
}
16+
17+
public trackEvent(name: string, eventData: Dictionary<unknown>): void {
18+
ga('send', {
19+
hitType: 'event',
20+
eventCategory: 'user-actions',
21+
eventAction: name,
22+
...eventData
23+
});
24+
}
25+
26+
public trackPage(name: string, eventData: Dictionary<unknown>): void {
27+
ga('send', {
28+
hitType: 'pageview',
29+
page: name,
30+
...eventData
31+
});
32+
}
33+
34+
public trackError(name: string, eventData: Dictionary<unknown>): void {
35+
ga('send', {
36+
hitType: 'event',
37+
eventCategory: 'error',
38+
eventAction: name,
39+
...eventData
40+
});
41+
}
42+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import 'google.analytics';
2+
3+
export function loadGA(): UniversalAnalytics.ga;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// tslint:disable
2+
3+
export const loadGA = () => {
4+
/**
5+
* Creates a temporary global ga object and loads analytics.js.
6+
* Parameters o, a, and m are all used internally. They could have been
7+
* declared using 'var', instead they are declared as parameters to save
8+
* 4 bytes ('var ').
9+
*
10+
* @param {Window} i The global context object.
11+
* @param {HTMLDocument} s The DOM document object.
12+
* @param {string} o Must be 'script'.
13+
* @param {string} g Protocol relative URL of the analytics.js script.
14+
* @param {string} r Global name of analytics object. Defaults to 'ga'.
15+
* @param {HTMLElement} a Async script tag.
16+
* @param {HTMLElement} m First script tag in document.
17+
*/
18+
19+
if (window.ga) {
20+
return window.ga;
21+
}
22+
23+
/**
24+
* Do not modify. Below snippet is from Google
25+
*/
26+
27+
(function (i, s, o, g, r, a, m) {
28+
i['GoogleAnalyticsObject'] = r; // Acts as a pointer to support renaming.
29+
30+
// Creates an initial ga() function.
31+
// The queued commands will be executed once analytics.js loads.
32+
(i[r] =
33+
i[r] ||
34+
function () {
35+
(i[r].q = i[r].q || []).push(arguments);
36+
}),
37+
// Sets the time (as an integer) this tag was executed.
38+
// Used for timing hits.
39+
(i[r].l = 1 * new Date());
40+
41+
// Insert the script tag asynchronously.
42+
// Inserts above current tag to prevent blocking in addition to using the
43+
// async attribute.
44+
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
45+
a.async = 1;
46+
a.src = g;
47+
m.parentNode.insertBefore(a, m);
48+
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
49+
50+
return ga;
51+
};

0 commit comments

Comments
 (0)