From 59692766b007294baedc450ef9643c46cf077a58 Mon Sep 17 00:00:00 2001 From: rickykuo666 Date: Tue, 6 Aug 2024 17:45:35 +0100 Subject: [PATCH 1/5] add google analytics --- components/AccountBody.tsx | 41 +++++++++++++--- components/LoginModal.tsx | 10 +++- components/SuccessModal.tsx | 20 +++++++- .../operationModals/ChangeBaker/index.tsx | 2 + .../operationModals/Delegate/BakerBox.tsx | 5 ++ .../operationModals/Delegate/ConfirmBaker.tsx | 18 ++++++- .../Delegate/DelegateStart.tsx | 10 +++- components/operationModals/Delegate/index.tsx | 5 ++ .../EndDelegate/ConfirmEndDelegate.tsx | 2 + .../ConfirmFinalizeUnstake.tsx | 2 + .../FinalizeUnstake/UnstakeOperationBox.tsx | 8 +++- .../operationModals/Stake/SelectAmount.tsx | 9 +++- .../operationModals/Stake/StakeStart.tsx | 14 +++++- .../operationModals/Unstake/SelectAmount.tsx | 4 ++ .../operationModals/Unstake/UnstakeStart.tsx | 10 +++- pages/_document.tsx | 17 +++++++ providers/ConnectionProvider/index.tsx | 4 ++ providers/OperationResponseProvider/index.tsx | 16 ++++++- utils/trackGAEvent.ts | 47 +++++++++++++++++++ 19 files changed, 226 insertions(+), 18 deletions(-) create mode 100644 utils/trackGAEvent.ts diff --git a/components/AccountBody.tsx b/components/AccountBody.tsx index 59c4780..ff506d2 100644 --- a/components/AccountBody.tsx +++ b/components/AccountBody.tsx @@ -38,6 +38,7 @@ import { CopyAlert } from './CopyAlert' import { ExpandBakerInfoTable } from './ExpandBakerInfoTable' import _ from 'lodash' import { DisabledStakeAlert } from '@/components/DisabledStakeAlert' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' const getNumOfUnstake = ( unstOps?: UnstakedOperation[], @@ -75,7 +76,8 @@ export const AccountBody = ({ title, message, opHash, - resetOperation + resetOperation, + opType } = useOperationResponse() const { @@ -160,6 +162,7 @@ export const AccountBody = ({ desc={message} tzktLink={`${process.env.NEXT_PUBLIC_TZKT_UI_URL}/${opHash}`} resetOperation={resetOperation} + opType={opType} /> )} { + trackGAEvent( + GAAction.BUTTON_CLICK, + GACategory.END_DELEGATE_BEGIN + ) endDelegateModal.onOpen() }} /> @@ -249,7 +256,15 @@ export const AccountBody = ({ {accountInfo?.type === 'user' && (stakingOpsStatus.Delegated ? ( - changeBakerModal.onOpen()} /> + { + trackGAEvent( + GAAction.BUTTON_CLICK, + GACategory.CHOOSE_CHANGE_BAKER + ) + changeBakerModal.onOpen() + }} + /> ) : ( ))} @@ -263,9 +278,9 @@ export const AccountBody = ({ fontWeight={600} lineHeight='18px' > - {accountInfo?.evaluatedDelegate.alias ?? + {accountInfo?.evaluatedDelegate?.alias ?? simplifyAddress( - accountInfo?.evaluatedDelegate.address ?? '' + accountInfo?.evaluatedDelegate?.address ?? '' )} delegateModal.onOpen()} + onClick={() => { + trackGAEvent( + GAAction.BUTTON_CLICK, + GACategory.CHOOSE_BAKER_START + ) + delegateModal.onOpen() + }} w='100%' > Select Baker @@ -322,7 +343,10 @@ export const AccountBody = ({ disabled={ stakingOpsStatus.Delegated && !stakingOpsStatus.CanUnstake } - onClick={() => unstakeModal.onOpen()} + onClick={() => { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.CHOOSE_UNSTAKE) + unstakeModal.onOpen() + }} w='100%' > Unstake @@ -332,7 +356,10 @@ export const AccountBody = ({ {stakingOpsStatus.Delegated && ( stakeModal.onOpen()} + onClick={() => { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.CHOOSE_STAKE) + stakeModal.onOpen() + }} w='100%' > Stake diff --git a/components/LoginModal.tsx b/components/LoginModal.tsx index a84bfeb..37e511a 100644 --- a/components/LoginModal.tsx +++ b/components/LoginModal.tsx @@ -3,6 +3,7 @@ import { Box, Flex, Image, Text, FlexProps } from '@chakra-ui/react' import Link from 'next/link' import { PrimaryButton } from './buttons/PrimaryButton' import { useConnection } from '@/providers/ConnectionProvider' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' const STEPS = ['DELEGATE', 'STAKE TEZ', 'EARN TEZ'] @@ -46,7 +47,14 @@ export const LoginModal = () => { ))} - + { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.WALLET_BEGIN) + connect() + }} + > Connect Wallet diff --git a/components/SuccessModal.tsx b/components/SuccessModal.tsx index 193486e..2ebfc24 100644 --- a/components/SuccessModal.tsx +++ b/components/SuccessModal.tsx @@ -14,19 +14,36 @@ import { import { PrimaryButton } from './buttons/PrimaryButton' import Link from 'next/link' import { ExternalLinkIcon } from '@chakra-ui/icons' +import { OpType } from '@/providers/OperationResponseProvider' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' + +const setGAEvent = (opType?: OpType) => { + switch (opType) { + case 'delegate': + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.CONTINUE_AFTER_DELEGATION) + return + case 'stake': + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.CONTINUE_AFTER_STAKE) + return + default: + return + } +} export const SuccessModal = ({ title, desc, tzktLink, resetOperation, - open + open, + opType }: { title?: string desc: string tzktLink: string resetOperation: () => void open: boolean + opType?: OpType }) => { const { onClose } = useDisclosure() @@ -69,6 +86,7 @@ export const SuccessModal = ({ { + setGAEvent(opType) resetOperation() onClose() }} diff --git a/components/operationModals/ChangeBaker/index.tsx b/components/operationModals/ChangeBaker/index.tsx index ef865d0..774c5f9 100644 --- a/components/operationModals/ChangeBaker/index.tsx +++ b/components/operationModals/ChangeBaker/index.tsx @@ -68,6 +68,7 @@ export const ChangeBakerModal = ({ handleOneStepBack={handleOneStepBack} selectedBaker={selectedBaker as BakerInfo} setSelectedBaker={setSelectedBaker} + isChangeBaker={true} /> ) default: @@ -92,6 +93,7 @@ export const ChangeBakerModal = ({ handleOneStepBack={handleOneStepBack} selectedBaker={selectedBaker as BakerInfo} setSelectedBaker={setSelectedBaker} + isChangeBaker={true} /> ) default: diff --git a/components/operationModals/Delegate/BakerBox.tsx b/components/operationModals/Delegate/BakerBox.tsx index 1ff98ab..bbba9c1 100644 --- a/components/operationModals/Delegate/BakerBox.tsx +++ b/components/operationModals/Delegate/BakerBox.tsx @@ -6,6 +6,7 @@ import useClipboard from '@/utils/useClipboard' import { CopyAlert } from '@/components/CopyAlert' import { BakerInfo } from '@/components/Operations/tezInterfaces' import { mutezToTez } from '@/utils/mutezToTez' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' interface BakerBoxProps { baker: BakerInfo @@ -57,6 +58,10 @@ export const BakerBox = ({ { + trackGAEvent( + GAAction.BUTTON_CLICK, + GACategory.CHOOSE_BAKER_SUCCESS + ) setSelectedBaker(baker) handleOneStepForward() }} diff --git a/components/operationModals/Delegate/ConfirmBaker.tsx b/components/operationModals/Delegate/ConfirmBaker.tsx index 169fcab..adde104 100644 --- a/components/operationModals/Delegate/ConfirmBaker.tsx +++ b/components/operationModals/Delegate/ConfirmBaker.tsx @@ -19,22 +19,26 @@ import { useConnection } from '@/providers/ConnectionProvider' import { setDelegate } from '@/components/Operations/operations' import { PrimaryButton } from '@/components/buttons/PrimaryButton' import { ErrorBlock } from '@/components/ErrorBlock' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' interface ChooseBakerProps { handleOneStepForward: () => void handleOneStepBack: () => void selectedBaker: BakerInfo setSelectedBaker: (b: null) => void + isChangeBaker?: boolean } export const ConfirmBaker = ({ handleOneStepForward, handleOneStepBack, selectedBaker, - setSelectedBaker + setSelectedBaker, + isChangeBaker }: ChooseBakerProps) => { const { Tezos, beaconWallet } = useConnection() - const { setMessage, setSuccess, setOpHash } = useOperationResponse() + const { setMessage, setSuccess, setOpHash, setOpType } = + useOperationResponse() const [errorMessage, setErrorMessage] = useState('') const [waitingOperation, setWaitingOperation] = useState(false) @@ -99,6 +103,7 @@ export const ConfirmBaker = ({ { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.START_DELEGATE_BEGIN) if (!Tezos || !beaconWallet) { setErrorMessage('Wallet is not initialized, log out to try again.') return @@ -116,7 +121,16 @@ export const ConfirmBaker = ({ ) setWaitingOperation(false) if (response.success) { + if (isChangeBaker) + trackGAEvent( + GAAction.BUTTON_CLICK, + GACategory.CHANGE_BAKER_SUCCESS + ) + else + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.START_DELEGATE_END) + setOpHash(response.opHash) + setOpType('delegate') setMessage( 'You have successfully delegated your balance to the baker. You can now (optionally) stake funds with the baker, and potentially earn higher rewards.' ) diff --git a/components/operationModals/Delegate/DelegateStart.tsx b/components/operationModals/Delegate/DelegateStart.tsx index 7e65b95..bd68d47 100644 --- a/components/operationModals/Delegate/DelegateStart.tsx +++ b/components/operationModals/Delegate/DelegateStart.tsx @@ -2,6 +2,7 @@ import React from 'react' import { Image, Box, Flex, Text } from '@chakra-ui/react' import { PrimaryButton } from '@/components/buttons/PrimaryButton' import { Header, Description } from '@/components/modalBody' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' export const DelegateStart = ({ handleOneStepForward @@ -25,7 +26,14 @@ export const DelegateStart = ({ - Continue + { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.CONTINUE_DELEGATION) + handleOneStepForward() + }} + > + Continue + ) } diff --git a/components/operationModals/Delegate/index.tsx b/components/operationModals/Delegate/index.tsx index b8a76c2..8406ca4 100644 --- a/components/operationModals/Delegate/index.tsx +++ b/components/operationModals/Delegate/index.tsx @@ -14,6 +14,7 @@ import useCurrentStep from '@/utils/useCurrentStep' import { Stepper } from '@/components/modalBody/Stepper' import { BackIcon, CloseIcon } from '@/components/icons' import { ConfirmBaker } from './ConfirmBaker' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' export interface DelegateModalProps { isOpen: boolean @@ -99,6 +100,10 @@ export const DelegationModal = ({ /> { + trackGAEvent( + GAAction.BUTTON_CLICK, + GACategory.CHOOSE_BAKER_CLOSED + ) closeReset() onClose() }} diff --git a/components/operationModals/EndDelegate/ConfirmEndDelegate.tsx b/components/operationModals/EndDelegate/ConfirmEndDelegate.tsx index 6c8c7a1..5070fb2 100644 --- a/components/operationModals/EndDelegate/ConfirmEndDelegate.tsx +++ b/components/operationModals/EndDelegate/ConfirmEndDelegate.tsx @@ -6,6 +6,7 @@ import { useConnection } from '@/providers/ConnectionProvider' import { AddressBox, Header, ColumnHeader } from '@/components/modalBody' import { useOperationResponse } from '@/providers/OperationResponseProvider' import { ErrorBlock } from '@/components/ErrorBlock' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' interface ConfirmEndDelegate { spendableBalance: number @@ -39,6 +40,7 @@ export const ConfirmEndDelegate = ({ const response = await setDelegate(Tezos, undefined, beaconWallet) setWaitingOperation(false) if (response.success) { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.END_DELEGATE_END) setOpHash(response.opHash) setTitle('Delegation Ended!') setMessage( diff --git a/components/operationModals/FinalizeUnstake/ConfirmFinalizeUnstake.tsx b/components/operationModals/FinalizeUnstake/ConfirmFinalizeUnstake.tsx index 3f09326..652b1b9 100644 --- a/components/operationModals/FinalizeUnstake/ConfirmFinalizeUnstake.tsx +++ b/components/operationModals/FinalizeUnstake/ConfirmFinalizeUnstake.tsx @@ -6,6 +6,7 @@ import { useConnection } from '@/providers/ConnectionProvider' import { Header, BalanceBox, ColumnHeader } from '@/components/modalBody' import { useOperationResponse } from '@/providers/OperationResponseProvider' import { ErrorBlock } from '@/components/ErrorBlock' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' interface ConfirmFinalizeUnstake { withdrawAmount: number @@ -42,6 +43,7 @@ export const ConfirmFinalizeUnstake = ({ setWaitingOperation(false) if (response.success) { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.FINALIZE_END) setOpHash(response.opHash) setMessage( `You have successfully finalized ${withdrawAmount} ꜩ. These funds are now part of your spendable balance.` diff --git a/components/operationModals/FinalizeUnstake/UnstakeOperationBox.tsx b/components/operationModals/FinalizeUnstake/UnstakeOperationBox.tsx index 4b447e7..4773188 100644 --- a/components/operationModals/FinalizeUnstake/UnstakeOperationBox.tsx +++ b/components/operationModals/FinalizeUnstake/UnstakeOperationBox.tsx @@ -5,6 +5,7 @@ import { mutezToTez } from '@/utils/mutezToTez' import { TertiaryButton } from '@/components/buttons/TertiaryButton' import { FinalizeUnstakeModal } from '.' import Link from 'next/link' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' export const UnstakeOperationBox = ({ unstakeOp, @@ -101,7 +102,12 @@ export const UnstakeOperationBox = ({ )} {canFinalize && ( - finalizeUnstakeModal.onOpen()}> + { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.FINALIZE_BEGIN) + finalizeUnstakeModal.onOpen() + }} + > Finalize )} diff --git a/components/operationModals/Stake/SelectAmount.tsx b/components/operationModals/Stake/SelectAmount.tsx index d78ac84..116a74d 100644 --- a/components/operationModals/Stake/SelectAmount.tsx +++ b/components/operationModals/Stake/SelectAmount.tsx @@ -6,6 +6,7 @@ import { stake } from '@/components/Operations/operations' import { useConnection } from '@/providers/ConnectionProvider' import { useOperationResponse } from '@/providers/OperationResponseProvider' import { ErrorBlock } from '@/components/ErrorBlock' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' export const SelectAmount = ({ spendableBalance, @@ -19,12 +20,14 @@ export const SelectAmount = ({ stakedAmount: number }) => { const { Tezos, beaconWallet } = useConnection() - const { setMessage, setSuccess, setOpHash } = useOperationResponse() + const { setMessage, setSuccess, setOpHash, setOpType } = + useOperationResponse() const [errorMessage, setErrorMessage] = useState('') const [waitingOperation, setWaitingOperation] = useState(false) const handleChange = (event: any) => { const val = Number(event.target.value) + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.INPUT_AMOUNT) if (val <= spendableBalance) setStakedAmount(val) else if (val === 0) setStakedAmount(0) @@ -67,12 +70,16 @@ export const SelectAmount = ({ return } + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.START_STAKE_BEGIN) + setWaitingOperation(true) const response = await stake(Tezos, stakedAmount, beaconWallet) setWaitingOperation(false) if (response.success) { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.START_STAKE_END) setOpHash(response.opHash) + setOpType('stake') setMessage(`You have successfully staked ${stakedAmount} ꜩ`) setSuccess(true) setStakedAmount(0) diff --git a/components/operationModals/Stake/StakeStart.tsx b/components/operationModals/Stake/StakeStart.tsx index 542bb04..5fa630e 100644 --- a/components/operationModals/Stake/StakeStart.tsx +++ b/components/operationModals/Stake/StakeStart.tsx @@ -2,6 +2,7 @@ import React, { useState } from 'react' import { Flex, Text, Checkbox, Image } from '@chakra-ui/react' import { Header, Description } from '@/components/modalBody' import { PrimaryButton } from '@/components/buttons/PrimaryButton' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' export const StakeStart = ({ handleOneStepForward @@ -34,7 +35,10 @@ export const StakeStart = ({ > setIsChecked(!isChecked)} + onChange={() => { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.ACCEPT_DISCLAIMER) + setIsChecked(!isChecked) + }} /> - + { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.CONTINUE_STAKE) + handleOneStepForward() + }} + > Continue diff --git a/components/operationModals/Unstake/SelectAmount.tsx b/components/operationModals/Unstake/SelectAmount.tsx index 4c16fea..234d928 100644 --- a/components/operationModals/Unstake/SelectAmount.tsx +++ b/components/operationModals/Unstake/SelectAmount.tsx @@ -13,6 +13,7 @@ import { unstake } from '@/components/Operations/operations' import { useConnection } from '@/providers/ConnectionProvider' import { useOperationResponse } from '@/providers/OperationResponseProvider' import { ErrorBlock } from '@/components/ErrorBlock' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' export const SelectAmount = ({ stakedAmount, @@ -84,11 +85,14 @@ export const SelectAmount = ({ return } + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.END_STAKE_BEGIN) + setWaitingOperation(true) const response = await unstake(Tezos, unstakeAmount, beaconWallet) setWaitingOperation(false) if (response.success) { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.END_STAKE_END) setOpHash(response.opHash) setTitle('Unstake Requested') setMessage( diff --git a/components/operationModals/Unstake/UnstakeStart.tsx b/components/operationModals/Unstake/UnstakeStart.tsx index 260a71a..99b1c17 100644 --- a/components/operationModals/Unstake/UnstakeStart.tsx +++ b/components/operationModals/Unstake/UnstakeStart.tsx @@ -3,6 +3,7 @@ import { Flex, Image } from '@chakra-ui/react' import { Header, Description } from '@/components/modalBody' import { PrimaryButton } from '@/components/buttons/PrimaryButton' import { RoundBorderText } from '../Delegate/DelegateStart' +import { trackGAEvent, GAAction, GACategory } from '@/utils/trackGAEvent' export const UnstakeStart = ({ handleOneStepForward @@ -22,7 +23,14 @@ export const UnstakeStart = ({ - I Understand + { + trackGAEvent(GAAction.BUTTON_CLICK, GACategory.CHOOSE_I_UNDERSTAND) + handleOneStepForward() + }} + > + I Understand + ) } diff --git a/pages/_document.tsx b/pages/_document.tsx index 23d501c..3ee0325 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -1,10 +1,27 @@ import { Html, Head, Main, NextScript } from 'next/document' +import Script from 'next/script' export default function Document() { return ( +