Integrate heap analytics
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
41
packages/website/ts/redux/analyticsMiddleware.ts
Normal file
41
packages/website/ts/redux/analyticsMiddleware.ts
Normal file
@@ -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;
|
||||
};
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user