diff --git a/src/lib/mixpanel/helpers.ts b/src/lib/mixpanel/helpers.ts index 2940a9cd99a..ad8402eec07 100644 --- a/src/lib/mixpanel/helpers.ts +++ b/src/lib/mixpanel/helpers.ts @@ -77,6 +77,32 @@ export const trackOpportunityEvent = ( mixpanel?.track(event, eventData) } +export type TrackYieldEventProps = { + provider: string + yieldType: string + yieldId: string + assetSymbol: string + network: string + amountCryptoPrecision: string + action: 'enter' | 'exit' | 'manage' +} + +export const trackYieldEvent = (event: MixPanelEvent, properties: TrackYieldEventProps) => { + const mixpanel = getMixPanel() + if (!mixpanel) return + + const eventData = { + provider: properties.provider, + yieldType: properties.yieldType, + yieldId: properties.yieldId, + asset: properties.assetSymbol, + network: properties.network, + amountCryptoPrecision: properties.amountCryptoPrecision, + action: properties.action, + } + mixpanel.track(event, eventData) +} + export const trackAppleSearchAdsAttribution = (data: AppleSearchAdsAttributionData) => { const mixpanel = getMixPanel() if (!mixpanel) return diff --git a/src/lib/mixpanel/types.ts b/src/lib/mixpanel/types.ts index 7fcb4dbccc6..622ae6ec8c6 100644 --- a/src/lib/mixpanel/types.ts +++ b/src/lib/mixpanel/types.ts @@ -76,6 +76,13 @@ export enum MixPanelEvent { HighlightedTokenClicked = 'Highlighted Token Clicked', FiveStarRating = 'Five Star Rating', AdAttributionReceived = 'Ad Attribution Received', + // Yield XYZ events + YieldEnterConfirm = 'Yield Enter Confirm', + YieldEnterSuccess = 'Yield Enter Success', + YieldExitConfirm = 'Yield Exit Confirm', + YieldExitSuccess = 'Yield Exit Success', + YieldClaimConfirm = 'Yield Claim Confirm', + YieldClaimSuccess = 'Yield Claim Success', } export type TrackOpportunityProps = { diff --git a/src/pages/Yields/hooks/useYieldTransactionFlow.ts b/src/pages/Yields/hooks/useYieldTransactionFlow.ts index 53321dfdd46..5378a79bdf2 100644 --- a/src/pages/Yields/hooks/useYieldTransactionFlow.ts +++ b/src/pages/Yields/hooks/useYieldTransactionFlow.ts @@ -20,6 +20,8 @@ import type { Hash } from 'viem' import { useFeatureFlag } from '@/hooks/useFeatureFlag/useFeatureFlag' import { useWallet } from '@/hooks/useWallet/useWallet' import { bnOrZero } from '@/lib/bignumber/bignumber' +import { trackYieldEvent } from '@/lib/mixpanel/helpers' +import { MixPanelEvent } from '@/lib/mixpanel/types' import { parseAndUpsertSecondClassChainTx } from '@/lib/utils/secondClassChainTx' import { enterYield, exitYield, fetchAction, manageYield } from '@/lib/yieldxyz/api' import { YIELD_MAX_POLL_ATTEMPTS, YIELD_POLL_INTERVAL_MS } from '@/lib/yieldxyz/constants' @@ -634,6 +636,30 @@ export const useYieldTransactionFlow = ({ address: userAddress, }) + // Track confirm event for the first non-approval transaction + const isApproval = isApprovalTransaction(tx) + const isFirstNonApprovalTx = + !isApproval && allTransactions.slice(0, yieldTxIndex).every(t => isApprovalTransaction(t)) + + if (isFirstNonApprovalTx) { + const confirmEvent = + action === 'enter' + ? MixPanelEvent.YieldEnterConfirm + : action === 'exit' + ? MixPanelEvent.YieldExitConfirm + : MixPanelEvent.YieldClaimConfirm + + trackYieldEvent(confirmEvent, { + provider: yieldItem.providerId, + yieldType: yieldItem.mechanics.type, + yieldId: yieldItem.id, + assetSymbol, + network: yieldItem.network, + amountCryptoPrecision: amount, + action, + }) + } + const isLastTransaction = yieldTxIndex + 1 >= allTransactions.length const completeLastYieldTransaction = async () => { @@ -734,6 +760,25 @@ export const useYieldTransactionFlow = ({ updateStepStatus(uiStepIndex, { status: 'success', loadingMessage: undefined }) queryClient.removeQueries({ queryKey: ['yieldxyz', 'quote'] }) + + // Track success event + const successEvent = + action === 'enter' + ? MixPanelEvent.YieldEnterSuccess + : action === 'exit' + ? MixPanelEvent.YieldExitSuccess + : MixPanelEvent.YieldClaimSuccess + + trackYieldEvent(successEvent, { + provider: yieldItem.providerId, + yieldType: yieldItem.mechanics.type, + yieldId: yieldItem.id, + assetSymbol, + network: yieldItem.network, + amountCryptoPrecision: amount, + action, + }) + setStep(ModalStep.Success) } @@ -790,6 +835,7 @@ export const useYieldTransactionFlow = ({ yieldItem, action, amount, + assetSymbol, toast, translate, updateStepStatus, @@ -891,6 +937,25 @@ export const useYieldTransactionFlow = ({ const transactions = filterExecutableTransactions(quoteData.transactions) if (transactions.length === 0) { + // Track success event for already-completed flows + if (yieldItem) { + const successEvent = + action === 'enter' + ? MixPanelEvent.YieldEnterSuccess + : action === 'exit' + ? MixPanelEvent.YieldExitSuccess + : MixPanelEvent.YieldClaimSuccess + + trackYieldEvent(successEvent, { + provider: yieldItem.providerId, + yieldType: yieldItem.mechanics.type, + yieldId: yieldItem.id, + assetSymbol, + network: yieldItem.network, + amountCryptoPrecision: amount, + action, + }) + } setStep(ModalStep.Success) setIsSubmitting(false) return @@ -955,12 +1020,13 @@ export const useYieldTransactionFlow = ({ accountId, action, amount, + assetSymbol, quoteError, quoteData, resolveSymbolForTx, translate, showErrorToast, - yieldItem?.mechanics.type, + yieldItem, ]) const isAmountLocked = useMemo(