Skip to content

Commit

Permalink
[Wallet] Analytics Retooling + Analytics for Send & Request (#4041)
Browse files Browse the repository at this point in the history
### Description
Created ability to add event properties for subEvent tracking and exposed those methods to the component used in the wallet.

Added analytics for the 2nd half of the Send flow (Ivan already did the first half), Secure Send, and the Request Payment flow.

### Other changes
Minor cleanup of dead code.

### Tested
No new tests added.

### Related issues
#3645 & #4008 

### Backwards compatibility
Yes
  • Loading branch information
tarikbellamine committed Jun 11, 2020
1 parent ba34d70 commit f9b029b
Show file tree
Hide file tree
Showing 22 changed files with 431 additions and 258 deletions.
1 change: 1 addition & 0 deletions packages/mobile/__mocks__/react-native-reanimated.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('react-native-reanimated/mock')
2 changes: 1 addition & 1 deletion packages/mobile/src/account/Education.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class Education extends React.Component<Props, State> {

return (
<View style={style.body}>
{/*
{/*
// @ts-ignore */}
<Swiper
onIndexChanged={this.setStep}
Expand Down
31 changes: 28 additions & 3 deletions packages/mobile/src/analytics/CeloAnalytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import CeloAnalytics, { AnalyzedApps } from '@celo/react-components/analytics/Ce
import {
CustomEventNames,
DefaultEventNames,
PROPERTY_PATH_WHITELIST,
EventPropertyType,
PropertyPathWhitelist,
} from 'src/analytics/constants'
import { DEFAULT_TESTNET, SEGMENT_API_KEY } from 'src/config'
import { store } from 'src/redux/store'
Expand All @@ -12,17 +13,41 @@ type EventNames = CustomEventNames | DefaultEventNames

class WalletAnalytics extends CeloAnalytics {
constructor() {
super(AnalyzedApps.Wallet, PROPERTY_PATH_WHITELIST, Logger, SEGMENT_API_KEY, DEFAULT_TESTNET)
super(AnalyzedApps.Wallet, PropertyPathWhitelist, Logger, SEGMENT_API_KEY, DEFAULT_TESTNET)
}

isEnabled() {
// Remove __DEV__ here to test analytics in dev builds
return !__DEV__ && store.getState().app.analyticsEnabled
}

track(eventName: EventNames, eventProperties: object = {}, attachDeviceInfo: boolean = false) {
track(
eventName: EventNames,
eventProperties: EventPropertyType = {},
attachDeviceInfo: boolean = false
) {
super.track(eventName, eventProperties, attachDeviceInfo)
}

startTracking(eventName: EventNames, eventProperties: EventPropertyType = {}) {
super.startTracking(eventName, eventProperties)
}

trackSubEvent(
eventName: EventNames,
subEventName: EventNames,
eventProperties: EventPropertyType = {}
) {
super.trackSubEvent(eventName, subEventName, eventProperties)
}

stopTracking(
eventName: EventNames,
eventProperties: EventPropertyType = {},
attachDeviceInfo: boolean = false
) {
super.stopTracking(eventName, eventProperties, attachDeviceInfo)
}
}

export default new WalletAnalytics()
204 changes: 114 additions & 90 deletions packages/mobile/src/analytics/constants.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { DefaultEventNames } from '@celo/react-components/analytics/constants'

export enum CustomEventNames {
// Onboarding
language_select = 'language_select',
nux_continue = 'nux_continue',
full_name_input = 'full_name_input',
invitation_code = 'invitation_code',
signup_submit = 'signup_submit',
import_contacts = 'import_contacts',
import_contacts_skip = 'import_contacts_skip',
blockChainCorruption = 'block_chain_corruption',
disconnect_banner = 'disconnect_banner',

// Education
gold_cancel1 = 'gold_cancel1',
Expand All @@ -24,41 +23,64 @@ export enum CustomEventNames {
dollar_cancel3 = 'dollar_cancel3',
send_dollar_nux = 'send_dollar_nux',
wallet_dollar_nux = 'wallet_dollar_nux',
send_input = 'send_input',
transaction_details = 'transaction_details',

// Payment send
send_input = 'send_input',
send_select_cancel = 'send_select_cancel',
send_dollar_confirm = 'send_dollar_confirm',
edit_dollar_confirm = 'edit_dollar_confirm',
send_invite_details = 'send_invite_details',
send_invite = 'send_invite',
edit_send_invite = 'edit_send_invite',

send_cancel = 'send_cancel', // when cancel is clicked after launching send flow
send_search = 'send_search', // when text is input into search bar
send_scan = 'send_scan', // when scan QR icon is selected from the send screen
send_select_recipient = 'send_select_recipient', // when recipient was selected
send_amount_back = 'send_amount_back', // back button pressed on amount screen
send_continue = 'send_continue', // when next button pressed on amount enter page
send_confirm_back = 'send_confirm_back', // when back button pressed on send confirmation screen
send_confirm = 'send_confirm', // when send button pressed on send confirmation screen
send_error = 'send_error', // when there is an error sending a transaction
send_complete = 'send_complete', // when a send or invite transaction has successfully completed

// Send events, separate from button tracking above
send_dollar_transaction = 'send_dollar_transaction',
send_dollar_transaction_confirmed = 'send_dollar_transaction_confirmed',
send_secure_start = 'send_secure_start', // when either secure send scan or manual confirm button pressed
send_secure_cancel = 'send_secure_cancel', // when secure send flow is canceled
send_secure_back = 'send_secure_back', // when back button is pressed during secure send
send_secure_submit = 'send_secure_submit', // when an account is submitted for validation
send_secure_success = 'send_secure_success', // when an account has been validated
send_secure_incorrect = 'send_secure_incorrect', // when there's been an error validating the account
send_secure_info = 'send_secure_info', // when "help" button is pressed
send_secure_info_dismissed = 'send_secure_info_dismissed', // when "help" button is dismissed
send_secure_edit = 'send_secure_edit', // when "edit" address button is pressed to manually initate secure send flow

invite_error = 'invite_error', // when there is an error sending an invite

// Payment requests
// Payment request
request_cancel = 'request_cancel', // when cancel is clicked after launching request flow
request_search = 'request_search', // when text is input into search bar
request_scan = 'request_scan', // when scan QR icon is selected from the request screen
request_select_recipient = 'request_select_recipient', // when recipient was selected
request_amount_back = 'request_amount_back', // back button pressed on amount screen
request_continue = 'request_continue', // when next button pressed on amount enter page
request_unavailable = 'request_unavailable', // when request attempted to unverified user
request_payment_request = 'incoming_request_payment_request',
request_payment_edit = 'incoming_request_payment_edit',
request_confirm_back = 'request_confirm_back', // when back button pressed on request confirmation screen
request_confirm = 'request_confirm', // when request button pressed on request confirmation screen
request_error = 'request_error', // when there is an error requesting a transaction

incoming_request_payment_decline = 'incoming_request_payment_decline',
incoming_request_payment_pay = 'incoming_request_payment_pay',
incoming_request_payment_review = 'incoming_request_payment_review',

outgoing_request_payment_review = 'outgoing_request_payment_review',
outgoing_request_payment_remind = 'outgoing_request_payment_remind',
outgoing_request_payment_cancel = 'outgoing_request_payment_cancel',

// Send events, separate from button tracking above
send_dollar_transaction = 'send_dollar_transaction',
send_dollar_transaction_confirmed = 'send_dollar_transaction_confirmed',

fetch_balance = 'fetch_balance',

// Verification event and sub-events
verification_start = 'verification_start',
verification_setup = 'verification_setup',
Expand All @@ -77,25 +99,24 @@ export enum CustomEventNames {
verification_cancelled = 'verification_cancelled',
verification_success = 'verification_success',
verification_timed_out = 'verification_timed_out',

verification_actionable_attestation_start = 'verification_actionable_attestation_start',
verification_actionable_attestation_finish = 'verification_actionable_attestation_finish',
verification_validate_code_start = 'verification_validate_code_start',
verification_validate_code_finish = 'verification_validate_code_finish',

// PGPNP
phone_number_quota_purchase_success = 'phone_number_quota_purchase_success',
phone_number_quota_purchase_failure = 'phone_number_quota_purchase_failure',
phone_number_quota_purchase_skip = 'phone_number_quota_purchase_skip',

// Invite
redeem_invite_success = 'redeem_invite_success',
redeem_invite_timed_out = 'redeem_invite_timed_out',
redeem_invite_failed = 'redeem_invite_failed',
send_invite_details = 'send_invite_details',
send_invite = 'send_invite',
edit_send_invite = 'edit_send_invite',

// Pin
photos_education = 'photos_education',
get_backup_key = 'get_backup_key',
earn_celo_gold = 'earn_celo_gold',
user_restart = 'user_restart',
pin_continue = 'pin_continue',
pin_wallet_import = 'pin_wallet_import',
pin_value = 'pin_value',
Expand All @@ -111,11 +132,11 @@ export enum CustomEventNames {
invite_friends_sms = 'invite_friends_sms', // to count the # of taps on “Invite with SMS" button on Invite_Friends_Review
invite_friends_whatsapp = 'invite_friends_whatsapp', // to count the # of taps on “Invite with WhatsApp" button on Invite_Friends_Review

// Backup Key
get_backup_key = 'get_backup_key',
backup_start = 'backup_start', // ‘set up now’ button click
backup_setup_info = 'backup_setup_info',

backup_quiz_backspace = 'backup_quiz_backspace', // whenever the backspace is pressed

backup_quiz_submit = 'backup_quiz_submit', // (Count # of taps on "Submit" button in Backup_Quiz)
backup_quiz_success = 'backup_quiz_success', // (Count # of successful Account Key confirmations Backup_Quiz)
backup_quiz_incorrect = 'backup_quiz_incorrect', // (Count # of failed Account Key confirmations Backup_Quiz)
Expand Down Expand Up @@ -198,6 +219,8 @@ export enum CustomEventNames {
import_phrase_input = 'import_phrase_input', // to record the # of times a value is inputted here [we should not track the actual value of this field, just whether the user filled it out]
import_wallet_submit = 'import_wallet_submit', // to count the # of times that the “Restore Celo Wallet” button is pressed
import_wallet_cancel = 'import_wallet_cancel', // to count the # of times that the “Cancel” button is pressed
import_contacts = 'import_contacts',
import_contacts_skip = 'import_contacts_skip',

// Escrowed payments
escrowed_payment_review = 'escrowed_payment_review',
Expand All @@ -223,13 +246,6 @@ export enum CustomEventNames {
transaction_send_gas_estimated = 'transaction_send_gas_estimated',
transaction_send_gas_hash_received = 'transaction_send_gas_hash_received',
transaction_send_gas_receipt = 'transaction_send_gas_receipt',

// Misc
fetch_balance = 'fetch_balance',

// Errors
user_restart = 'user_restart',
blockChainCorruption = 'block_chain_corruption',
}

export enum CommonValues {
Expand All @@ -239,68 +255,76 @@ export enum CommonValues {
timeout = 'timeout',
}

export type EventPropertyType = {
[key in PropertyPathWhitelist]?: any
}

// TODO(nitya): separate this out by event name
export const PROPERTY_PATH_WHITELIST = [
'address',
'component',
'countryCode',
'cta',
'currentScreen',
'didQuery',
'dollarAmount',
'dollarBalance',
'dollarPendingBalance',
'error',
'exchangeInputAmount',
'exchangeRate',
'fullName',
'goldAmount',
'goldBalance',
'goldPendingBalance',
'goldToDollarExchangeRate',
'inputToken',
'inviteCode',
'isCorrect',
'issuer',
'label',
'language',
'localCurrency',
'localCurrencyAmount',
'localCurrencyExchangeRate',
'makerAmount',
'makerToken',
'makerTokenAmount',
'method',
'name',
'navigation.state.key',
'navigation.state.routeName',
'nextScreen',
'note',
'phoneNumber',
'previousScreen',
'query',
'recipientAddress',
'recipientKind',
'requesteeAddress',
'requestIndex',
'rootTag',
'routeName',
'screen',
'selectedAnswer',
'selectedRecipientAddress',
'selectedRecipientPhoneNumber',
'sendAmount',
'subtitle',
'success',
'syncProgress',
'takerAmount',
'testnet',
'timeElapsed',
'title',
'to',
'tti',
'txId',
'verificationIndex',
'verificationsRemaining',
]
export enum PropertyPathWhitelist {
address = 'address',
component = 'component',
context = 'context',
countryCode = 'countryCode',
cta = 'cta',
currentScreen = 'currentScreen',
didQuery = 'didQuery',
dollarAmount = 'dollarAmount',
dollarBalance = 'dollarBalance',
dollarPendingBalance = 'dollarPendingBalance',
error = 'error',
exchangeInputAmount = 'exchangeInputAmount',
exchangeRate = 'exchangeRate',
fullName = 'fullName',
goldAmount = 'goldAmount',
goldBalance = 'goldBalance',
goldPendingBalance = 'goldPendingBalance',
goldToDollarExchangeRate = 'goldToDollarExchangeRate',
inputToken = 'inputToken',
inviteCode = 'inviteCode',
isCorrect = 'isCorrect',
isInvite = 'isInvite',
issuer = 'issuer',
label = 'label',
language = 'language',
localCurrency = 'localCurrency',
localCurrencyAmount = 'localCurrencyAmount',
localCurrencyExchangeRate = 'localCurrencyExchangeRate',
makerAmount = 'makerAmount',
makerToken = 'makerToken',
makerTokenAmount = 'makerTokenAmount',
method = 'method',
name = 'name',
'navigation.state.key' = 'navigation.state.key',
'navigation.state.routeName' = 'navigation.state.routeName',
nextScreen = 'nextScreen',
note = 'note',
phoneNumber = 'phoneNumber',
previousScreen = 'previousScreen',
query = 'query',
recipientAddress = 'recipientAddress',
recipientKind = 'recipientKind',
requesteeAddress = 'requesteeAddress',
requestIndex = 'requestIndex',
rootTag = 'rootTag',
routeName = 'routeName',
screen = 'screen',
selectedAnswer = 'selectedAnswer',
selectedRecipientAddress = 'selectedRecipientAddress',
selectedRecipientPhoneNumber = 'selectedRecipientPhoneNumber',
sendAmount = 'sendAmount',
subtitle = 'subtitle',
success = 'success',
syncProgress = 'syncProgress',
takerAmount = 'takerAmount',
testnet = 'testnet',
timeElapsed = 'timeElapsed',
title = 'title',
to = 'to',
tti = 'tti',
txId = 'txId',
validationType = 'validationType',
verificationIndex = 'verificationIndex',
verificationsRemaining = 'verificationsRemaining',
}

export { DefaultEventNames }
2 changes: 1 addition & 1 deletion packages/mobile/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental

export class App extends React.Component {
async componentDidMount() {
CeloAnalytics.track(DefaultEventNames.appLoaded, this.props, true)
CeloAnalytics.track(DefaultEventNames.appLoaded, {}, true)
const appLoadedAt: Date = new Date()
const appStartListener = DeviceEventEmitter.addListener(
'AppStartedLoading',
Expand Down
4 changes: 2 additions & 2 deletions packages/mobile/src/exchange/saga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export function* doFetchExchangeRate(action: FetchExchangeRateAction) {

Logger.debug(
TAG,
`Retrieved exchange rate:
`Retrieved exchange rate:
${dollarMakerExchangeRate.toString()} gold per dollar, estimated at ${dollarMakerAmount}
${goldMakerExchangeRate.toString()} dollar per gold, estimated at ${goldMakerAmount}`
)
Expand Down Expand Up @@ -229,7 +229,7 @@ export function* exchangeGoldAndStableTokens(action: ExchangeTokensAction) {
)
Logger.debug(
TAG,
`Will receive at least ${convertedTakerAmount}
`Will receive at least ${convertedTakerAmount}
wei for ${convertedMakerAmount} wei of ${makerToken}`
)

Expand Down
Loading

0 comments on commit f9b029b

Please sign in to comment.