aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Klebanoff <steve.klebanoff@gmail.com>2018-11-16 02:43:42 +0800
committerSteve Klebanoff <steve.klebanoff@gmail.com>2018-11-16 02:43:42 +0800
commit61f227e123218ba76a7fdf7fc2ee89171c2bf16c (patch)
treed821f01c41dd58e03b093a40930748dac51c2148
parent20ed4fbbd46f359ca1436b2d3b9d17527c01df54 (diff)
downloaddexon-sol-tools-61f227e123218ba76a7fdf7fc2ee89171c2bf16c.tar
dexon-sol-tools-61f227e123218ba76a7fdf7fc2ee89171c2bf16c.tar.gz
dexon-sol-tools-61f227e123218ba76a7fdf7fc2ee89171c2bf16c.tar.bz2
dexon-sol-tools-61f227e123218ba76a7fdf7fc2ee89171c2bf16c.tar.lz
dexon-sol-tools-61f227e123218ba76a7fdf7fc2ee89171c2bf16c.tar.xz
dexon-sol-tools-61f227e123218ba76a7fdf7fc2ee89171c2bf16c.tar.zst
dexon-sol-tools-61f227e123218ba76a7fdf7fc2ee89171c2bf16c.zip
feat(instant): Heap middleware and first tracking events
-rw-r--r--packages/instant/src/components/zero_ex_instant_container.tsx5
-rw-r--r--packages/instant/src/redux/analytics_middleware.ts38
-rw-r--r--packages/instant/src/redux/store.ts7
-rw-r--r--packages/instant/src/util/analytics.ts35
-rw-r--r--packages/instant/src/util/heap.ts13
5 files changed, 88 insertions, 10 deletions
diff --git a/packages/instant/src/components/zero_ex_instant_container.tsx b/packages/instant/src/components/zero_ex_instant_container.tsx
index 698bfef17..d977b0690 100644
--- a/packages/instant/src/components/zero_ex_instant_container.tsx
+++ b/packages/instant/src/components/zero_ex_instant_container.tsx
@@ -10,6 +10,7 @@ import { SelectedAssetInstantHeading } from '../containers/selected_asset_instan
import { ColorOption } from '../style/theme';
import { zIndex } from '../style/z_index';
import { OrderProcessState, SlideAnimationState } from '../types';
+import { analytics } from '../util/analytics';
import { CSSReset } from './css_reset';
import { SlidingPanel } from './sliding_panel';
@@ -68,6 +69,10 @@ export class ZeroExInstantContainer extends React.Component<{}, ZeroExInstantCon
</React.Fragment>
);
}
+ // tslint:disable-next-line:prefer-function-over-method
+ public componentDidMount(): void {
+ analytics.track('Widget - Opened');
+ }
private readonly _handleSymbolClick = (): void => {
this.setState({
tokenSelectionPanelAnimationState: 'slidIn',
diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts
new file mode 100644
index 000000000..8dd674e94
--- /dev/null
+++ b/packages/instant/src/redux/analytics_middleware.ts
@@ -0,0 +1,38 @@
+import { ObjectMap } from '@0x/types';
+import * as _ from 'lodash';
+import { Middleware } from 'redux';
+
+import { analytics } from '../util/analytics';
+
+import { AccountState } from './../types';
+import { Action, ActionTypes } from './actions';
+import { State } from './reducer';
+
+export const analyticsMiddleware: Middleware = store => next => middlewareAction => {
+ const prevState = store.getState() as State;
+ const nextAction = next(middlewareAction) as Action;
+ const nextState = store.getState() as State;
+
+ const curAccount = nextState.providerState.account;
+ const prevAccount = prevState.providerState.account;
+ switch (nextAction.type) {
+ case ActionTypes.SET_ACCOUNT_STATE_READY:
+ if (curAccount.state === AccountState.Ready && !_.isEqual(curAccount, prevAccount)) {
+ const ethAddress = curAccount.address;
+ analytics.addUserProperties({ ethAddress });
+ analytics.track('Wallet - Ready');
+ }
+ break;
+ case ActionTypes.UPDATE_ACCOUNT_ETH_BALANCE:
+ if (
+ curAccount.state === AccountState.Ready &&
+ curAccount.ethBalanceInWei &&
+ !_.isEqual(curAccount, prevAccount)
+ ) {
+ const ethBalanceInWei = curAccount.ethBalanceInWei.toString();
+ analytics.addUserProperties({ ethBalanceInWei });
+ }
+ }
+
+ return nextAction;
+};
diff --git a/packages/instant/src/redux/store.ts b/packages/instant/src/redux/store.ts
index 20710765d..54dfe58c4 100644
--- a/packages/instant/src/redux/store.ts
+++ b/packages/instant/src/redux/store.ts
@@ -1,7 +1,8 @@
import * as _ from 'lodash';
-import { createStore, Store as ReduxStore } from 'redux';
-import { devToolsEnhancer } from 'redux-devtools-extension/developmentOnly';
+import { applyMiddleware, createStore, Store as ReduxStore } from 'redux';
+import { composeWithDevTools, devToolsEnhancer } from 'redux-devtools-extension/developmentOnly';
+import { analyticsMiddleware } from './analytics_middleware';
import { createReducer, State } from './reducer';
export type Store = ReduxStore<State>;
@@ -9,6 +10,6 @@ export type Store = ReduxStore<State>;
export const store = {
create: (initialState: State): Store => {
const reducer = createReducer(initialState);
- return createStore(reducer, initialState, devToolsEnhancer({}));
+ return createStore(reducer, initialState, composeWithDevTools(applyMiddleware(analyticsMiddleware)));
},
};
diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts
new file mode 100644
index 000000000..4de3e5eff
--- /dev/null
+++ b/packages/instant/src/util/analytics.ts
@@ -0,0 +1,35 @@
+import { ObjectMap } from '@0x/types';
+import { logUtils } from '@0x/utils';
+
+import { HeapAnalytics, heapUtil } from './heap';
+
+export class Analytics {
+ public static init(): Analytics {
+ return new Analytics();
+ }
+ public track(eventName: string, eventProperties?: ObjectMap<string | number>): void {
+ console.log('HEAP: tracking', eventName, eventProperties);
+ this._evaluteHeapCall(heap => heap.track(eventName, eventProperties));
+ }
+ public addUserProperties(properties: ObjectMap<string | number>): void {
+ console.log('HEAP: adding user properties', properties);
+ this._evaluteHeapCall(heap => heap.addUserProperties(properties));
+ }
+ public addEventProperties(properties: ObjectMap<string | number>): void {
+ this._evaluteHeapCall(heap => heap.addEventProperties(properties));
+ }
+ private _evaluteHeapCall(heapFunctionCall: (heap: HeapAnalytics) => void): void {
+ const curHeap = heapUtil.getHeap();
+ if (curHeap) {
+ try {
+ heapFunctionCall(curHeap);
+ } catch (e) {
+ // We never want analytics to crash our React component
+ // TODO: error reporter here
+ logUtils.log('Analytics error', e);
+ }
+ }
+ }
+}
+
+export const analytics = Analytics.init();
diff --git a/packages/instant/src/util/heap.ts b/packages/instant/src/util/heap.ts
index 399ac3f6f..2f2c221b1 100644
--- a/packages/instant/src/util/heap.ts
+++ b/packages/instant/src/util/heap.ts
@@ -20,8 +20,13 @@ interface ModifiedWindow {
const getWindow = (): ModifiedWindow => {
return window as ModifiedWindow;
};
-// Typescript-compatible version of https://docs.heapanalytics.com/docs/installation
+
const setupZeroExInstantHeap = () => {
+ const curWindow = getWindow();
+ // Set property to specify that this is zeroEx's heap
+ curWindow.zeroExInstantLoadedHeap = true;
+
+ // Typescript-compatible version of https://docs.heapanalytics.com/docs/installation
/* tslint:disable */
((window as any).heap = (window as any).heap || []),
((window as any).heap.load = function(e: any, t: any) {
@@ -60,9 +65,6 @@ const setupZeroExInstantHeap = () => {
(window as any).heap.load(HEAP_ANALYTICS_DEVELOPMENT_APP_ID);
/* tslint:enable */
- const curWindow = getWindow();
- // Set property to specify that this is zeroEx's heap
- curWindow.zeroExInstantLoadedHeap = true;
return curWindow.heap as HeapAnalytics;
};
@@ -71,17 +73,14 @@ export const heapUtil = {
const curWindow = getWindow();
const hasOtherExistingHeapIntegration = curWindow.heap && !curWindow.zeroExInstantLoadedHeap;
if (hasOtherExistingHeapIntegration) {
- logUtils.log('Heap integration already exists');
return null;
}
const zeroExInstantHeapIntegration = curWindow.zeroExInstantLoadedHeap && curWindow.heap;
if (zeroExInstantHeapIntegration) {
- logUtils.log('Using existing 0x instant heap');
return zeroExInstantHeapIntegration;
}
- logUtils.log('Setting up heap');
return setupZeroExInstantHeap();
},
};