diff options
Diffstat (limited to 'packages/website')
-rw-r--r-- | packages/website/package.json | 10 | ||||
-rw-r--r-- | packages/website/ts/components/fill_order.tsx | 14 | ||||
-rw-r--r-- | packages/website/ts/components/generate_order/generate_order_form.tsx | 36 | ||||
-rw-r--r-- | packages/website/ts/components/inputs/allowance_toggle.tsx | 10 | ||||
-rw-r--r-- | packages/website/ts/components/onboarding/portal_onboarding_flow.tsx | 15 | ||||
-rw-r--r-- | packages/website/ts/components/portal/portal.tsx | 6 | ||||
-rw-r--r-- | packages/website/ts/components/relayer_index/relayer_grid_tile.tsx | 6 | ||||
-rw-r--r-- | packages/website/ts/components/relayer_index/relayer_top_tokens.tsx | 6 | ||||
-rw-r--r-- | packages/website/ts/components/wallet/wallet.tsx | 4 | ||||
-rw-r--r-- | packages/website/ts/components/wallet/wrap_ether_item.tsx | 29 | ||||
-rw-r--r-- | packages/website/ts/index.tsx | 4 | ||||
-rw-r--r-- | packages/website/ts/types.ts | 6 | ||||
-rw-r--r-- | packages/website/ts/utils/analytics.ts | 80 | ||||
-rw-r--r-- | packages/website/ts/utils/configs.ts | 1 | ||||
-rw-r--r-- | packages/website/ts/utils/constants.ts | 1 | ||||
-rw-r--r-- | packages/website/ts/utils/utils.ts | 1 |
16 files changed, 147 insertions, 82 deletions
diff --git a/packages/website/package.json b/packages/website/package.json index b5b4b6119..3e48a3a26 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -11,12 +11,9 @@ "clean": "shx rm -f public/bundle*", "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'", "watch_without_deps": "webpack-dev-server --content-base public --https", - "deploy_dogfood": - "npm run build; aws s3 sync ./public/. s3://dogfood.0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", - "deploy_staging": - "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", - "deploy_live": - "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --exclude *.map.js" + "deploy_dogfood": "npm run build; aws s3 sync ./public/. s3://dogfood.0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", + "deploy_staging": "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", + "deploy_live": "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --exclude *.map.js" }, "author": "Fabio Berger", "license": "Apache-2.0", @@ -49,7 +46,6 @@ "react-copy-to-clipboard": "^4.2.3", "react-document-title": "^2.0.3", "react-dom": "15.6.1", - "react-ga": "^2.4.1", "react-popper": "^1.0.0-beta.6", "react-redux": "^5.0.3", "react-router-dom": "^4.1.1", diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index 03ba1183d..46e33061f 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -506,6 +506,10 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { await this._checkForUntrackedTokensAndAskToAddAsync(); } + private _trackOrderEvent(eventName: string): void { + const parsedOrder = this.state.parsedOrder; + analytics.trackOrderEvent(eventName, parsedOrder); + } private async _onFillOrderClickFireAndForgetAsync(): Promise<void> { if (this.props.blockchainErr !== BlockchainErrs.NoError || _.isEmpty(this.props.userAddress)) { this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); @@ -552,14 +556,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { }); return; } - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; - const eventLabel = `${parsedOrder.metadata.takerToken.symbol}-${networkName}`; try { const orderFilledAmount: BigNumber = await this.props.blockchain.fillOrderAsync( signedOrder, this.props.orderFillAmount, ); - analytics.logEvent('Portal', 'Fill Order Success', eventLabel, parsedOrder.signedOrder.takerTokenAmount); + this._trackOrderEvent('Fill Order Success'); // After fill completes, let's force fetch the token balances this.props.dispatcher.forceTokenStateRefetch(); this.setState({ @@ -573,7 +575,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { this.setState({ isFilling: false, }); - analytics.logEvent('Portal', 'Fill Order Failure', eventLabel, parsedOrder.signedOrder.takerTokenAmount); + this._trackOrderEvent('Fill Order Failure'); const errMsg = `${err}`; if (utils.didUserDenyWeb3Request(errMsg)) { return; @@ -638,7 +640,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { globalErrMsg: '', unavailableTakerAmount: takerTokenAmount, }); - analytics.logEvent('Portal', 'Cancel Order Success', eventLabel, parsedOrder.signedOrder.makerTokenAmount); + this._trackOrderEvent('Cancel Order Success'); return; } catch (err) { this.setState({ @@ -648,7 +650,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { if (utils.didUserDenyWeb3Request(errMsg)) { return; } - analytics.logEvent('Portal', 'Cancel Order Failure', eventLabel, parsedOrder.signedOrder.makerTokenAmount); + this._trackOrderEvent('Cancel Order Failure'); globalErrMsg = 'Failed to cancel order, please refresh and try again'; logUtils.log(`${err}`); this.setState({ 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 d26b5c3fa..53fb3fc91 100644 --- a/packages/website/ts/components/generate_order/generate_order_form.tsx +++ b/packages/website/ts/components/generate_order/generate_order_form.tsx @@ -1,6 +1,6 @@ import { generatePseudoRandomSalt, getOrderHashHex } from '@0xproject/order-utils'; import { colors, constants as sharedConstants } from '@0xproject/react-shared'; -import { ECSignature, Order } from '@0xproject/types'; +import { ECSignature, Order as ZeroExOrder } from '@0xproject/types'; import { BigNumber, logUtils } from '@0xproject/utils'; import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; @@ -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 } from 'ts/types'; +import { AlertTypes, BlockchainErrs, HashData, Side, SideToAssetToken, Token, TokenByAddress, Order } from 'ts/types'; import { analytics } from 'ts/utils/analytics'; import { constants } from 'ts/utils/constants'; import { errorReporter } from 'ts/utils/error_reporter'; @@ -254,7 +254,8 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G userAddressIfExists, debitToken.address, ); - const receiveAmount = this.props.sideToAssetToken[Side.Receive].amount; + const receiveToken = this.props.sideToAssetToken[Side.Receive]; + const receiveAmount = receiveToken.amount; if ( !_.isUndefined(debitToken.amount) && !_.isUndefined(receiveAmount) && @@ -264,24 +265,28 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G debitBalance.gte(debitToken.amount) && debitAllowance.gte(debitToken.amount) ) { - const didSignSuccessfully = await this._signTransactionAsync(); - if (didSignSuccessfully) { - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; - const eventLabel = `${this.props.tokenByAddress[debitToken.address].symbol}-${networkName}`; - analytics.logEvent('Portal', 'Sign Order Success', eventLabel, debitToken.amount.toNumber()); + const signedOrder = await this._signTransactionAsync(); + const doesSignedOrderExist = !_.isUndefined(signedOrder); + if (doesSignedOrderExist) { + analytics.trackOrderEvent('Sign Order Success', signedOrder); this.setState({ globalErrMsg: '', shouldShowIncompleteErrs: false, }); } - return didSignSuccessfully; + return doesSignedOrderExist; } else { let globalErrMsg = 'You must fix the above errors in order to generate a valid order'; if (this.props.userAddress === '') { globalErrMsg = 'You must enable wallet communication'; this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); } - analytics.logEvent('Portal', 'Sign Order Failure', globalErrMsg); + analytics.track('Sign Order Failure', { + makerTokenAmount: debitToken.amount.toString(), + makerToken: this.props.tokenByAddress[debitToken.address].symbol, + takerTokenAmount: receiveToken.amount.toString(), + takerToken: this.props.tokenByAddress[receiveToken.address].symbol, + }); this.setState({ globalErrMsg, shouldShowIncompleteErrs: true, @@ -289,7 +294,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G return false; } } - private async _signTransactionAsync(): Promise<boolean> { + private async _signTransactionAsync(): Promise<Order | undefined> { this.setState({ signingState: SigningState.SIGNING, }); @@ -299,11 +304,11 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G this.setState({ signingState: SigningState.UNSIGNED, }); - return false; + return undefined; } const hashData = this.props.hashData; - const zeroExOrder: Order = { + const zeroExOrder: ZeroExOrder = { exchangeContractAddress: exchangeContractAddr, expirationUnixTimestampSec: hashData.orderExpiryTimestamp, feeRecipient: hashData.feeRecipientAddress, @@ -320,9 +325,10 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G const orderHash = getOrderHashHex(zeroExOrder); let globalErrMsg = ''; + let order; try { const ecSignature = await this.props.blockchain.signOrderHashAsync(orderHash); - const order = utils.generateOrder( + order = utils.generateOrder( exchangeContractAddr, this.props.sideToAssetToken, hashData.orderExpiryTimestamp, @@ -356,7 +362,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G signingState: globalErrMsg === '' ? SigningState.SIGNED : SigningState.UNSIGNED, globalErrMsg, }); - return globalErrMsg === ''; + return order; } private _updateOrderAddress(address?: string): void { if (!_.isUndefined(address)) { diff --git a/packages/website/ts/components/inputs/allowance_toggle.tsx b/packages/website/ts/components/inputs/allowance_toggle.tsx index 0d5995696..b3f1aead2 100644 --- a/packages/website/ts/components/inputs/allowance_toggle.tsx +++ b/packages/website/ts/components/inputs/allowance_toggle.tsx @@ -111,14 +111,16 @@ export class AllowanceToggle extends React.Component<AllowanceToggleProps, Allow if (!this._isAllowanceSet()) { newAllowanceAmountInBaseUnits = DEFAULT_ALLOWANCE_AMOUNT_IN_BASE_UNITS; } - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; - const eventLabel = `${this.props.token.symbol}-${networkName}`; + const logData = { + tokenSymbol: this.props.token.symbol, + newAllowance: newAllowanceAmountInBaseUnits.toNumber(), + }; try { await this.props.blockchain.setProxyAllowanceAsync(this.props.token, newAllowanceAmountInBaseUnits); - analytics.logEvent('Portal', 'Set Allowance Success', eventLabel, newAllowanceAmountInBaseUnits.toNumber()); + analytics.track('Set Allowances Success', logData); await this.props.refetchTokenStateAsync(); } catch (err) { - analytics.logEvent('Portal', 'Set Allowance Failure', eventLabel, newAllowanceAmountInBaseUnits.toNumber()); + analytics.track('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 20a8f0a32..63b98cee7 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -225,20 +225,25 @@ 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) ) { - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; - analytics.logEvent('Portal', 'Onboarding Started - Automatic', networkName, this.props.stepIndex); + analytics.track('Onboarding Started', { + reason: 'automatic', + stepIndex: this.props.stepIndex, + }); this.props.updateIsRunning(true); } } private _updateOnboardingStep(stepIndex: number): void { - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; this.props.updateOnboardingStep(stepIndex); - analytics.logEvent('Portal', 'Update Onboarding Step', networkName, 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.logEvent('Portal', 'Onboarding Closed', networkName, this.props.stepIndex); + analytics.track('OnboardingClosed', { + stepIndex: this.props.stepIndex, + }); } private _renderZrxAllowanceToggle(): React.ReactNode { const zrxToken = utils.getZrxToken(this.props.tokenByAddress); diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index f983241fa..2e02f42f6 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -390,8 +390,10 @@ export class Portal extends React.Component<PortalProps, PortalState> { } private _startOnboarding(): void { - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; - analytics.logEvent('Portal', 'Onboarding Started - Manual', networkName, this.props.portalOnboardingStep); + analytics.track('Onboarding Started', { + reason: 'manual', + stepIndex: this.props.portalOnboardingStep, + }); this.props.dispatcher.updatePortalOnboardingShowing(true); } private _renderWalletSection(): React.ReactNode { 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 431cf145b..2eb04f2d6 100644 --- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx +++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx @@ -64,10 +64,10 @@ export const RelayerGridTile: React.StatelessComponent<RelayerGridTileProps> = ( const link = props.relayerInfo.appUrl || props.relayerInfo.url; const topTokens = props.relayerInfo.topTokens; const weeklyTxnVolume = props.relayerInfo.weeklyTxnVolume; - const networkName = sharedConstants.NETWORK_NAME_BY_ID[props.networkId]; - const eventLabel = `${props.relayerInfo.name}-${networkName}`; const onClick = () => { - analytics.logEvent('Portal', 'Relayer Click', eventLabel); + analytics.track('Relayer Click', { + name: props.relayerInfo.name, + }); utils.openUrl(link); }; const headerImageUrl = props.relayerInfo.logoImgUrl; 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 c48b672e9..883c8d81b 100644 --- a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx +++ b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx @@ -46,11 +46,11 @@ class TokenLink extends React.Component<TokenLinkProps, TokenLinkState> { }; } public render(): React.ReactNode { - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; - const eventLabel = `${this.props.tokenInfo.symbol}-${networkName}`; const onClick = (event: React.MouseEvent<HTMLElement>) => { event.stopPropagation(); - analytics.logEvent('Portal', 'Token Click', eventLabel); + analytics.track('Token Click', { + tokenSymbol: this.props.tokenInfo.symbol, + }); const tokenLink = this._tokenLinkFromToken(this.props.tokenInfo, this.props.networkId); utils.openUrl(tokenLink); }; diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 6c1c495d7..940cd6c58 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -491,7 +491,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Opened' : 'Wallet - Unwrap WETH Opened'; - analytics.logEvent('Portal', action, networkName); + analytics.track(action); this.setState({ wrappedEtherDirection, }); @@ -500,7 +500,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Closed' : 'Wallet - Unwrap WETH Closed'; - analytics.logEvent('Portal', action, networkName); + analytics.track(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 2b4cf93fe..01d9bdb66 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -188,20 +188,23 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther this.setState({ isEthConversionHappening: true, }); - const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; + const etherToken = this.props.etherToken; + const amountToConvert = this.state.currentInputAmount; + const ethAmount = Web3Wrapper.toUnitAmount(amountToConvert, constants.DECIMAL_PLACES_ETH).toString(); + const tokenAmount = Web3Wrapper.toUnitAmount(amountToConvert, etherToken.decimals).toString(); try { - const etherToken = this.props.etherToken; - const amountToConvert = this.state.currentInputAmount; if (this.props.direction === Side.Deposit) { await this.props.blockchain.convertEthToWrappedEthTokensAsync(etherToken.address, amountToConvert); - const ethAmount = Web3Wrapper.toUnitAmount(amountToConvert, constants.DECIMAL_PLACES_ETH); - this.props.dispatcher.showFlashMessage(`Successfully wrapped ${ethAmount.toString()} ETH to WETH`); - analytics.logEvent('Portal', 'Wrap ETH Successfully', networkName); + this.props.dispatcher.showFlashMessage(`Successfully wrapped ${ethAmount} ETH to WETH`); + analytics.track('Wrap ETH Success', { + amount: ethAmount, + }); } else { await this.props.blockchain.convertWrappedEthTokensToEthAsync(etherToken.address, amountToConvert); - const tokenAmount = Web3Wrapper.toUnitAmount(amountToConvert, etherToken.decimals); - this.props.dispatcher.showFlashMessage(`Successfully unwrapped ${tokenAmount.toString()} WETH to ETH`); - analytics.logEvent('Portal', 'Unwrap WETH Successfully', networkName); + this.props.dispatcher.showFlashMessage(`Successfully unwrapped ${tokenAmount} WETH to ETH`); + analytics.track('Unwrap WETH Success', { + amount: tokenAmount, + }); } await this.props.refetchEthTokenStateAsync(); this.props.onConversionSuccessful(); @@ -214,10 +217,14 @@ 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.logEvent('Portal', 'Wrap ETH Failed', networkName); + analytics.track('Wrap ETH Failure', { + amount: ethAmount, + }); } else { this.props.dispatcher.showFlashMessage('Failed to unwrap your WETH. Please try again.'); - analytics.logEvent('Portal', 'Unwrap WETH Failed', networkName); + analytics.track('Unwrap WETH Failed', { + amount: tokenAmount, + }); } await errorReporter.reportAsync(err); } diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx index c7ccfdf1f..aba72f52a 100644 --- a/packages/website/ts/index.tsx +++ b/packages/website/ts/index.tsx @@ -74,10 +74,6 @@ const LazyEthereumTypesDocumentation = createLazyComponent('Documentation', asyn System.import<any>(/* webpackChunkName: "ethereumTypesDocs" */ 'ts/containers/ethereum_types_documentation'), ); -analytics.init(); -// tslint:disable-next-line:no-floating-promises -analytics.logProviderAsync((window as any).web3); - render( <Router> <div> diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index e8dc694f6..f107b3b5e 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -516,8 +516,10 @@ export interface OutdatedWrappedEtherByNetworkId { }; } -export interface ItemByAddress<T> { - [address: string]: T; +export type ItemByAddress<T> = ObjectMap<T>; + +export interface ObjectMap<T> { + [key: string]: T; } export type TokenStateByAddress = ItemByAddress<TokenState>; diff --git a/packages/website/ts/utils/analytics.ts b/packages/website/ts/utils/analytics.ts index f4bfa083f..9a1684813 100644 --- a/packages/website/ts/utils/analytics.ts +++ b/packages/website/ts/utils/analytics.ts @@ -1,27 +1,71 @@ import * as _ from 'lodash'; -import * as ReactGA from 'react-ga'; -import { InjectedWeb3 } from 'ts/types'; +import { InjectedWeb3, ObjectMap, Order } from 'ts/types'; import { configs } from 'ts/utils/configs'; import { utils } from 'ts/utils/utils'; -export const analytics = { - init(): void { - ReactGA.initialize(configs.GOOGLE_ANALYTICS_ID); - }, - logEvent(category: string, action: string, label: string, value?: any): void { - ReactGA.event({ - category, - action, - label, - value, - }); - }, - async logProviderAsync(web3IfExists: InjectedWeb3): Promise<void> { +export interface HeapAnalytics { + indentify(id: string, idType: string): void; + track(eventName: string, eventProperties?: ObjectMap<string | number>): void; + resetIdentity(): void; + addUserProperties(properties: ObjectMap<string | number>): void; + addEventProperties(properties: ObjectMap<string | number>): void; + removeEventProperty(property: string): void; + clearEventProperties(): void; +} + +export class Analytics implements HeapAnalytics { + private _heap: HeapAnalytics; + public static init(): Analytics { + const heap = (window as any).heap; + if (!_.isUndefined(heap)) { + return new Analytics(heap); + } else { + throw new Error('Could not find the Heap SDK on the page.'); + } + } + constructor(heap: HeapAnalytics) { + this._heap = heap; + } + // HeapAnalytics Wrappers + public indentify(id: string, idType: string): void { + this._heap.indentify(id, idType); + } + public track(eventName: string, eventProperties?: ObjectMap<string | number>): void { + this._heap.track(eventName, eventProperties); + } + public resetIdentity(): void { + this._heap.resetIdentity(); + } + public addUserProperties(properties: ObjectMap<string | number>): void { + this._heap.addUserProperties(properties); + } + public addEventProperties(properties: ObjectMap<string | number>): void { + this._heap.addEventProperties(properties); + } + public removeEventProperty(property: string): void { + this._heap.removeEventProperty(property); + } + public clearEventProperties(): void { + this._heap.clearEventProperties(); + } + // Custom methods + public trackOrderEvent(eventName: string, order: Order): 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); + } + public async logProviderAsync(web3IfExists: InjectedWeb3): Promise<void> { await utils.onPageLoadAsync(); const providerType = !_.isUndefined(web3IfExists) && !_.isUndefined(web3IfExists.currentProvider) ? utils.getProviderType(web3IfExists.currentProvider) : 'NONE'; - ReactGA.ga('set', 'dimension1', providerType); - }, -}; + } +} + +// Assume heap library has loaded. +export const analytics = Analytics.init(); diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts index 97aabd13d..a2fd6a47e 100644 --- a/packages/website/ts/utils/configs.ts +++ b/packages/website/ts/utils/configs.ts @@ -23,6 +23,7 @@ export const configs = { DOMAIN_PRODUCTION: '0xproject.com', ENVIRONMENT: isDevelopment ? Environments.DEVELOPMENT : Environments.PRODUCTION, GOOGLE_ANALYTICS_ID: 'UA-98720122-1', + HEAP_APP_ID: '410099666', LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE: '2017-11-22', LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE: '2018-7-5', OUTDATED_WRAPPED_ETHERS: [ diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index e43f541bf..d52b9b392 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -34,6 +34,7 @@ export const constants = { PROVIDER_NAME_GENERIC: 'Injected Web3', PROVIDER_NAME_PUBLIC: '0x Public', ROLLBAR_ACCESS_TOKEN: '32c39bfa4bb6440faedc1612a9c13d28', + HEAP_APP_ID: '410099666', S3_DOC_BUCKET_ROOT: 'https://s3.amazonaws.com/doc-jsons', S3_STAGING_DOC_BUCKET_ROOT: 'https://s3.amazonaws.com/staging-doc-jsons', SUCCESS_STATUS: 200, diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 8c76a7592..df7f8d10f 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -313,6 +313,7 @@ export const utils = { const baseUrl = `https://${window.location.hostname}${hasPort ? `:${port}` : ''}`; return baseUrl; }, + // TODO: Fix this, it's a lie. async onPageLoadAsync(): Promise<void> { if (document.readyState === 'complete') { return; // Already loaded |