aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/website/public/index.html12
-rw-r--r--packages/website/ts/blockchain.ts2
-rw-r--r--packages/website/ts/components/fill_order.tsx6
-rw-r--r--packages/website/ts/components/forms/subscribe_form.tsx4
-rw-r--r--packages/website/ts/components/generate_order/generate_order_form.tsx8
-rw-r--r--packages/website/ts/components/inputs/allowance_toggle.tsx6
-rw-r--r--packages/website/ts/components/onboarding/portal_onboarding_flow.tsx9
-rw-r--r--packages/website/ts/components/portal/portal.tsx5
-rw-r--r--packages/website/ts/components/relayer_index/relayer_grid_tile.tsx4
-rw-r--r--packages/website/ts/components/relayer_index/relayer_top_tokens.tsx3
-rw-r--r--packages/website/ts/components/wallet/wallet.tsx8
-rw-r--r--packages/website/ts/components/wallet/wrap_ether_item.tsx10
-rw-r--r--packages/website/ts/index.tsx1
-rw-r--r--packages/website/ts/pages/wiki/wiki.tsx2
-rw-r--r--packages/website/ts/redux/analyticsMiddleware.ts41
-rw-r--r--packages/website/ts/redux/store.ts7
-rw-r--r--packages/website/ts/utils/analytics.ts56
-rw-r--r--packages/website/ts/utils/utils.ts12
18 files changed, 122 insertions, 74 deletions
diff --git a/packages/website/public/index.html b/packages/website/public/index.html
index 2d9b722f8..a8a61f8ad 100644
--- a/packages/website/public/index.html
+++ b/packages/website/public/index.html
@@ -23,6 +23,12 @@
</head>
<body style="margin: 0px; min-width: 355px;">
+ <!-- Heap SDK -->
+ <script type="text/javascript">
+ window.heap = window.heap || [], heap.load = function (e, t) { window.heap.appid = e, window.heap.config = t = t || {}; var r = t.forceSSL || "https:" === document.location.protocol, a = document.createElement("script"); a.type = "text/javascript", a.async = !0, a.src = (r ? "https:" : "http:") + "//cdn.heapanalytics.com/js/heap-" + e + ".js"; var n = document.getElementsByTagName("script")[0]; n.parentNode.insertBefore(a, n); for (var o = function (e) { return function () { heap.push([e].concat(Array.prototype.slice.call(arguments, 0))) } }, p = ["addEventProperties", "addUserProperties", "clearEventProperties", "identify", "resetIdentity", "removeEventProperty", "setEventProperties", "track", "unsetEventProperty"], c = 0; c < p.length; c++)heap[p[c]] = o(p[c]) };
+ heap.load("410099666");
+ </script>
+ <!-- End Heap SDK -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-98720122-1"></script>
<script>
@@ -82,12 +88,6 @@
})(window, document, 'https://static.hotjar.com/c/hotjar-', '.js?sv=');
</script>
<!-- End Hotjar Tracking Code -->
- <!-- Heap SDK -->
- <script type="text/javascript">
- window.heap = window.heap || [], heap.load = function (e, t) { window.heap.appid = e, window.heap.config = t = t || {}; var r = t.forceSSL || "https:" === document.location.protocol, a = document.createElement("script"); a.type = "text/javascript", a.async = !0, a.src = (r ? "https:" : "http:") + "//cdn.heapanalytics.com/js/heap-" + e + ".js"; var n = document.getElementsByTagName("script")[0]; n.parentNode.insertBefore(a, n); for (var o = function (e) { return function () { heap.push([e].concat(Array.prototype.slice.call(arguments, 0))) } }, p = ["addEventProperties", "addUserProperties", "clearEventProperties", "identify", "resetIdentity", "removeEventProperty", "setEventProperties", "track", "unsetEventProperty"], c = 0; c < p.length; c++)heap[p[c]] = o(p[c]) };
- heap.load("410099666");
- </script>
- <!-- End Heap SDK -->
<!-- Main -->
<script type="text/javascript" crossorigin="anonymous" src="/bundle.js" charset="utf-8"></script>
</body>
diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts
index 0e6698318..954595cef 100644
--- a/packages/website/ts/blockchain.ts
+++ b/packages/website/ts/blockchain.ts
@@ -795,7 +795,7 @@ export class Blockchain {
return tokenByAddress;
}
private async _onPageLoadInitFireAndForgetAsync(): Promise<void> {
- await utils.onPageLoadAsync(); // wait for page to load
+ await utils.onPageLoadPromise; // wait for page to load
const networkIdIfExists = await Blockchain._getInjectedWeb3ProviderNetworkIdIfExistsAsync();
this.networkId = !_.isUndefined(networkIdIfExists) ? networkIdIfExists : constants.NETWORK_ID_MAINNET;
const injectedWeb3IfExists = Blockchain._getInjectedWeb3();
diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx
index 46e33061f..25d21c3dd 100644
--- a/packages/website/ts/components/fill_order.tsx
+++ b/packages/website/ts/components/fill_order.tsx
@@ -1,5 +1,5 @@
import { getOrderHashHex, isValidSignature } from '@0xproject/order-utils';
-import { colors, constants as sharedConstants } from '@0xproject/react-shared';
+import { colors } from '@0xproject/react-shared';
import { Order as ZeroExOrder } from '@0xproject/types';
import { BigNumber, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
@@ -508,7 +508,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
}
private _trackOrderEvent(eventName: string): void {
const parsedOrder = this.state.parsedOrder;
- analytics.trackOrderEvent(eventName, parsedOrder);
+ analytics.trackOrderEventAsync(eventName, parsedOrder);
}
private async _onFillOrderClickFireAndForgetAsync(): Promise<void> {
if (this.props.blockchainErr !== BlockchainErrs.NoError || _.isEmpty(this.props.userAddress)) {
@@ -630,8 +630,6 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
});
return;
}
- const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId];
- const eventLabel = `${parsedOrder.metadata.makerToken.symbol}-${networkName}`;
try {
await this.props.blockchain.cancelOrderAsync(signedOrder, availableTakerTokenAmount);
this.setState({
diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx
index 8ef58328e..19abbdf5f 100644
--- a/packages/website/ts/components/forms/subscribe_form.tsx
+++ b/packages/website/ts/components/forms/subscribe_form.tsx
@@ -6,6 +6,7 @@ import { Button } from 'ts/components/ui/button';
import { Container } from 'ts/components/ui/container';
import { Input } from 'ts/components/ui/input';
import { Text } from 'ts/components/ui/text';
+import { analytics } from 'ts/utils/analytics';
import { backendClient } from 'ts/utils/backend_client';
export interface SubscribeFormProps {}
@@ -112,6 +113,9 @@ export class SubscribeForm extends React.Component<SubscribeFormProps, Subscribe
try {
const response = await backendClient.subscribeToNewsletterAsync(this.state.emailText);
const status = response.status === 200 ? SubscribeFormStatus.Success : SubscribeFormStatus.Error;
+ if (status === SubscribeFormStatus.Success) {
+ analytics.indentifyAsync(this.state.emailText, 'email');
+ }
this.setState({ status, emailText: '' });
} catch (error) {
this._setStatus(SubscribeFormStatus.Error);
diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx
index 53fb3fc91..691abd4aa 100644
--- a/packages/website/ts/components/generate_order/generate_order_form.tsx
+++ b/packages/website/ts/components/generate_order/generate_order_form.tsx
@@ -1,5 +1,5 @@
import { generatePseudoRandomSalt, getOrderHashHex } from '@0xproject/order-utils';
-import { colors, constants as sharedConstants } from '@0xproject/react-shared';
+import { colors } from '@0xproject/react-shared';
import { ECSignature, Order as ZeroExOrder } from '@0xproject/types';
import { BigNumber, logUtils } from '@0xproject/utils';
import * as _ from 'lodash';
@@ -20,7 +20,7 @@ import { SwapIcon } from 'ts/components/ui/swap_icon';
import { Dispatcher } from 'ts/redux/dispatcher';
import { portalOrderSchema } from 'ts/schemas/portal_order_schema';
import { validator } from 'ts/schemas/validator';
-import { AlertTypes, BlockchainErrs, HashData, Side, SideToAssetToken, Token, TokenByAddress, Order } from 'ts/types';
+import { AlertTypes, BlockchainErrs, HashData, Order, Side, SideToAssetToken, Token, TokenByAddress } from 'ts/types';
import { analytics } from 'ts/utils/analytics';
import { constants } from 'ts/utils/constants';
import { errorReporter } from 'ts/utils/error_reporter';
@@ -268,7 +268,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
const signedOrder = await this._signTransactionAsync();
const doesSignedOrderExist = !_.isUndefined(signedOrder);
if (doesSignedOrderExist) {
- analytics.trackOrderEvent('Sign Order Success', signedOrder);
+ analytics.trackOrderEventAsync('Sign Order Success', signedOrder);
this.setState({
globalErrMsg: '',
shouldShowIncompleteErrs: false,
@@ -281,7 +281,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
globalErrMsg = 'You must enable wallet communication';
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
}
- analytics.track('Sign Order Failure', {
+ analytics.trackAsync('Sign Order Failure', {
makerTokenAmount: debitToken.amount.toString(),
makerToken: this.props.tokenByAddress[debitToken.address].symbol,
takerTokenAmount: receiveToken.amount.toString(),
diff --git a/packages/website/ts/components/inputs/allowance_toggle.tsx b/packages/website/ts/components/inputs/allowance_toggle.tsx
index b3f1aead2..8e9d4fe8d 100644
--- a/packages/website/ts/components/inputs/allowance_toggle.tsx
+++ b/packages/website/ts/components/inputs/allowance_toggle.tsx
@@ -1,4 +1,4 @@
-import { constants as sharedConstants, Styles } from '@0xproject/react-shared';
+import { Styles } from '@0xproject/react-shared';
import { BigNumber, logUtils } from '@0xproject/utils';
import * as _ from 'lodash';
import Toggle from 'material-ui/Toggle';
@@ -117,10 +117,10 @@ export class AllowanceToggle extends React.Component<AllowanceToggleProps, Allow
};
try {
await this.props.blockchain.setProxyAllowanceAsync(this.props.token, newAllowanceAmountInBaseUnits);
- analytics.track('Set Allowances Success', logData);
+ analytics.trackAsync('Set Allowances Success', logData);
await this.props.refetchTokenStateAsync();
} catch (err) {
- analytics.track('Set Allowance Failure', logData);
+ analytics.trackAsync('Set Allowance Failure', logData);
this.setState({
isSpinnerVisible: false,
});
diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
index 63b98cee7..516fdac3c 100644
--- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
+++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
@@ -1,4 +1,3 @@
-import { constants as sharedConstants } from '@0xproject/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import { RouteComponentProps, withRouter } from 'react-router';
@@ -225,7 +224,7 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
(this.props.stepIndex === 0 && !this.props.isRunning && this.props.blockchainIsLoaded) ||
(!this.props.isRunning && !this.props.hasBeenClosed && this.props.blockchainIsLoaded)
) {
- analytics.track('Onboarding Started', {
+ analytics.trackAsync('Onboarding Started', {
reason: 'automatic',
stepIndex: this.props.stepIndex,
});
@@ -234,14 +233,10 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
}
private _updateOnboardingStep(stepIndex: number): void {
this.props.updateOnboardingStep(stepIndex);
- analytics.track('Update Onboarding Step', {
- stepIndex,
- });
}
private _closeOnboarding(): void {
- const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId];
this.props.updateIsRunning(false);
- analytics.track('OnboardingClosed', {
+ analytics.trackAsync('OnboardingClosed', {
stepIndex: this.props.stepIndex,
});
}
diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx
index 2e02f42f6..f5ac3b6f3 100644
--- a/packages/website/ts/components/portal/portal.tsx
+++ b/packages/website/ts/components/portal/portal.tsx
@@ -1,4 +1,4 @@
-import { colors, constants as sharedConstants } from '@0xproject/react-shared';
+import { colors } from '@0xproject/react-shared';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import * as React from 'react';
@@ -388,9 +388,8 @@ export class Portal extends React.Component<PortalProps, PortalState> {
startOnboarding
);
}
-
private _startOnboarding(): void {
- analytics.track('Onboarding Started', {
+ analytics.trackAsync('Onboarding Started', {
reason: 'manual',
stepIndex: this.props.portalOnboardingStep,
});
diff --git a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
index 2eb04f2d6..937f0b79d 100644
--- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
+++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
@@ -1,4 +1,4 @@
-import { constants as sharedConstants, Styles } from '@0xproject/react-shared';
+import { Styles } from '@0xproject/react-shared';
import * as _ from 'lodash';
import { GridTile as PlainGridTile } from 'material-ui/GridList';
import * as React from 'react';
@@ -65,7 +65,7 @@ export const RelayerGridTile: React.StatelessComponent<RelayerGridTileProps> = (
const topTokens = props.relayerInfo.topTokens;
const weeklyTxnVolume = props.relayerInfo.weeklyTxnVolume;
const onClick = () => {
- analytics.track('Relayer Click', {
+ analytics.trackAsync('Relayer Click', {
name: props.relayerInfo.name,
});
utils.openUrl(link);
diff --git a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx
index 883c8d81b..e6e0095c2 100644
--- a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx
+++ b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx
@@ -1,6 +1,5 @@
import {
colors,
- constants as sharedConstants,
EtherscanLinkSuffixes,
utils as sharedUtils,
} from '@0xproject/react-shared';
@@ -48,7 +47,7 @@ class TokenLink extends React.Component<TokenLinkProps, TokenLinkState> {
public render(): React.ReactNode {
const onClick = (event: React.MouseEvent<HTMLElement>) => {
event.stopPropagation();
- analytics.track('Token Click', {
+ analytics.trackAsync('Token Click', {
tokenSymbol: this.props.tokenInfo.symbol,
});
const tokenLink = this._tokenLinkFromToken(this.props.tokenInfo, this.props.networkId);
diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx
index 940cd6c58..2fdcded38 100644
--- a/packages/website/ts/components/wallet/wallet.tsx
+++ b/packages/website/ts/components/wallet/wallet.tsx
@@ -1,4 +1,4 @@
-import { constants as sharedConstants, EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared';
+import { EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared';
import { BigNumber, errorUtils } from '@0xproject/utils';
import * as _ from 'lodash';
@@ -488,19 +488,17 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
);
}
private _openWrappedEtherActionRow(wrappedEtherDirection: Side): void {
- const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId];
const action =
wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Opened' : 'Wallet - Unwrap WETH Opened';
- analytics.track(action);
+ analytics.trackAsync(action);
this.setState({
wrappedEtherDirection,
});
}
private _closeWrappedEtherActionRow(wrappedEtherDirection: Side): void {
- const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId];
const action =
wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Closed' : 'Wallet - Unwrap WETH Closed';
- analytics.track(action);
+ analytics.trackAsync(action);
this.setState({
wrappedEtherDirection: undefined,
});
diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx
index 01d9bdb66..9fec8afa1 100644
--- a/packages/website/ts/components/wallet/wrap_ether_item.tsx
+++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx
@@ -1,4 +1,4 @@
-import { constants as sharedConstants, Styles } from '@0xproject/react-shared';
+import { Styles } from '@0xproject/react-shared';
import { BigNumber, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
@@ -196,13 +196,13 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther
if (this.props.direction === Side.Deposit) {
await this.props.blockchain.convertEthToWrappedEthTokensAsync(etherToken.address, amountToConvert);
this.props.dispatcher.showFlashMessage(`Successfully wrapped ${ethAmount} ETH to WETH`);
- analytics.track('Wrap ETH Success', {
+ analytics.trackAsync('Wrap ETH Success', {
amount: ethAmount,
});
} else {
await this.props.blockchain.convertWrappedEthTokensToEthAsync(etherToken.address, amountToConvert);
this.props.dispatcher.showFlashMessage(`Successfully unwrapped ${tokenAmount} WETH to ETH`);
- analytics.track('Unwrap WETH Success', {
+ analytics.trackAsync('Unwrap WETH Success', {
amount: tokenAmount,
});
}
@@ -217,12 +217,12 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther
logUtils.log(err.stack);
if (this.props.direction === Side.Deposit) {
this.props.dispatcher.showFlashMessage('Failed to wrap your ETH. Please try again.');
- analytics.track('Wrap ETH Failure', {
+ analytics.trackAsync('Wrap ETH Failure', {
amount: ethAmount,
});
} else {
this.props.dispatcher.showFlashMessage('Failed to unwrap your WETH. Please try again.');
- analytics.track('Unwrap WETH Failed', {
+ analytics.trackAsync('Unwrap WETH Failed', {
amount: tokenAmount,
});
}
diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx
index aba72f52a..4838df6b4 100644
--- a/packages/website/ts/index.tsx
+++ b/packages/website/ts/index.tsx
@@ -16,7 +16,6 @@ import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
import { tradeHistoryStorage } from 'ts/local_storage/trade_history_storage';
import { store } from 'ts/redux/store';
import { WebsiteLegacyPaths, WebsitePaths } from 'ts/types';
-import { analytics } from 'ts/utils/analytics';
import { muiTheme } from 'ts/utils/mui_theme';
import { utils } from 'ts/utils/utils';
// Polyfills
diff --git a/packages/website/ts/pages/wiki/wiki.tsx b/packages/website/ts/pages/wiki/wiki.tsx
index 9659900be..55f532b11 100644
--- a/packages/website/ts/pages/wiki/wiki.tsx
+++ b/packages/website/ts/pages/wiki/wiki.tsx
@@ -205,7 +205,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
articlesBySection,
},
async () => {
- await utils.onPageLoadAsync();
+ await utils.onPageLoadPromise;
const hash = this.props.location.hash.slice(1);
sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID);
},
diff --git a/packages/website/ts/redux/analyticsMiddleware.ts b/packages/website/ts/redux/analyticsMiddleware.ts
new file mode 100644
index 000000000..2778445e7
--- /dev/null
+++ b/packages/website/ts/redux/analyticsMiddleware.ts
@@ -0,0 +1,41 @@
+import { Middleware } from 'redux';
+import { State } from 'ts/redux/reducer';
+import { ActionTypes } from 'ts/types';
+import { analytics } from 'ts/utils/analytics';
+
+export const analyticsMiddleware: Middleware = store => next => action => {
+ const nextAction = next(action);
+ const nextState = (store.getState() as any) as State;
+ switch (action.type) {
+ case ActionTypes.UpdateInjectedProviderName:
+ analytics.addEventPropertiesAsync({
+ injectedProviderName: nextState.injectedProviderName,
+ });
+ break;
+ case ActionTypes.UpdateNetworkId:
+ analytics.addEventPropertiesAsync({
+ networkId: nextState.networkId,
+ });
+ break;
+ case ActionTypes.UpdateUserAddress:
+ analytics.addUserPropertiesAsync({
+ ethAddress: nextState.userAddress,
+ });
+ break;
+ case ActionTypes.UpdateUserEtherBalance:
+ if (nextState.userEtherBalanceInWei) {
+ analytics.addUserPropertiesAsync({
+ ethBalance: nextState.userEtherBalanceInWei.toString(),
+ });
+ }
+ break;
+ case ActionTypes.UpdatePortalOnboardingStep:
+ analytics.trackAsync('Update Onboarding Step', {
+ stepIndex: nextState.portalOnboardingStep,
+ });
+ break;
+ default:
+ break;
+ }
+ return nextAction;
+};
diff --git a/packages/website/ts/redux/store.ts b/packages/website/ts/redux/store.ts
index 2672e3f61..006241371 100644
--- a/packages/website/ts/redux/store.ts
+++ b/packages/website/ts/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 } from 'redux-devtools-extension/developmentOnly';
import { stateStorage } from 'ts/local_storage/state_storage';
+import { analyticsMiddleware } from 'ts/redux/analyticsMiddleware';
import { reducer, State } from 'ts/redux/reducer';
const ONE_SECOND = 1000;
@@ -9,7 +10,7 @@ const ONE_SECOND = 1000;
export const store: ReduxStore<State> = createStore(
reducer,
stateStorage.getPersistedDefaultState(),
- devToolsEnhancer({ name: '0x Website Redux Store' }),
+ composeWithDevTools(applyMiddleware(analyticsMiddleware)),
);
store.subscribe(
_.throttle(() => {
diff --git a/packages/website/ts/utils/analytics.ts b/packages/website/ts/utils/analytics.ts
index 9a1684813..961f9af5a 100644
--- a/packages/website/ts/utils/analytics.ts
+++ b/packages/website/ts/utils/analytics.ts
@@ -1,9 +1,9 @@
import * as _ from 'lodash';
-import { InjectedWeb3, ObjectMap, Order } from 'ts/types';
-import { configs } from 'ts/utils/configs';
+import { ObjectMap, Order } from 'ts/types';
import { utils } from 'ts/utils/utils';
export interface HeapAnalytics {
+ loaded: boolean;
indentify(id: string, idType: string): void;
track(eventName: string, eventProperties?: ObjectMap<string | number>): void;
resetIdentity(): void;
@@ -13,12 +13,15 @@ export interface HeapAnalytics {
clearEventProperties(): void;
}
-export class Analytics implements HeapAnalytics {
+export class Analytics {
private _heap: HeapAnalytics;
public static init(): Analytics {
+ return new Analytics(Analytics.getHeap());
+ }
+ public static getHeap(): HeapAnalytics {
const heap = (window as any).heap;
if (!_.isUndefined(heap)) {
- return new Analytics(heap);
+ return heap;
} else {
throw new Error('Could not find the Heap SDK on the page.');
}
@@ -27,45 +30,58 @@ export class Analytics implements HeapAnalytics {
this._heap = heap;
}
// HeapAnalytics Wrappers
- public indentify(id: string, idType: string): void {
+ public async indentifyAsync(id: string, idType: string): Promise<void> {
+ await this._heapLoadedGuardAsync();
this._heap.indentify(id, idType);
}
- public track(eventName: string, eventProperties?: ObjectMap<string | number>): void {
+ public async trackAsync(eventName: string, eventProperties?: ObjectMap<string | number>): Promise<void> {
+ await this._heapLoadedGuardAsync();
this._heap.track(eventName, eventProperties);
}
- public resetIdentity(): void {
+ public async resetIdentityAsync(): Promise<void> {
+ await this._heapLoadedGuardAsync();
this._heap.resetIdentity();
}
- public addUserProperties(properties: ObjectMap<string | number>): void {
+ public async addUserPropertiesAsync(properties: ObjectMap<string | number>): Promise<void> {
+ await this._heapLoadedGuardAsync();
this._heap.addUserProperties(properties);
}
- public addEventProperties(properties: ObjectMap<string | number>): void {
+ public async addEventPropertiesAsync(properties: ObjectMap<string | number>): Promise<void> {
+ await this._heapLoadedGuardAsync();
this._heap.addEventProperties(properties);
}
- public removeEventProperty(property: string): void {
+ public async removeEventPropertyAsync(property: string): Promise<void> {
+ await this._heapLoadedGuardAsync();
this._heap.removeEventProperty(property);
}
- public clearEventProperties(): void {
+ public async clearEventPropertiesAsync(): Promise<void> {
+ await this._heapLoadedGuardAsync();
this._heap.clearEventProperties();
}
// Custom methods
- public trackOrderEvent(eventName: string, order: Order): void {
+ public async trackOrderEventAsync(eventName: string, order: Order): Promise<void> {
const orderLoggingData = {
takerTokenAmount: order.signedOrder.takerTokenAmount,
makeTokenAmount: order.signedOrder.makerTokenAmount,
takerToken: order.metadata.takerToken.symbol,
makerToken: order.metadata.makerToken.symbol,
};
- this.track(eventName, orderLoggingData);
+ this.trackAsync(eventName, orderLoggingData);
}
- public async logProviderAsync(web3IfExists: InjectedWeb3): Promise<void> {
- await utils.onPageLoadAsync();
- const providerType =
- !_.isUndefined(web3IfExists) && !_.isUndefined(web3IfExists.currentProvider)
- ? utils.getProviderType(web3IfExists.currentProvider)
- : 'NONE';
+ /**
+ * Heap is not available as a UMD module, and additionally has the strange property of replacing itself with
+ * a different object once it's loaded.
+ * Instead of having an await call before every analytics use, we opt to have the awaiting logic in here by
+ * guarding every API call with the guard below.
+ */
+ private async _heapLoadedGuardAsync(): Promise<void> {
+ if (this._heap.loaded) {
+ return undefined;
+ }
+ await utils.onPageLoadPromise;
+ // HACK: Reset heap to loaded heap
+ this._heap = (window as any).heap;
}
}
-// Assume heap library has loaded.
export const analytics = Analytics.init();
diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts
index df7f8d10f..bd6a57eea 100644
--- a/packages/website/ts/utils/utils.ts
+++ b/packages/website/ts/utils/utils.ts
@@ -313,15 +313,13 @@ export const utils = {
const baseUrl = `https://${window.location.hostname}${hasPort ? `:${port}` : ''}`;
return baseUrl;
},
- // TODO: Fix this, it's a lie.
- async onPageLoadAsync(): Promise<void> {
+ onPageLoadPromise: new Promise((resolve, _reject) => {
if (document.readyState === 'complete') {
- return; // Already loaded
+ resolve();
+ return;
}
- return new Promise<void>((resolve, _reject) => {
- window.onload = () => resolve();
- });
- },
+ window.onload = () => resolve();
+ }),
getProviderType(provider: Provider): Providers | string {
const constructorName = provider.constructor.name;
let parsedProviderName = constructorName;