diff --git a/src/analytics/event.ts b/src/analytics/event.ts
index b45a6307dd..818c70de5b 100644
--- a/src/analytics/event.ts
+++ b/src/analytics/event.ts
@@ -139,6 +139,33 @@ export const event = {
* Called when a keyboard shortcut is triggered
*/
keyboardShortcutTriggered: 'keyboard.shortcut.triggered',
+ /**
+ * Called when user views the Leaderboard tab within Points
+ */
+ pointsLeaderboardViewed: 'points.leaderboard.viewed',
+ /**
+ * Called when user copies their referral link
+ * within Points and tracks if it was a code or link
+ */
+ pointsReferralCopied: 'points.referral.copied',
+ /**
+ * Called when user taps the claim button
+ * within the Points / Eth rewards screen
+ */
+ pointsRewardsClaimButtonClicked: 'points.rewards.claim_button.clicked',
+ /**
+ * Called when user chooses which network to claim rewards on and the
+ * code to claim is executed within the Points / Eth rewards screen
+ */
+ pointsRewardsClaimSubmitted: 'points.rewards.claim.submitted',
+ /**
+ * Called when user views the Rewards tab within Points
+ */
+ pointsRewardsViewed: 'points.rewards.viewed',
+ /**
+ * Called when user views the Points tab
+ */
+ pointsViewed: 'points.viewed',
/**
* Called when the popup entry is opened, including:
* - extension popup
@@ -549,6 +576,35 @@ export type EventProperties = {
*/
type: KeyboardEventDescription;
};
+ [event.pointsLeaderboardViewed]: undefined;
+ [event.pointsReferralCopied]: {
+ /**
+ * Was a `link` or `code` copied
+ */
+ type: 'link' | 'code';
+ };
+ [event.pointsRewardsClaimButtonClicked]: {
+ /**
+ * Claim amount in ETH
+ */
+ claimAmount: number;
+ };
+ [event.pointsRewardsClaimSubmitted]: {
+ /**
+ * claim amount in ETH
+ */
+ claimAmount: number;
+ /**
+ * claim amount in USD
+ */
+ claimAmountUSD: number;
+ /**
+ * which network of the three possible was selected
+ */
+ networkSelected: 'optimism' | 'base' | 'zora';
+ };
+ [event.pointsRewardsViewed]: undefined;
+ [event.pointsViewed]: undefined;
[event.popupOpened]: undefined;
[event.settingsAnalyticsTrackingDisabled]: undefined;
[event.revokeSubmitted]: {
diff --git a/src/analytics/userProperties.ts b/src/analytics/userProperties.ts
index 2c8ed579e5..f36bf4a44d 100644
--- a/src/analytics/userProperties.ts
+++ b/src/analytics/userProperties.ts
@@ -1,13 +1,23 @@
// these can be reported separately so they must be optional
export interface UserProperties {
+ // number of imported or generated accounts
ownedAccounts?: number;
+ // number of accounts tied to paired hardware wallets
hardwareAccounts?: number;
+ // number of watched addresses or ens
watchedAccounts?: number;
+ // number of imported or generated secret recovery phrases
recoveryPhrases?: number;
+ // number of imported secret recovery phrases
importedRecoveryPhrases?: number;
+ // number of unique private keys
privateKeys?: number;
+ // number of imported unique private keys
importedPrivateKeys?: number;
+ // number of paired trezor hardware wallets
trezorDevices?: number;
+ // number of paired ledger hardware wallets
ledgerDevices?: number;
+ // whether a recovery phrase or private key has been imported
hasImported?: boolean;
}
diff --git a/src/core/raps/actions/claim.ts b/src/core/raps/actions/claim.ts
index 9532756bf9..e9fc59e762 100644
--- a/src/core/raps/actions/claim.ts
+++ b/src/core/raps/actions/claim.ts
@@ -22,7 +22,7 @@ export async function claim({
? CLAIM_MOCK_DATA
: await metadataPostClient.claimUserRewards({ address });
- // Checking ig we got the tx hash
+ // Checking if we got the tx hash
const txHash = claimInfo.claimUserRewards?.txHash;
if (!txHash) {
// If there's no transaction hash the relayer didn't submit the transaction
diff --git a/src/entries/popup/pages/home/Points/ClaimOverview.tsx b/src/entries/popup/pages/home/Points/ClaimOverview.tsx
index 4fc1b83f6d..66564cf666 100644
--- a/src/entries/popup/pages/home/Points/ClaimOverview.tsx
+++ b/src/entries/popup/pages/home/Points/ClaimOverview.tsx
@@ -1,5 +1,5 @@
import { motion } from 'framer-motion';
-import { useEffect, useState } from 'react';
+import { memo, useEffect, useState } from 'react';
import { PointsErrorType } from '~/core/graphql/__generated__/metadata';
import { i18n } from '~/core/languages';
@@ -47,7 +47,7 @@ export function ClaimOverview({
const showSuccess = !waitToDisplay && success && preparingClaim && !error;
useEffect(() => {
- setTimeout(() => setWaitToDisplay(false), 3000);
+ setTimeout(() => setWaitToDisplay(false), 4000);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
@@ -186,7 +186,7 @@ function ErrorText({ error }: { error?: string }) {
);
}
-function RainbowSlant() {
+const RainbowSlant = memo(function () {
return (
@@ -208,7 +208,8 @@ function RainbowSlant() {
);
-}
+});
+RainbowSlant.displayName = 'RainbowSlant';
function ClaimSummary({ amount, price }: { amount: string; price: string }) {
return (
diff --git a/src/entries/popup/pages/home/Points/ClaimSheet.tsx b/src/entries/popup/pages/home/Points/ClaimSheet.tsx
index 2be9319f7c..171f2d7927 100644
--- a/src/entries/popup/pages/home/Points/ClaimSheet.tsx
+++ b/src/entries/popup/pages/home/Points/ClaimSheet.tsx
@@ -2,12 +2,14 @@ import { useMutation } from '@tanstack/react-query';
import { motion } from 'framer-motion';
import { useEffect, useState } from 'react';
+import { analytics } from '~/analytics';
+import { event } from '~/analytics/event';
import config from '~/core/firebase/remoteConfig';
import { i18n } from '~/core/languages';
import { RapClaimActionParameters } from '~/core/raps/references';
import { chainsLabel } from '~/core/references/chains';
import { useCurrentAddressStore, useCurrentCurrencyStore } from '~/core/state';
-import { ChainId } from '~/core/types/chains';
+import { ChainId, chainIdToNameMapping } from '~/core/types/chains';
import { GasSpeed } from '~/core/types/gas';
import {
convertAmountAndPriceToNativeDisplay,
@@ -149,7 +151,15 @@ export function ClaimSheet() {
setSelectedChainId(chain);
setInitialClaimableAmount(claimableBalance.amount);
setInitialClaimableDisplay(claimablePriceDisplay.display);
- setTimeout(() => claimRewards(), 500);
+ claimRewards();
+ analytics.track(event.pointsRewardsClaimSubmitted, {
+ claimAmount: Number(claimableBalance.amount),
+ claimAmountUSD: Number(claimablePriceDisplay.display.slice(1)),
+ networkSelected: chainIdToNameMapping[chain] as
+ | 'optimism'
+ | 'zora'
+ | 'base',
+ });
};
const baseInfo = {
@@ -170,7 +180,7 @@ export function ClaimSheet() {
useEffect(() => {
if (showSuccess && !showSummary) {
- setTimeout(() => setShowSummary(true), 5000);
+ setTimeout(() => setShowSummary(true), 7000);
}
}, [showSuccess, showSummary]);
diff --git a/src/entries/popup/pages/home/Points/PointsDashboard.tsx b/src/entries/popup/pages/home/Points/PointsDashboard.tsx
index 93a58377ac..791ce4bc99 100644
--- a/src/entries/popup/pages/home/Points/PointsDashboard.tsx
+++ b/src/entries/popup/pages/home/Points/PointsDashboard.tsx
@@ -13,6 +13,8 @@ import {
import { Address } from 'viem';
import rainbowIcon from 'static/images/icon-16@2x.png';
+import { analytics } from '~/analytics';
+import { event } from '~/analytics/event';
import { PointsQuery } from '~/core/graphql/__generated__/metadata';
import { i18n } from '~/core/languages';
import { useCurrentAddressStore, useCurrentCurrencyStore } from '~/core/state';
@@ -273,25 +275,28 @@ function TextWithMoreInfo({ children }: PropsWithChildren) {
);
}
-export const copyReferralLink = (referralCode: string) =>
+export const copyReferralLink = (referralCode: string) => {
+ analytics.track(event.pointsReferralCopied, { type: 'link' });
copy({
value: `https://rainbow.me/points?ref=${referralCode}`,
title: i18n.t('points.copied_referral_link'),
description: `rainbow.me/points?ref=${referralCode}`,
});
+};
const formatReferralCode = (referralCode: string) =>
referralCode.slice(0, 3) + '-' + referralCode.slice(-3);
function ReferralCode() {
const { currentAddress } = useCurrentAddressStore();
const { data, isSuccess } = usePoints(currentAddress);
- const copyReferralCode = () =>
+ const copyReferralCode = () => {
+ analytics.track(event.pointsReferralCopied, { type: 'code' });
copy({
value: data?.user.referralCode || '',
title: i18n.t('points.copied_referral_code'),
description: formatReferralCode(data?.user.referralCode || ''),
});
-
+ };
return (
@@ -716,7 +721,15 @@ function ClaimYourPointsCta({
whileTap={{ scale: 0.98 }}
whileFocus={{ scale: 1.02 }}
whileHover={{ scale: 1.02 }}
- onClick={() => showClaimSheet()}
+ onClick={() => {
+ // TODO: Also track amount in USD
+ analytics.track(event.pointsRewardsClaimButtonClicked, {
+ claimAmount: Number(
+ convertRawAmountToDecimalFormat(claimableReward, 18),
+ ),
+ });
+ showClaimSheet();
+ }}
>
{i18n.t('points.rewards.claim_reward', {
@@ -894,12 +907,6 @@ function MyEarnings({ earnings = '0' }: { earnings?: string }) {
{i18n.t('points.rewards.my_earnings')}
-
@@ -1101,6 +1108,14 @@ export function PointsDashboard() {
const [displayMode, setDisplayMode] = useState<'rewards' | 'leaderboard'>(
'rewards',
);
+ useEffect(() => {
+ if (displayMode === 'rewards') {
+ analytics.track(event.pointsRewardsViewed);
+ } else if (displayMode === 'leaderboard') {
+ analytics.track(event.pointsLeaderboardViewed);
+ }
+ analytics.track(event.pointsViewed);
+ }, [displayMode]);
return (
<>
Your reward is ready",
"claim_complete": "> Claim Complete",
"already_claimed": "> Your reward has already been claimed",