Merge pull request #447 from 0xProject/refactorAnalytics
Refactor Website Analytics
This commit is contained in:
commit
76a31b6fd6
@ -39,6 +39,7 @@ import {
|
||||
BlockchainErrs,
|
||||
ContractInstance,
|
||||
Order as PortalOrder,
|
||||
Providers,
|
||||
ProviderType,
|
||||
Side,
|
||||
SideToAssetToken,
|
||||
@ -58,6 +59,12 @@ import * as MintableArtifacts from '../contracts/Mintable.json';
|
||||
const BLOCK_NUMBER_BACK_TRACK = 50;
|
||||
const GWEI_IN_WEI = 1000000000;
|
||||
|
||||
const providerToName: { [provider: string]: string } = {
|
||||
[Providers.Metamask]: constants.PROVIDER_NAME_METAMASK,
|
||||
[Providers.Parity]: constants.PROVIDER_NAME_PARITY_SIGNER,
|
||||
[Providers.Mist]: constants.PROVIDER_NAME_MIST,
|
||||
};
|
||||
|
||||
export class Blockchain {
|
||||
public networkId: number;
|
||||
public nodeVersion: string;
|
||||
@ -71,18 +78,12 @@ export class Blockchain {
|
||||
private _ledgerSubprovider: LedgerWalletSubprovider;
|
||||
private _defaultGasPrice: BigNumber;
|
||||
private static _getNameGivenProvider(provider: Web3.Provider): string {
|
||||
if (!_.isUndefined((provider as any).isMetaMask)) {
|
||||
return constants.PROVIDER_NAME_METAMASK;
|
||||
const providerType = utils.getProviderType(provider);
|
||||
const providerNameIfExists = providerToName[providerType];
|
||||
if (_.isUndefined(providerNameIfExists)) {
|
||||
return constants.PROVIDER_NAME_GENERIC;
|
||||
}
|
||||
|
||||
// HACK: We use the fact that Parity Signer's provider is an instance of their
|
||||
// internal `Web3FrameProvider` class.
|
||||
const isParitySigner = _.startsWith(provider.constructor.toString(), 'function Web3FrameProvider');
|
||||
if (isParitySigner) {
|
||||
return constants.PROVIDER_NAME_PARITY_SIGNER;
|
||||
}
|
||||
|
||||
return constants.PROVIDER_NAME_GENERIC;
|
||||
return providerNameIfExists;
|
||||
}
|
||||
private static async _getProviderAsync(injectedWeb3: Web3, networkIdIfExists: number) {
|
||||
const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3);
|
||||
|
@ -7,7 +7,6 @@ import { Card, CardHeader, CardText } from 'material-ui/Card';
|
||||
import Divider from 'material-ui/Divider';
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import * as React from 'react';
|
||||
import * as ReactGA from 'react-ga';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Blockchain } from 'ts/blockchain';
|
||||
import { TrackTokenConfirmationDialog } from 'ts/components/dialogs/track_token_confirmation_dialog';
|
||||
@ -22,6 +21,7 @@ import { Dispatcher } from 'ts/redux/dispatcher';
|
||||
import { portalOrderSchema } from 'ts/schemas/portal_order_schema';
|
||||
import { validator } from 'ts/schemas/validator';
|
||||
import { AlertTypes, BlockchainErrs, Order, Token, TokenByAddress, WebsitePaths } from 'ts/types';
|
||||
import { analytics } from 'ts/utils/analytics';
|
||||
import { constants } from 'ts/utils/constants';
|
||||
import { errorReporter } from 'ts/utils/error_reporter';
|
||||
import { utils } from 'ts/utils/utils';
|
||||
@ -544,12 +544,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
|
||||
signedOrder,
|
||||
this.props.orderFillAmount,
|
||||
);
|
||||
ReactGA.event({
|
||||
category: 'Portal',
|
||||
action: 'Fill Order Success',
|
||||
label: eventLabel,
|
||||
value: parsedOrder.signedOrder.takerTokenAmount,
|
||||
});
|
||||
analytics.logEvent('Portal', 'Fill Order Success', eventLabel, parsedOrder.signedOrder.takerTokenAmount);
|
||||
// After fill completes, let's force fetch the token balances
|
||||
this.props.dispatcher.forceTokenStateRefetch();
|
||||
this.setState({
|
||||
@ -563,12 +558,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
|
||||
this.setState({
|
||||
isFilling: false,
|
||||
});
|
||||
ReactGA.event({
|
||||
category: 'Portal',
|
||||
action: 'Fill Order Failure',
|
||||
label: eventLabel,
|
||||
value: parsedOrder.signedOrder.takerTokenAmount,
|
||||
});
|
||||
analytics.logEvent('Portal', 'Fill Order Failure', eventLabel, parsedOrder.signedOrder.takerTokenAmount);
|
||||
const errMsg = `${err}`;
|
||||
if (utils.didUserDenyWeb3Request(errMsg)) {
|
||||
return;
|
||||
@ -633,12 +623,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
|
||||
globalErrMsg: '',
|
||||
unavailableTakerAmount: takerTokenAmount,
|
||||
});
|
||||
ReactGA.event({
|
||||
category: 'Portal',
|
||||
action: 'Cancel Order Success',
|
||||
label: eventLabel,
|
||||
value: parsedOrder.signedOrder.makerTokenAmount,
|
||||
});
|
||||
analytics.logEvent('Portal', 'Cancel Order Success', eventLabel, parsedOrder.signedOrder.makerTokenAmount);
|
||||
return;
|
||||
} catch (err) {
|
||||
this.setState({
|
||||
@ -648,12 +633,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
|
||||
if (utils.didUserDenyWeb3Request(errMsg)) {
|
||||
return;
|
||||
}
|
||||
ReactGA.event({
|
||||
category: 'Portal',
|
||||
action: 'Cancel Order Failure',
|
||||
label: eventLabel,
|
||||
value: parsedOrder.signedOrder.makerTokenAmount,
|
||||
});
|
||||
analytics.logEvent('Portal', 'Cancel Order Failure', eventLabel, parsedOrder.signedOrder.makerTokenAmount);
|
||||
globalErrMsg = 'Failed to cancel order, please refresh and try again';
|
||||
utils.consoleLog(`${err}`);
|
||||
this.setState({
|
||||
|
@ -5,7 +5,6 @@ import * as _ from 'lodash';
|
||||
import Dialog from 'material-ui/Dialog';
|
||||
import Divider from 'material-ui/Divider';
|
||||
import * as React from 'react';
|
||||
import * as ReactGA from 'react-ga';
|
||||
import { Blockchain } from 'ts/blockchain';
|
||||
import { ExpirationInput } from 'ts/components/inputs/expiration_input';
|
||||
import { HashInput } from 'ts/components/inputs/hash_input';
|
||||
@ -21,6 +20,7 @@ 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 { analytics } from 'ts/utils/analytics';
|
||||
import { constants } from 'ts/utils/constants';
|
||||
import { errorReporter } from 'ts/utils/error_reporter';
|
||||
import { utils } from 'ts/utils/utils';
|
||||
@ -256,12 +256,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
|
||||
if (didSignSuccessfully) {
|
||||
const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId];
|
||||
const eventLabel = `${this.props.tokenByAddress[debitToken.address].symbol}-${networkName}`;
|
||||
ReactGA.event({
|
||||
category: 'Portal',
|
||||
action: 'Sign Order Success',
|
||||
label: eventLabel,
|
||||
value: debitToken.amount.toNumber(),
|
||||
});
|
||||
analytics.logEvent('Portal', 'Sign Order Success', eventLabel, debitToken.amount.toNumber());
|
||||
this.setState({
|
||||
globalErrMsg: '',
|
||||
shouldShowIncompleteErrs: false,
|
||||
@ -274,11 +269,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
|
||||
globalErrMsg = 'You must enable wallet communication';
|
||||
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
|
||||
}
|
||||
ReactGA.event({
|
||||
category: 'Portal',
|
||||
action: 'Sign Order Failure',
|
||||
label: globalErrMsg,
|
||||
});
|
||||
analytics.logEvent('Portal', 'Sign Order Failure', globalErrMsg);
|
||||
this.setState({
|
||||
globalErrMsg,
|
||||
shouldShowIncompleteErrs: true,
|
||||
|
@ -3,10 +3,10 @@ import { BigNumber } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
import Toggle from 'material-ui/Toggle';
|
||||
import * as React from 'react';
|
||||
import * as ReactGA from 'react-ga';
|
||||
import { Blockchain } from 'ts/blockchain';
|
||||
import { Dispatcher } from 'ts/redux/dispatcher';
|
||||
import { BalanceErrs, Token, TokenState } from 'ts/types';
|
||||
import { analytics } from 'ts/utils/analytics';
|
||||
import { constants } from 'ts/utils/constants';
|
||||
import { errorReporter } from 'ts/utils/error_reporter';
|
||||
import { utils } from 'ts/utils/utils';
|
||||
@ -82,20 +82,10 @@ export class AllowanceToggle extends React.Component<AllowanceToggleProps, Allow
|
||||
const eventLabel = `${this.props.token.symbol}-${networkName}`;
|
||||
try {
|
||||
await this.props.blockchain.setProxyAllowanceAsync(this.props.token, newAllowanceAmountInBaseUnits);
|
||||
ReactGA.event({
|
||||
category: 'Portal',
|
||||
action: 'Set Allowance Success',
|
||||
label: eventLabel,
|
||||
value: newAllowanceAmountInBaseUnits.toNumber(),
|
||||
});
|
||||
analytics.logEvent('Portal', 'Set Allowance Success', eventLabel, newAllowanceAmountInBaseUnits.toNumber());
|
||||
await this.props.refetchTokenStateAsync();
|
||||
} catch (err) {
|
||||
ReactGA.event({
|
||||
category: 'Portal',
|
||||
action: 'Set Allowance Failure',
|
||||
label: eventLabel,
|
||||
value: newAllowanceAmountInBaseUnits.toNumber(),
|
||||
});
|
||||
analytics.logEvent('Portal', 'Set Allowance Failure', eventLabel, newAllowanceAmountInBaseUnits.toNumber());
|
||||
this.setState({
|
||||
isSpinnerVisible: false,
|
||||
});
|
||||
|
@ -2,7 +2,6 @@
|
||||
import { MuiThemeProvider } from 'material-ui/styles';
|
||||
import * as React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import * as ReactGA from 'react-ga';
|
||||
import { Provider } from 'react-redux';
|
||||
import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom';
|
||||
import * as injectTapEventPlugin from 'react-tap-event-plugin';
|
||||
@ -17,9 +16,9 @@ import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
|
||||
import { tradeHistoryStorage } from 'ts/local_storage/trade_history_storage';
|
||||
import { reducer, State } from 'ts/redux/reducer';
|
||||
import { WebsitePaths } from 'ts/types';
|
||||
import { analytics } from 'ts/utils/analytics';
|
||||
import { muiTheme } from 'ts/utils/mui_theme';
|
||||
import { utils } from 'ts/utils/utils';
|
||||
import * as Web3 from 'web3';
|
||||
import 'whatwg-fetch';
|
||||
injectTapEventPlugin();
|
||||
|
||||
@ -47,13 +46,9 @@ const LazyConnectDocumentation = createLazyComponent('Documentation', async () =
|
||||
System.import<any>(/* webpackChunkName: "connectDocs" */ 'ts/containers/connect_documentation'),
|
||||
);
|
||||
|
||||
ReactGA.initialize('UA-98720122-1');
|
||||
window.onload = () => {
|
||||
const providerName = (window as any).web3
|
||||
? utils.web3ProviderToString((window as any).web3.currentProvider)
|
||||
: 'NONE';
|
||||
ReactGA.ga('set', 'dimension1', providerName);
|
||||
};
|
||||
analytics.init();
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
analytics.logProviderAsync((window as any).web3);
|
||||
const store: ReduxStore<State> = createStore(reducer);
|
||||
render(
|
||||
<Router>
|
||||
|
@ -463,4 +463,10 @@ export enum Deco {
|
||||
CapWords,
|
||||
Upper,
|
||||
}
|
||||
|
||||
export enum Providers {
|
||||
Parity = 'PARITY',
|
||||
Metamask = 'METAMASK',
|
||||
Mist = 'MIST',
|
||||
}
|
||||
// tslint:disable:max-file-line-count
|
||||
|
26
packages/website/ts/utils/analytics.ts
Normal file
26
packages/website/ts/utils/analytics.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as ReactGA from 'react-ga';
|
||||
import { configs } from 'ts/utils/configs';
|
||||
import { utils } from 'ts/utils/utils';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export const analytics = {
|
||||
init() {
|
||||
ReactGA.initialize(configs.GOOGLE_ANALYTICS_ID);
|
||||
},
|
||||
logEvent(category: string, action: string, label: string, value?: any) {
|
||||
ReactGA.event({
|
||||
category,
|
||||
action,
|
||||
label,
|
||||
value,
|
||||
});
|
||||
},
|
||||
async logProviderAsync(web3IfExists: Web3) {
|
||||
await utils.onPageLoadAsync();
|
||||
const providerType = !_.isUndefined(web3IfExists)
|
||||
? utils.getProviderType(web3IfExists.currentProvider)
|
||||
: 'NONE';
|
||||
ReactGA.ga('set', 'dimension1', providerType);
|
||||
},
|
||||
};
|
@ -62,6 +62,7 @@ export const configs = {
|
||||
TRST: '/images/token_icons/trust.png',
|
||||
} as { [symbol: string]: string },
|
||||
IS_MAINNET_ENABLED: true,
|
||||
GOOGLE_ANALYTICS_ID: 'UA-98720122-1',
|
||||
LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE: '2017-11-22',
|
||||
LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE: '2017-12-19',
|
||||
// NEW_WRAPPED_ETHERS is temporary until we remove the SHOULD_DEPRECATE_OLD_WETH_TOKEN flag
|
||||
|
@ -25,6 +25,7 @@ export const constants = {
|
||||
PROVIDER_NAME_LEDGER: 'Ledger',
|
||||
PROVIDER_NAME_METAMASK: 'Metamask',
|
||||
PROVIDER_NAME_PARITY_SIGNER: 'Parity Signer',
|
||||
PROVIDER_NAME_MIST: 'Mist',
|
||||
PROVIDER_NAME_GENERIC: 'Injected Web3',
|
||||
PROVIDER_NAME_PUBLIC: '0x Public',
|
||||
ROLLBAR_ACCESS_TOKEN: 'a6619002b51c4464928201e6ea94de65',
|
||||
|
@ -4,10 +4,11 @@ import { BigNumber } from '@0xproject/utils';
|
||||
import deepEqual = require('deep-equal');
|
||||
import * as _ from 'lodash';
|
||||
import * as moment from 'moment';
|
||||
import { Order, ScreenWidths, Side, SideToAssetToken, Token, TokenByAddress } from 'ts/types';
|
||||
import { Order, Providers, ScreenWidths, Side, SideToAssetToken, Token, TokenByAddress } from 'ts/types';
|
||||
import { configs } from 'ts/utils/configs';
|
||||
import { constants } from 'ts/utils/constants';
|
||||
import * as u2f from 'ts/vendor/u2f_api';
|
||||
import Web3 = require('web3');
|
||||
|
||||
const LG_MIN_EM = 64;
|
||||
const MD_MIN_EM = 52;
|
||||
@ -268,17 +269,6 @@ export const utils = {
|
||||
const baseUrl = `https://${window.location.hostname}${hasPort ? `:${port}` : ''}`;
|
||||
return baseUrl;
|
||||
},
|
||||
web3ProviderToString(provider: Web3Provider): string {
|
||||
let parsedProviderName = provider.constructor.name;
|
||||
if (provider.constructor.name === 'MetamaskInpageProvider') {
|
||||
parsedProviderName = 'METAMASK';
|
||||
} else if (provider.constructor.name === 'EthereumProvider') {
|
||||
parsedProviderName = 'MIST';
|
||||
} else if ((provider as any).isParity) {
|
||||
parsedProviderName = 'PARITY';
|
||||
}
|
||||
return parsedProviderName;
|
||||
},
|
||||
async onPageLoadAsync(): Promise<void> {
|
||||
if (document.readyState === 'complete') {
|
||||
return; // Already loaded
|
||||
@ -287,4 +277,25 @@ export const utils = {
|
||||
window.onload = () => resolve();
|
||||
});
|
||||
},
|
||||
getProviderType(provider: Web3.Provider): Providers | string {
|
||||
const constructorName = provider.constructor.name;
|
||||
let parsedProviderName = constructorName;
|
||||
switch (constructorName) {
|
||||
case 'MetamaskInpageProvider':
|
||||
parsedProviderName = Providers.Metamask;
|
||||
break;
|
||||
|
||||
case 'EthereumProvider':
|
||||
parsedProviderName = Providers.Mist;
|
||||
break;
|
||||
|
||||
default:
|
||||
parsedProviderName = constructorName;
|
||||
break;
|
||||
}
|
||||
if ((provider as any).isParity) {
|
||||
parsedProviderName = Providers.Parity;
|
||||
}
|
||||
return parsedProviderName;
|
||||
},
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user