From a8815e4e2c3dd1dd773948c67618f28a62a86e3a Mon Sep 17 00:00:00 2001 From: Tomek Marciniak Date: Thu, 11 Apr 2024 11:36:49 +0200 Subject: [PATCH] chore(analytics): replace jitsu with mixpanel --- packages/features/package.json | 2 +- .../src/common/hooks/use-analytics.ts | 24 ---- .../views/mnemonic-confirmation.tsx | 6 +- .../src/onboarding/views/mnemonic-input.tsx | 6 +- packages/features/src/router.tsx | 13 +- .../components/confirm-transaction-form.tsx | 12 +- pnpm-lock.yaml | 117 +++--------------- 7 files changed, 38 insertions(+), 142 deletions(-) delete mode 100644 packages/features/src/common/hooks/use-analytics.ts diff --git a/packages/features/package.json b/packages/features/package.json index 418aa0cc..f0954aea 100644 --- a/packages/features/package.json +++ b/packages/features/package.json @@ -34,7 +34,6 @@ }, "dependencies": { "@hookform/resolvers": "^3.3.2", - "@jitsu/jitsu-react": "^1.7.2", "@palladxyz/key-management": "^0.0.1", "@palladxyz/mina-core": "^0.0.1", "@palladxyz/offchain-data": "^1.0.0", @@ -84,6 +83,7 @@ "react-day-picker": "^8.9.1", "react-dom": "^18.2.0", "react-hook-form": "^7.49.2", + "react-mixpanel-browser": "^4.1.0", "react-qr-code": "^2.0.12", "react-router": "^6.21.0", "react-router-dom": "^6.21.0", diff --git a/packages/features/src/common/hooks/use-analytics.ts b/packages/features/src/common/hooks/use-analytics.ts deleted file mode 100644 index 8f440ee2..00000000 --- a/packages/features/src/common/hooks/use-analytics.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useJitsu } from '@jitsu/jitsu-react' - -import { useAppStore } from '../store/app' - -type Event = - | 'wallet_restored' - | 'wallet_created' - | 'transaction_sent' - | 'portfolio_delegated' - -type TrackProps = { - event: Event - metadata?: Record -} - -export const useAnalytics = () => { - const { analytics } = useJitsu() - const canTrack = useAppStore((state) => state.shareData) - const track = ({ event, metadata }: TrackProps) => { - if (!canTrack) return - return analytics.track(event, metadata) - } - return { track } -} diff --git a/packages/features/src/onboarding/views/mnemonic-confirmation.tsx b/packages/features/src/onboarding/views/mnemonic-confirmation.tsx index 79bdc0cf..96f3c0b6 100644 --- a/packages/features/src/onboarding/views/mnemonic-confirmation.tsx +++ b/packages/features/src/onboarding/views/mnemonic-confirmation.tsx @@ -8,9 +8,9 @@ import { DEFAULT_NETWORK, KeyAgents, useVault } from '@palladxyz/vault' import { Loader2Icon } from 'lucide-react' import { useMemo, useState } from 'react' import { useForm } from 'react-hook-form' +import { useMixpanel } from 'react-mixpanel-browser' import { useNavigate } from 'react-router-dom' -import { useAnalytics } from '@/common/hooks/use-analytics' import { useAppStore } from '@/common/store/app' import { useOnboardingStore } from '@/common/store/onboarding' import { ButtonArrow } from '@/components/button-arrow' @@ -25,7 +25,7 @@ const getConfirmationIndex = () => { } export const MnemonicConfirmationView = () => { - const { track } = useAnalytics() + const mixpanel = useMixpanel() const [restoring, setRestoring] = useState(false) const restoreWallet = useVault((state) => state.restoreWallet) const [confirmationIndex] = useState(getConfirmationIndex()) @@ -80,7 +80,7 @@ export const MnemonicConfirmationView = () => { KeyAgents.InMemory, 'Test' // TODO: make this a configurable credential name or random if not provided ) - track({ event: 'wallet_created' }) + mixpanel.track('WalletCreated') setVaultStateInitialized() return navigate('/onboarding/finish') } finally { diff --git a/packages/features/src/onboarding/views/mnemonic-input.tsx b/packages/features/src/onboarding/views/mnemonic-input.tsx index c832aecd..dc38188f 100644 --- a/packages/features/src/onboarding/views/mnemonic-input.tsx +++ b/packages/features/src/onboarding/views/mnemonic-input.tsx @@ -10,10 +10,10 @@ import { DEFAULT_NETWORK, KeyAgents, useVault } from '@palladxyz/vault' import { Loader2Icon } from 'lucide-react' import { useState } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' +import { useMixpanel } from 'react-mixpanel-browser' import { useNavigate } from 'react-router-dom' import { shallow } from 'zustand/shallow' -import { useAnalytics } from '@/common/hooks/use-analytics' import { useAppStore } from '@/common/store/app' import { useOnboardingStore } from '@/common/store/onboarding' import { Autocomplete } from '@/components/autocomplete' @@ -35,7 +35,7 @@ const mnemonicIterator = Array.from( ) export const MnemonicInputView = () => { - const { track } = useAnalytics() + const mixpanel = useMixpanel() const [restoring, setRestoring] = useState(false) const restoreWallet = useVault((state) => state.restoreWallet) const navigate = useNavigate() @@ -83,7 +83,7 @@ export const MnemonicInputView = () => { KeyAgents.InMemory, 'Test' // TODO: make this a configurable credential name or random if not provided ) - track({ event: 'wallet_restored' }) + mixpanel.track('WalletRestored') setVaultStateInitialized() return navigate('/onboarding/finish') } finally { diff --git a/packages/features/src/router.tsx b/packages/features/src/router.tsx index e5f7f58f..1be5f51f 100644 --- a/packages/features/src/router.tsx +++ b/packages/features/src/router.tsx @@ -1,6 +1,6 @@ -import { JitsuProvider } from '@jitsu/jitsu-react' import dayjs from 'dayjs' import relativeTime from 'dayjs/plugin/relativeTime' +import { MixpanelProvider } from 'react-mixpanel-browser' import { MemoryRouter, Route, Routes } from 'react-router-dom' import { Toaster } from '@/components/ui/toaster' @@ -33,10 +33,15 @@ import { TransactionsView } from './transactions/views/transactions' dayjs.extend(relativeTime) +const mixpanelConfig = { + track_pageview: true +} + export const Router = () => { return ( -
@@ -101,6 +106,6 @@ export const Router = () => {
-
+ ) } diff --git a/packages/features/src/send/components/confirm-transaction-form.tsx b/packages/features/src/send/components/confirm-transaction-form.tsx index 0a9012de..370109b0 100644 --- a/packages/features/src/send/components/confirm-transaction-form.tsx +++ b/packages/features/src/send/components/confirm-transaction-form.tsx @@ -10,11 +10,11 @@ import { } from 'mina-signer/dist/node/mina-signer/src/TSTypes' import { useState } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' +import { useMixpanel } from 'react-mixpanel-browser' import { useNavigate } from 'react-router-dom' import { z } from 'zod' import { useAccount } from '@/common/hooks/use-account' -import { useAnalytics } from '@/common/hooks/use-analytics' import { usePendingTransactionStore } from '@/common/store/pending-transactions' import { useTransactionStore } from '@/common/store/transaction' import { ButtonArrow } from '@/components/button-arrow' @@ -28,7 +28,7 @@ import { ConfirmTransactionSchema } from './confirm-transaction-form.schema' type ConfirmTransactionData = z.infer export const ConfirmTransactionForm = () => { - const { track } = useAnalytics() + const mixpanel = useMixpanel() const [submitting, setSubmitting] = useState(false) const navigate = useNavigate() // can use @@ -127,14 +127,14 @@ export const ConfirmTransactionForm = () => { expireAt: addHours(new Date(), 8).toISOString() }) await syncWallet() - track({ - event: kind === 'staking' ? 'portfolio_delegated' : 'transaction_sent', - metadata: { + mixpanel.track( + kind === 'staking' ? 'PortfolioDelegated' : 'TransactionSent', + { amount: transaction.amount, fee: transaction.fee, to: kind === 'staking' && transaction.to } - }) + ) navigate('/transactions/success', { state: { hash diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86b23751..2773b7b3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -230,9 +230,6 @@ importers: '@hookform/resolvers': specifier: ^3.3.2 version: 3.3.3(react-hook-form@7.49.2) - '@jitsu/jitsu-react': - specifier: ^1.7.2 - version: 1.7.2(@types/dlv@1.1.4)(@types/react@18.2.46)(react-router-dom@6.21.1)(react@18.2.0) '@palladxyz/key-management': specifier: ^0.0.1 version: link:../key-management @@ -380,6 +377,9 @@ importers: react-hook-form: specifier: ^7.49.2 version: 7.49.2(react@18.2.0) + react-mixpanel-browser: + specifier: ^4.1.0 + version: 4.1.0(react@18.2.0) react-qr-code: specifier: ^2.0.12 version: 2.0.12(react@18.2.0) @@ -844,54 +844,6 @@ packages: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.20 - /@analytics/cookie-utils@0.2.12: - resolution: {integrity: sha512-2h/yuIu3kmu+ZJlKmlT6GoRvUEY2k1BbQBezEv5kGhnn9KpmzPz715Y3GmM2i+m7Y0QmBdVUoA260dQZkofs2A==} - dependencies: - '@analytics/global-storage-utils': 0.1.7 - dev: false - - /@analytics/core@0.12.7(@types/dlv@1.1.4): - resolution: {integrity: sha512-etmIPCoxWLoUZ/o1o2zvIk4cdVHa8I1xUQtTuLA+YXQ4SsFbm75ZoMXJBqWrNSENpqCJgoL6hizl5uTbkNN+1Q==} - dependencies: - '@analytics/global-storage-utils': 0.1.7 - '@analytics/type-utils': 0.6.2 - analytics-utils: 1.0.12(@types/dlv@1.1.4) - transitivePeerDependencies: - - '@types/dlv' - dev: false - - /@analytics/global-storage-utils@0.1.7: - resolution: {integrity: sha512-V+spzGLZYm4biZT4uefaylm80SrLXf8WOTv9hCgA46cLcyxx3LD4GCpssp1lj+RcWLl/uXJQBRO4Mnn/o1x6Gw==} - dependencies: - '@analytics/type-utils': 0.6.2 - dev: false - - /@analytics/localstorage-utils@0.1.10: - resolution: {integrity: sha512-uJS+Jp1yLG5VFCgA5T82ZODYBS0xuDQx0NtAZrgbqt9j51BX3TcgmOez5LVkrUNu/lpbxjCLq35I4TKj78VmOQ==} - dependencies: - '@analytics/global-storage-utils': 0.1.7 - dev: false - - /@analytics/session-storage-utils@0.0.7: - resolution: {integrity: sha512-PSv40UxG96HVcjY15e3zOqU2n8IqXnH8XvTkg1X43uXNTKVSebiI2kUjA3Q7ESFbw5DPwcLbJhV7GforpuBLDw==} - dependencies: - '@analytics/global-storage-utils': 0.1.7 - dev: false - - /@analytics/storage-utils@0.4.2: - resolution: {integrity: sha512-AXObwyVQw9h2uJh1t2hUgabtVxzYpW+7uKVbdHQK80vr3Td5rrmCxrCxarh7HUuAgSDZ0bZWqmYxVgmwKceaLg==} - dependencies: - '@analytics/cookie-utils': 0.2.12 - '@analytics/global-storage-utils': 0.1.7 - '@analytics/localstorage-utils': 0.1.10 - '@analytics/session-storage-utils': 0.0.7 - '@analytics/type-utils': 0.6.2 - dev: false - - /@analytics/type-utils@0.6.2: - resolution: {integrity: sha512-TD+xbmsBLyYy/IxFimW/YL/9L2IEnM7/EoV9Aeh56U64Ify8o27HJcKjo38XY9Tcn0uOq1AX3thkKgvtWvwFQg==} - dev: false - /@babel/code-frame@7.23.5: resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} @@ -3147,33 +3099,6 @@ packages: chalk: 4.1.2 dev: true - /@jitsu/jitsu-react@1.7.2(@types/dlv@1.1.4)(@types/react@18.2.46)(react-router-dom@6.21.1)(react@18.2.0): - resolution: {integrity: sha512-afUn8Fq9hX+mjLBtsjY2n7btnlDdrSMMGtkE+10/dsAyV+vRLa6Dtyd9v39yEauB679aN5CicC+45EGIBiBRQw==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': 15.x || 16.x || 17.x || 18.x - react: 15.x || 16.x || 17.x || 18.x - react-router-dom: 5.x || 6.x - peerDependenciesMeta: - react-router-dom: - optional: true - dependencies: - '@jitsu/js': 1.7.2(@types/dlv@1.1.4) - '@types/react': 18.2.46 - react: 18.2.0 - react-router-dom: 6.21.1(react-dom@18.2.0)(react@18.2.0) - transitivePeerDependencies: - - '@types/dlv' - dev: false - - /@jitsu/js@1.7.2(@types/dlv@1.1.4): - resolution: {integrity: sha512-7u5CFnre5PKjxSI7nr53IU7Ejr/66CbxfENQBrcsV8uyTS5xb8FHNdSqFKaTLWln4dcc2zGiu3ZntUyc5DL/uQ==} - dependencies: - analytics: 0.8.9(@types/dlv@1.1.4) - transitivePeerDependencies: - - '@types/dlv' - dev: false - /@jridgewell/gen-mapping@0.3.3: resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} engines: {node: '>=6.0.0'} @@ -5793,10 +5718,6 @@ packages: '@types/ms': 0.7.34 dev: true - /@types/dlv@1.1.4: - resolution: {integrity: sha512-m8KmImw4Jt+4rIgupwfivrWEOnj1LzkmKkqbh075uG13eTQ1ZxHWT6T0vIdSQhLIjQCiR0n0lZdtyDOPO1x2Mw==} - dev: false - /@types/estree-jsx@1.0.3: resolution: {integrity: sha512-pvQ+TKeRHeiUGRhvYwRrQ/ISnohKkSJR14fT2yqyZ4e9K5vqc7hrtY2Y1Dw0ZwAzQ6DQsxsaCUuSIIi8v0Cq6w==} dependencies: @@ -6592,25 +6513,6 @@ packages: uri-js: 4.4.1 dev: true - /analytics-utils@1.0.12(@types/dlv@1.1.4): - resolution: {integrity: sha512-WvV2YWgsnXLxaY0QYux0crpBAg/0JA763NmbMVz22jKhMPo7dpTBet8G2IlF7ixTjLDzGlkHk1ZaKqqQmjJ+4w==} - peerDependencies: - '@types/dlv': ^1.0.0 - dependencies: - '@analytics/type-utils': 0.6.2 - '@types/dlv': 1.1.4 - dlv: 1.1.3 - dev: false - - /analytics@0.8.9(@types/dlv@1.1.4): - resolution: {integrity: sha512-oTbUzQpncMTslakqfK70GgB6bopk5hY+uuekwnadMkDyqNLgcD02KRzteTnO7q5Ko6wDECVtT8xi/6OuAMZykA==} - dependencies: - '@analytics/core': 0.12.7(@types/dlv@1.1.4) - '@analytics/storage-utils': 0.4.2 - transitivePeerDependencies: - - '@types/dlv' - dev: false - /ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} dependencies: @@ -12094,6 +11996,10 @@ packages: resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} engines: {node: '>=16 || 14 >=14.17'} + /mixpanel-browser@2.49.0: + resolution: {integrity: sha512-RZJCO7XXuuHBAWG5fd9Mavz994M7v7W3Qiaq8NzmN631pa4BQ0vNZQtRFqKcCCOBn4xqOZbX2GkuC7ZkQoL4cQ==} + dev: false + /mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -13409,6 +13315,15 @@ packages: resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} dev: false + /react-mixpanel-browser@4.1.0(react@18.2.0): + resolution: {integrity: sha512-ShHQQslGi240VTAo685keDtKKe3B3w3yURi/jCwdtCAk6+OQnm1MdhuDC3SFADJ10VvdNb3240t1nKn7uPnTRQ==} + peerDependencies: + react: '18' + dependencies: + mixpanel-browser: 2.49.0 + react: 18.2.0 + dev: false + /react-qr-code@2.0.12(react@18.2.0): resolution: {integrity: sha512-k+pzP5CKLEGBRwZsDPp98/CAJeXlsYRHM2iZn1Sd5Th/HnKhIZCSg27PXO58zk8z02RaEryg+60xa4vyywMJwg==} peerDependencies: