From d319b53e23047d4ff62415555475ef6da5f3d774 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 10 Jul 2018 15:13:54 -0700 Subject: Add Heap snippet --- packages/website/public/index.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/website/public/index.html b/packages/website/public/index.html index 060f2c3c2..2d9b722f8 100644 --- a/packages/website/public/index.html +++ b/packages/website/public/index.html @@ -82,6 +82,12 @@ })(window, document, 'https://static.hotjar.com/c/hotjar-', '.js?sv='); + + + -- cgit v1.2.3 From 9131a72a47690912db9b536186d05120daabd115 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 11 Jul 2018 12:14:23 -0700 Subject: Replace calls to google analytics with calls to heap --- packages/website/package.json | 10 +-- packages/website/ts/components/fill_order.tsx | 14 ++-- .../generate_order/generate_order_form.tsx | 36 ++++++---- .../ts/components/inputs/allowance_toggle.tsx | 10 +-- .../onboarding/portal_onboarding_flow.tsx | 15 ++-- packages/website/ts/components/portal/portal.tsx | 6 +- .../components/relayer_index/relayer_grid_tile.tsx | 6 +- .../relayer_index/relayer_top_tokens.tsx | 6 +- packages/website/ts/components/wallet/wallet.tsx | 4 +- .../ts/components/wallet/wrap_ether_item.tsx | 29 +++++--- packages/website/ts/index.tsx | 4 -- packages/website/ts/types.ts | 6 +- packages/website/ts/utils/analytics.ts | 80 +++++++++++++++++----- packages/website/ts/utils/configs.ts | 1 + packages/website/ts/utils/constants.ts | 1 + packages/website/ts/utils/utils.ts | 1 + yarn.lock | 16 ----- 17 files changed, 147 insertions(+), 98 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 { await this._checkForUntrackedTokensAndAskToAddAsync(); } + private _trackOrderEvent(eventName: string): void { + const parsedOrder = this.state.parsedOrder; + analytics.trackOrderEvent(eventName, parsedOrder); + } private async _onFillOrderClickFireAndForgetAsync(): Promise { 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 { }); 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 { 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 { 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 { 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 { + private async _signTransactionAsync(): Promise { this.setState({ signingState: SigningState.SIGNING, }); @@ -299,11 +304,11 @@ export class GenerateOrderForm extends React.Component { } 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 = ( 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 { }; } 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) => { 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 { 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 { 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(/* webpackChunkName: "ethereumTypesDocs" */ 'ts/containers/ethereum_types_documentation'), ); -analytics.init(); -// tslint:disable-next-line:no-floating-promises -analytics.logProviderAsync((window as any).web3); - render(
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 { - [address: string]: T; +export type ItemByAddress = ObjectMap; + +export interface ObjectMap { + [key: string]: T; } export type TokenStateByAddress = ItemByAddress; 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 { +export interface HeapAnalytics { + indentify(id: string, idType: string): void; + track(eventName: string, eventProperties?: ObjectMap): void; + resetIdentity(): void; + addUserProperties(properties: ObjectMap): void; + addEventProperties(properties: ObjectMap): 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): void { + this._heap.track(eventName, eventProperties); + } + public resetIdentity(): void { + this._heap.resetIdentity(); + } + public addUserProperties(properties: ObjectMap): void { + this._heap.addUserProperties(properties); + } + public addEventProperties(properties: ObjectMap): 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 { 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 { if (document.readyState === 'complete') { return; // Already loaded diff --git a/yarn.lock b/yarn.lock index 9c373aaa5..8582b3897 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9858,13 +9858,6 @@ react-event-listener@^0.4.5: prop-types "^15.5.4" warning "^3.0.0" -react-ga@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-2.4.1.tgz#dfbd5f028ed39a07067f7a8bf57dc0d240000767" - optionalDependencies: - prop-types "^15.6.0" - react "^15.6.2 || ^16.0" - react-highlight@0xproject/react-highlight: version "0.10.0" resolved "https://codeload.github.com/0xproject/react-highlight/tar.gz/83bbb4a09801abd341e2b9041cd884885a4a2098" @@ -9990,15 +9983,6 @@ react@^15.5.4: object-assign "^4.1.0" prop-types "^15.5.10" -"react@^15.6.2 || ^16.0": - version "16.3.2" - resolved "https://registry.yarnpkg.com/react/-/react-16.3.2.tgz#fdc8420398533a1e58872f59091b272ce2f91ea9" - dependencies: - fbjs "^0.8.16" - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.0" - read-chunk@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-2.1.0.tgz#6a04c0928005ed9d42e1a6ac5600e19cbc7ff655" -- cgit v1.2.3 From 098322c56475581df5bd80e12cb6c511963e4daf Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 11 Jul 2018 15:39:12 -0700 Subject: Integrate heap analytics --- packages/website/public/index.html | 12 ++--- packages/website/ts/blockchain.ts | 2 +- packages/website/ts/components/fill_order.tsx | 6 +-- .../website/ts/components/forms/subscribe_form.tsx | 4 ++ .../generate_order/generate_order_form.tsx | 8 ++-- .../ts/components/inputs/allowance_toggle.tsx | 6 +-- .../onboarding/portal_onboarding_flow.tsx | 9 +--- packages/website/ts/components/portal/portal.tsx | 5 +- .../components/relayer_index/relayer_grid_tile.tsx | 4 +- .../relayer_index/relayer_top_tokens.tsx | 3 +- packages/website/ts/components/wallet/wallet.tsx | 8 ++-- .../ts/components/wallet/wrap_ether_item.tsx | 10 ++-- packages/website/ts/index.tsx | 1 - packages/website/ts/pages/wiki/wiki.tsx | 2 +- packages/website/ts/redux/analyticsMiddleware.ts | 41 ++++++++++++++++ packages/website/ts/redux/store.ts | 7 +-- packages/website/ts/utils/analytics.ts | 56 ++++++++++++++-------- packages/website/ts/utils/utils.ts | 12 ++--- 18 files changed, 122 insertions(+), 74 deletions(-) create mode 100644 packages/website/ts/redux/analyticsMiddleware.ts 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 @@ + + + - - - 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 { - 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 { } private _trackOrderEvent(eventName: string): void { const parsedOrder = this.state.parsedOrder; - analytics.trackOrderEvent(eventName, parsedOrder); + analytics.trackOrderEventAsync(eventName, parsedOrder); } private async _onFillOrderClickFireAndForgetAsync(): Promise { if (this.props.blockchainErr !== BlockchainErrs.NoError || _.isEmpty(this.props.userAddress)) { @@ -630,8 +630,6 @@ export class FillOrder extends React.Component { }); 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 { 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 = ( 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 { public render(): React.ReactNode { const onClick = (event: React.MouseEvent) => { 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 { ); } 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 { 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 = 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): 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 { + await this._heapLoadedGuardAsync(); this._heap.indentify(id, idType); } - public track(eventName: string, eventProperties?: ObjectMap): void { + public async trackAsync(eventName: string, eventProperties?: ObjectMap): Promise { + await this._heapLoadedGuardAsync(); this._heap.track(eventName, eventProperties); } - public resetIdentity(): void { + public async resetIdentityAsync(): Promise { + await this._heapLoadedGuardAsync(); this._heap.resetIdentity(); } - public addUserProperties(properties: ObjectMap): void { + public async addUserPropertiesAsync(properties: ObjectMap): Promise { + await this._heapLoadedGuardAsync(); this._heap.addUserProperties(properties); } - public addEventProperties(properties: ObjectMap): void { + public async addEventPropertiesAsync(properties: ObjectMap): Promise { + await this._heapLoadedGuardAsync(); this._heap.addEventProperties(properties); } - public removeEventProperty(property: string): void { + public async removeEventPropertyAsync(property: string): Promise { + await this._heapLoadedGuardAsync(); this._heap.removeEventProperty(property); } - public clearEventProperties(): void { + public async clearEventPropertiesAsync(): Promise { + await this._heapLoadedGuardAsync(); this._heap.clearEventProperties(); } // Custom methods - public trackOrderEvent(eventName: string, order: Order): void { + public async trackOrderEventAsync(eventName: string, order: Order): Promise { 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 { - 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 { + 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 { + onPageLoadPromise: new Promise((resolve, _reject) => { if (document.readyState === 'complete') { - return; // Already loaded + resolve(); + return; } - return new Promise((resolve, _reject) => { - window.onload = () => resolve(); - }); - }, + window.onload = () => resolve(); + }), getProviderType(provider: Provider): Providers | string { const constructorName = provider.constructor.name; let parsedProviderName = constructorName; -- cgit v1.2.3 From 1ee78062d7731b35e47c0d4c4e30a68628f364a9 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 11 Jul 2018 15:43:37 -0700 Subject: Remove unused configs and constants --- packages/website/ts/utils/configs.ts | 1 - packages/website/ts/utils/constants.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts index a2fd6a47e..97aabd13d 100644 --- a/packages/website/ts/utils/configs.ts +++ b/packages/website/ts/utils/configs.ts @@ -23,7 +23,6 @@ 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 d52b9b392..e43f541bf 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -34,7 +34,6 @@ 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, -- cgit v1.2.3 From 0941e0a929f2fe3ef6d0cf1de5a1274f5f45f031 Mon Sep 17 00:00:00 2001 From: fragosti Date: Wed, 11 Jul 2018 16:50:00 -0700 Subject: Add no-floating-promises ignore comments --- packages/website/ts/components/fill_order.tsx | 1 + packages/website/ts/components/forms/subscribe_form.tsx | 1 + .../website/ts/components/generate_order/generate_order_form.tsx | 2 ++ packages/website/ts/components/inputs/allowance_toggle.tsx | 2 ++ .../website/ts/components/onboarding/portal_onboarding_flow.tsx | 2 ++ packages/website/ts/components/portal/portal.tsx | 1 + packages/website/ts/components/relayer_index/relayer_grid_tile.tsx | 1 + .../website/ts/components/relayer_index/relayer_top_tokens.tsx | 7 ++----- packages/website/ts/components/wallet/wallet.tsx | 2 ++ packages/website/ts/components/wallet/wrap_ether_item.tsx | 4 ++++ packages/website/ts/redux/analyticsMiddleware.ts | 5 +++++ packages/website/ts/utils/analytics.ts | 1 + 12 files changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index 25d21c3dd..e4838bc0f 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -508,6 +508,7 @@ export class FillOrder extends React.Component { } private _trackOrderEvent(eventName: string): void { const parsedOrder = this.state.parsedOrder; + // tslint:disable-next-line:no-floating-promises analytics.trackOrderEventAsync(eventName, parsedOrder); } private async _onFillOrderClickFireAndForgetAsync(): Promise { diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx index 19abbdf5f..be0468b6f 100644 --- a/packages/website/ts/components/forms/subscribe_form.tsx +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -114,6 +114,7 @@ export class SubscribeForm extends React.Component { ); } private _startOnboarding(): void { + // tslint:disable-next-line:no-floating-promises 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 937f0b79d..475b79f8f 100644 --- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx +++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx @@ -65,6 +65,7 @@ export const RelayerGridTile: React.StatelessComponent = ( const topTokens = props.relayerInfo.topTokens; const weeklyTxnVolume = props.relayerInfo.weeklyTxnVolume; const onClick = () => { + // tslint:disable-next-line:no-floating-promises analytics.trackAsync('Relayer Click', { name: props.relayerInfo.name, }); 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 e6e0095c2..33783b406 100644 --- a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx +++ b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx @@ -1,8 +1,4 @@ -import { - colors, - EtherscanLinkSuffixes, - utils as sharedUtils, -} from '@0xproject/react-shared'; +import { colors, EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared'; import * as _ from 'lodash'; import * as React from 'react'; @@ -47,6 +43,7 @@ class TokenLink extends React.Component { public render(): React.ReactNode { const onClick = (event: React.MouseEvent) => { event.stopPropagation(); + // tslint:disable-next-line:no-floating-promises analytics.trackAsync('Token Click', { tokenSymbol: this.props.tokenInfo.symbol, }); diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 2fdcded38..8523b819a 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -490,6 +490,7 @@ export class Wallet extends React.Component { private _openWrappedEtherActionRow(wrappedEtherDirection: Side): void { const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Opened' : 'Wallet - Unwrap WETH Opened'; + // tslint:disable-next-line:no-floating-promises analytics.trackAsync(action); this.setState({ wrappedEtherDirection, @@ -498,6 +499,7 @@ export class Wallet extends React.Component { private _closeWrappedEtherActionRow(wrappedEtherDirection: Side): void { const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Closed' : 'Wallet - Unwrap WETH Closed'; + // tslint:disable-next-line:no-floating-promises 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 9fec8afa1..9e3d06817 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -196,12 +196,14 @@ export class WrapEtherItem extends React.Component next => action => { const nextState = (store.getState() as any) as State; switch (action.type) { case ActionTypes.UpdateInjectedProviderName: + // tslint:disable-next-line:no-floating-promises analytics.addEventPropertiesAsync({ injectedProviderName: nextState.injectedProviderName, }); break; case ActionTypes.UpdateNetworkId: + // tslint:disable-next-line:no-floating-promises analytics.addEventPropertiesAsync({ networkId: nextState.networkId, }); break; case ActionTypes.UpdateUserAddress: + // tslint:disable-next-line:no-floating-promises analytics.addUserPropertiesAsync({ ethAddress: nextState.userAddress, }); break; case ActionTypes.UpdateUserEtherBalance: if (nextState.userEtherBalanceInWei) { + // tslint:disable-next-line:no-floating-promises analytics.addUserPropertiesAsync({ ethBalance: nextState.userEtherBalanceInWei.toString(), }); } break; case ActionTypes.UpdatePortalOnboardingStep: + // tslint:disable-next-line:no-floating-promises analytics.trackAsync('Update Onboarding Step', { stepIndex: nextState.portalOnboardingStep, }); diff --git a/packages/website/ts/utils/analytics.ts b/packages/website/ts/utils/analytics.ts index 961f9af5a..2ff9f8918 100644 --- a/packages/website/ts/utils/analytics.ts +++ b/packages/website/ts/utils/analytics.ts @@ -66,6 +66,7 @@ export class Analytics { takerToken: order.metadata.takerToken.symbol, makerToken: order.metadata.makerToken.symbol, }; + // tslint:disable-next-line:no-floating-promises this.trackAsync(eventName, orderLoggingData); } /** -- cgit v1.2.3 From 1df074b73e05adf669b0cedc4bb1473e9e5631db Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 12 Jul 2018 16:57:03 -0700 Subject: Make Analytics API non-async --- packages/website/ts/components/fill_order.tsx | 3 +- .../website/ts/components/forms/subscribe_form.tsx | 3 +- .../generate_order/generate_order_form.tsx | 6 +-- .../ts/components/inputs/allowance_toggle.tsx | 6 +-- .../onboarding/portal_onboarding_flow.tsx | 6 +-- packages/website/ts/components/portal/portal.tsx | 3 +- .../components/relayer_index/relayer_grid_tile.tsx | 3 +- .../relayer_index/relayer_top_tokens.tsx | 3 +- packages/website/ts/components/wallet/wallet.tsx | 6 +-- .../ts/components/wallet/wrap_ether_item.tsx | 12 ++---- packages/website/ts/redux/analyticsMiddleware.ts | 15 +++---- packages/website/ts/utils/analytics.ts | 47 ++++++++++------------ packages/website/ts/utils/utils.ts | 2 +- 13 files changed, 44 insertions(+), 71 deletions(-) diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index e4838bc0f..ff63410c3 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -508,8 +508,7 @@ export class FillOrder extends React.Component { } private _trackOrderEvent(eventName: string): void { const parsedOrder = this.state.parsedOrder; - // tslint:disable-next-line:no-floating-promises - analytics.trackOrderEventAsync(eventName, parsedOrder); + analytics.trackOrderEvent(eventName, parsedOrder); } private async _onFillOrderClickFireAndForgetAsync(): Promise { if (this.props.blockchainErr !== BlockchainErrs.NoError || _.isEmpty(this.props.userAddress)) { diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx index be0468b6f..ef19af644 100644 --- a/packages/website/ts/components/forms/subscribe_form.tsx +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -114,8 +114,7 @@ export class SubscribeForm extends React.Component { ); } private _startOnboarding(): void { - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync('Onboarding Started', { + analytics.track('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 475b79f8f..193dd237a 100644 --- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx +++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx @@ -65,8 +65,7 @@ export const RelayerGridTile: React.StatelessComponent = ( const topTokens = props.relayerInfo.topTokens; const weeklyTxnVolume = props.relayerInfo.weeklyTxnVolume; const onClick = () => { - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync('Relayer Click', { + analytics.track('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 33783b406..f3787bd27 100644 --- a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx +++ b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx @@ -43,8 +43,7 @@ class TokenLink extends React.Component { public render(): React.ReactNode { const onClick = (event: React.MouseEvent) => { event.stopPropagation(); - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync('Token Click', { + analytics.track('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 8523b819a..e462ab3e0 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -490,8 +490,7 @@ export class Wallet extends React.Component { private _openWrappedEtherActionRow(wrappedEtherDirection: Side): void { const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Opened' : 'Wallet - Unwrap WETH Opened'; - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync(action); + analytics.track(action); this.setState({ wrappedEtherDirection, }); @@ -499,8 +498,7 @@ export class Wallet extends React.Component { private _closeWrappedEtherActionRow(wrappedEtherDirection: Side): void { const action = wrappedEtherDirection === Side.Deposit ? 'Wallet - Wrap ETH Closed' : 'Wallet - Unwrap WETH Closed'; - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync(action); + 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 9e3d06817..2b85b69be 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -196,15 +196,13 @@ export class WrapEtherItem extends React.Component next => action => { const nextState = (store.getState() as any) as State; switch (action.type) { case ActionTypes.UpdateInjectedProviderName: - // tslint:disable-next-line:no-floating-promises - analytics.addEventPropertiesAsync({ + analytics.addEventProperties({ injectedProviderName: nextState.injectedProviderName, }); break; case ActionTypes.UpdateNetworkId: - // tslint:disable-next-line:no-floating-promises - analytics.addEventPropertiesAsync({ + analytics.addEventProperties({ networkId: nextState.networkId, }); break; case ActionTypes.UpdateUserAddress: - // tslint:disable-next-line:no-floating-promises - analytics.addUserPropertiesAsync({ + analytics.addUserProperties({ ethAddress: nextState.userAddress, }); break; case ActionTypes.UpdateUserEtherBalance: if (nextState.userEtherBalanceInWei) { - // tslint:disable-next-line:no-floating-promises - analytics.addUserPropertiesAsync({ + analytics.addUserProperties({ ethBalance: nextState.userEtherBalanceInWei.toString(), }); } break; case ActionTypes.UpdatePortalOnboardingStep: - // tslint:disable-next-line:no-floating-promises - analytics.trackAsync('Update Onboarding Step', { + analytics.track('Update Onboarding Step', { stepIndex: nextState.portalOnboardingStep, }); break; diff --git a/packages/website/ts/utils/analytics.ts b/packages/website/ts/utils/analytics.ts index 2ff9f8918..e39998d7a 100644 --- a/packages/website/ts/utils/analytics.ts +++ b/packages/website/ts/utils/analytics.ts @@ -12,7 +12,6 @@ export interface HeapAnalytics { removeEventProperty(property: string): void; clearEventProperties(): void; } - export class Analytics { private _heap: HeapAnalytics; public static init(): Analytics { @@ -29,45 +28,39 @@ export class Analytics { constructor(heap: HeapAnalytics) { this._heap = heap; } + // tslint:disable:no-floating-promises // HeapAnalytics Wrappers - public async indentifyAsync(id: string, idType: string): Promise { - await this._heapLoadedGuardAsync(); - this._heap.indentify(id, idType); + public indentify(id: string, idType: string): void { + this._heapLoadedGuardAsync(() => this._heap.indentify(id, idType)); } - public async trackAsync(eventName: string, eventProperties?: ObjectMap): Promise { - await this._heapLoadedGuardAsync(); - this._heap.track(eventName, eventProperties); + public track(eventName: string, eventProperties?: ObjectMap): void { + this._heapLoadedGuardAsync(() => this._heap.track(eventName, eventProperties)); } - public async resetIdentityAsync(): Promise { - await this._heapLoadedGuardAsync(); - this._heap.resetIdentity(); + public resetIdentity(): void { + this._heapLoadedGuardAsync(() => this._heap.resetIdentity()); } - public async addUserPropertiesAsync(properties: ObjectMap): Promise { - await this._heapLoadedGuardAsync(); - this._heap.addUserProperties(properties); + public addUserProperties(properties: ObjectMap): void { + this._heapLoadedGuardAsync(() => this._heap.addUserProperties(properties)); } - public async addEventPropertiesAsync(properties: ObjectMap): Promise { - await this._heapLoadedGuardAsync(); - this._heap.addEventProperties(properties); + public addEventProperties(properties: ObjectMap): void { + this._heapLoadedGuardAsync(() => this._heap.addEventProperties(properties)); } - public async removeEventPropertyAsync(property: string): Promise { - await this._heapLoadedGuardAsync(); - this._heap.removeEventProperty(property); + public removeEventProperty(property: string): void { + this._heapLoadedGuardAsync(() => this._heap.removeEventProperty(property)); } - public async clearEventPropertiesAsync(): Promise { - await this._heapLoadedGuardAsync(); - this._heap.clearEventProperties(); + public clearEventProperties(): void { + this._heapLoadedGuardAsync(() => this._heap.clearEventProperties()); } + // tslint:enable:no-floating-promises // Custom methods - public async trackOrderEventAsync(eventName: string, order: Order): Promise { + 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, }; - // tslint:disable-next-line:no-floating-promises - this.trackAsync(eventName, orderLoggingData); + this.track(eventName, orderLoggingData); } /** * Heap is not available as a UMD module, and additionally has the strange property of replacing itself with @@ -75,13 +68,15 @@ export class Analytics { * 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 { + private async _heapLoadedGuardAsync(callback: () => void): Promise { if (this._heap.loaded) { + callback(); return undefined; } await utils.onPageLoadPromise; // HACK: Reset heap to loaded heap this._heap = (window as any).heap; + callback(); } } diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index bd6a57eea..9c5e12ec7 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -318,7 +318,7 @@ export const utils = { resolve(); return; } - window.onload = () => resolve(); + window.onload = resolve; }), getProviderType(provider: Provider): Providers | string { const constructorName = provider.constructor.name; -- cgit v1.2.3 From 65af78c85d7872891c0bffeac76687a72a61dd59 Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 12 Jul 2018 18:20:46 -0700 Subject: Fix indentify typo --- packages/website/ts/components/forms/subscribe_form.tsx | 2 +- packages/website/ts/utils/analytics.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx index ef19af644..761db7517 100644 --- a/packages/website/ts/components/forms/subscribe_form.tsx +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -114,7 +114,7 @@ export class SubscribeForm extends React.Component): void; resetIdentity(): void; addUserProperties(properties: ObjectMap): void; @@ -30,8 +30,8 @@ export class Analytics { } // tslint:disable:no-floating-promises // HeapAnalytics Wrappers - public indentify(id: string, idType: string): void { - this._heapLoadedGuardAsync(() => this._heap.indentify(id, idType)); + public identify(id: string, idType: string): void { + this._heapLoadedGuardAsync(() => this._heap.identify(id, idType)); } public track(eventName: string, eventProperties?: ObjectMap): void { this._heapLoadedGuardAsync(() => this._heap.track(eventName, eventProperties)); -- cgit v1.2.3 From ee54438e92f191637ecb0d36e9d79e707d1c976c Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 12 Jul 2018 18:30:01 -0700 Subject: Fix logging typo --- packages/website/ts/components/onboarding/portal_onboarding_flow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index 94a6338ee..a51170735 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -236,7 +236,7 @@ class PlainPortalOnboardingFlow extends React.Component