Skip to content

Commit d58dfed

Browse files
authored
feat: update how we select user id (#1912)
1 parent c743a8f commit d58dfed

File tree

6 files changed

+78
-13
lines changed

6 files changed

+78
-13
lines changed

scripts/inject-amplitude.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { fileURLToPath } from 'url';
44

55
const AMPLITUDE_API_KEY = process.env.AMPLITUDE_API_KEY;
66
const AMPLITUDE_SERVER_URL = process.env.AMPLITUDE_SERVER_URL;
7-
const AMPLITUDE_SERVER_ZONE = process.env.AMPLITUDE_SERVER_ZONE || "US";
7+
const AMPLITUDE_SERVER_ZONE = process.env.AMPLITUDE_SERVER_ZONE || 'US';
88

99
const currentPath = fileURLToPath(import.meta.url);
1010
const projectRoot = path.dirname(currentPath);
@@ -14,7 +14,7 @@ if (AMPLITUDE_API_KEY) {
1414
const files = await fs.readdir('entry-points');
1515
for (const file of files) {
1616
inject(file);
17-
};
17+
}
1818
} catch (err) {
1919
console.error('Error injecting Amplitude scripts:', err);
2020
}
@@ -33,13 +33,14 @@ async function inject(fileName) {
3333
!(function () {
3434
var e = "${AMPLITUDE_API_KEY}";
3535
e &&
36-
(globalThis.amplitude.init(e${AMPLITUDE_SERVER_URL
37-
? `, undefined, {
36+
(globalThis.amplitude.init(e${
37+
AMPLITUDE_SERVER_URL
38+
? `, undefined, {
3839
serverUrl: "${AMPLITUDE_SERVER_URL}",
3940
serverZone: "${AMPLITUDE_SERVER_ZONE}"
4041
}`
41-
: ''
42-
}),
42+
: ''
43+
}),
4344
globalThis.amplitude.setOptOut(!1),
4445
globalThis.addEventListener("dydx:track", function (e) {
4546
var t = e.detail.eventType,
@@ -49,7 +50,7 @@ async function inject(fileName) {
4950
globalThis.addEventListener("dydx:identify", function (e) {
5051
var t = e.detail.property,
5152
d = e.detail.propertyValue;
52-
if ("walletAddress" === t) globalThis.amplitude.setUserId(d);
53+
if ("userId" === t) globalThis.amplitude.setUserId(d);
5354
else {
5455
var i = new globalThis.amplitude.Identify();
5556
i.set(t, d), globalThis.amplitude.identify(i);
@@ -67,4 +68,4 @@ async function inject(fileName) {
6768
await fs.writeFile(htmlFilePath, injectedHtml, 'utf-8');
6869

6970
console.log(`Amplitude scripts successfully injected (${fileName}).`);
70-
}
71+
}

src/constants/analytics.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ export const AnalyticsUserProperties = unionize(
8484

8585
// validators
8686
BonsaiValidatorUrl: ofType<string | null>(),
87+
88+
// User
89+
UserId: ofType<string | null>(),
90+
IsNewUser: ofType<boolean | null>(),
8791
},
8892
{ tag: 'type' as const, value: 'payload' as const }
8993
);
@@ -106,6 +110,8 @@ export const AnalyticsUserPropertyLoggableTypes = {
106110
AffiliateAddress: 'affiliateAddress',
107111
BonsaiValidatorUrl: 'bonsaiValidator',
108112
CustomFlags: 'customFlags',
113+
UserId: 'userId',
114+
IsNewUser: 'isNewUser',
109115
} as const satisfies Record<AnalyticsUserPropertyTypes, string>;
110116

111117
export type AnalyticsUserProperty = UnionOf<typeof AnalyticsUserProperties>;
@@ -196,6 +202,8 @@ export const AnalyticsEvents = unionize(
196202
state: OnboardingState;
197203
step?: OnboardingSteps;
198204
}>(),
205+
OnboardingSignInWithWalletClick: ofType<{}>(),
206+
OnboardingSignInWithSocialsClick: ofType<{}>(),
199207
OnboardingAccountDerived: ofType<{
200208
hasPreviousTransactions: boolean;
201209
}>(),

src/hooks/Onboarding/useGenerateKeys.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import { log } from 'console';
44
import { AES } from 'crypto-js';
55

66
import { EvmDerivedAccountStatus } from '@/constants/account';
7-
import { AnalyticsEvents } from '@/constants/analytics';
7+
import { AnalyticsEvents, AnalyticsUserProperties } from '@/constants/analytics';
88
import { DydxAddress } from '@/constants/wallets';
99

1010
import { useAppDispatch } from '@/state/appTypes';
1111
import { setSavedEncryptedSignature } from '@/state/wallet';
1212

13-
import { track } from '@/lib/analytics/analytics';
13+
import { identify, track } from '@/lib/analytics/analytics';
1414
import { parseWalletError } from '@/lib/wallet';
1515

1616
import { useAccounts } from '../useAccounts';
@@ -119,6 +119,7 @@ export function useGenerateKeys(generateKeysProps?: GenerateKeysProps) {
119119
track(AnalyticsEvents.OnboardingAccountDerived({ hasPreviousTransactions }));
120120

121121
if (!hasPreviousTransactions) {
122+
identify(AnalyticsUserProperties.IsNewUser(true));
122123
setDerivationStatus(EvmDerivedAccountStatus.EnsuringDeterminism);
123124

124125
// Second signature
@@ -134,6 +135,8 @@ export function useGenerateKeys(generateKeysProps?: GenerateKeysProps) {
134135
'Your wallet does not support deterministic signing. Please switch to a different wallet provider.'
135136
);
136137
}
138+
} else {
139+
identify(AnalyticsUserProperties.IsNewUser(false));
137140
}
138141
} catch (err) {
139142
setDerivationStatus(EvmDerivedAccountStatus.NotDerived);

src/hooks/useAnalytics.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
lastSuccessfulWebsocketRequestByOrigin,
99
} from '@/constants/analytics';
1010
import { DialogTypesTypes } from '@/constants/dialogs';
11-
import { WalletInfo } from '@/constants/wallets';
11+
import { ConnectorType, WalletInfo } from '@/constants/wallets';
1212

1313
import { calculateOnboardingStep } from '@/state/accountCalculators';
1414
import { getSubaccountId } from '@/state/accountInfoSelectors';
@@ -19,6 +19,7 @@ import { getSelectedLocale } from '@/state/localizationSelectors';
1919
import { getTradeFormValues } from '@/state/tradeFormSelectors';
2020

2121
import { identify, track } from '@/lib/analytics/analytics';
22+
import { runFn } from '@/lib/do';
2223

2324
import { useAccounts } from './useAccounts';
2425
import { useApiState } from './useApiState';
@@ -103,6 +104,51 @@ export const useAnalytics = () => {
103104
identify(AnalyticsUserProperties.Network(selectedNetwork));
104105
}, [selectedNetwork]);
105106

107+
// AnalyticsUserProperty.UserId
108+
const [analyticsUserId, setAnalyticsUserId] = useState<string | null>(null);
109+
110+
useEffect(() => {
111+
let dead = false;
112+
113+
runFn(async () => {
114+
if (dead) return;
115+
if (sourceAccount.walletInfo?.connectorType === ConnectorType.Test) {
116+
setAnalyticsUserId(null);
117+
}
118+
119+
if (sourceAccount.walletInfo?.connectorType === ConnectorType.Turnkey) {
120+
if (sourceAccount.walletInfo.userEmail && typeof globalThis.crypto !== 'undefined') {
121+
const normalizedEmail = sourceAccount.walletInfo.userEmail.trim().toLowerCase();
122+
const hashedEmail = await globalThis.crypto.subtle.digest(
123+
'SHA-256',
124+
new TextEncoder().encode(normalizedEmail)
125+
);
126+
127+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
128+
if (dead) return;
129+
130+
setAnalyticsUserId(
131+
Array.from(new Uint8Array(hashedEmail))
132+
.map((b) => b.toString(16).padStart(2, '0'))
133+
.join('')
134+
);
135+
136+
return;
137+
}
138+
}
139+
140+
setAnalyticsUserId(sourceAccount.address ?? null);
141+
});
142+
143+
return () => {
144+
dead = true;
145+
};
146+
}, [sourceAccount.address, sourceAccount.walletInfo]);
147+
148+
useEffect(() => {
149+
identify(AnalyticsUserProperties.UserId(analyticsUserId));
150+
}, [analyticsUserId]);
151+
106152
// AnalyticsUserProperty.WalletType
107153
useEffect(() => {
108154
identify(AnalyticsUserProperties.WalletType(sourceAccount.walletInfo?.name ?? null));

src/providers/TurnkeyAuthProvider.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useTurnkey } from '@turnkey/sdk-react';
88
import { jwtDecode } from 'jwt-decode';
99
import { useSearchParams } from 'react-router-dom';
1010

11-
import { AnalyticsEvents } from '@/constants/analytics';
11+
import { AnalyticsEvents, AnalyticsUserProperties } from '@/constants/analytics';
1212
import { DialogTypes } from '@/constants/dialogs';
1313
import { STRING_KEYS } from '@/constants/localization';
1414
import { ConnectorType, WalletType } from '@/constants/wallets';
@@ -34,7 +34,7 @@ import {
3434
} from '@/state/wallet';
3535
import { getSourceAccount, getTurnkeyEmailOnboardingData } from '@/state/walletSelectors';
3636

37-
import { track } from '@/lib/analytics/analytics';
37+
import { identify, track } from '@/lib/analytics/analytics';
3838
import { parseTurnkeyError } from '@/lib/turnkey/turnkeyUtils';
3939

4040
import { useTurnkeyWallet } from './TurnkeyWalletProvider';
@@ -135,7 +135,10 @@ const useTurnkeyAuthContext = () => {
135135

136136
if (response.dydxAddress === '') {
137137
setIsNewTurnkeyUser(true);
138+
identify(AnalyticsUserProperties.IsNewUser(true));
138139
dispatch(setRequiresAddressUpload(true));
140+
} else {
141+
identify(AnalyticsUserProperties.IsNewUser(false));
139142
}
140143

141144
if (loginMethod === LoginMethod.OAuth && response.alreadyExists) {

src/views/dialogs/OnboardingDialog.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import styled, { css } from 'styled-components';
55
import tw from 'twin.macro';
66

77
import { EvmDerivedAccountStatus, OnboardingSteps } from '@/constants/account';
8+
import { AnalyticsEvents } from '@/constants/analytics';
89
import { DialogProps, DialogTypes, OnboardingDialogProps } from '@/constants/dialogs';
910
import { STRING_KEYS } from '@/constants/localization';
1011
import { StatsigFlags } from '@/constants/statsig';
@@ -38,6 +39,7 @@ import { calculateOnboardingStep } from '@/state/accountCalculators';
3839
import { useAppDispatch } from '@/state/appTypes';
3940
import { openDialog } from '@/state/dialogs';
4041

42+
import { track } from '@/lib/analytics/analytics';
4143
import { testFlags } from '@/lib/testFlags';
4244

4345
import { LanguageSelector } from '../menus/LanguageSelector';
@@ -93,10 +95,12 @@ export const OnboardingDialog = ({
9395
);
9496

9597
const onDisplayChooseWallet = () => {
98+
track(AnalyticsEvents.OnboardingSignInWithWalletClick());
9699
dispatch(setDisplayChooseWallet(true));
97100
};
98101

99102
const onSignInWithSocials = () => {
103+
track(AnalyticsEvents.OnboardingSignInWithSocialsClick());
100104
dispatch(setDisplayChooseWallet(false));
101105
};
102106

0 commit comments

Comments
 (0)