Skip to content

Commit 5508de8

Browse files
authored
Ask user how they found MinusX (#70)
* Add login input to enter discovery method * Ensure valid input before login * Use auth APIs to show discovery input during auth * Add events to track discovery method
1 parent b37b62b commit 5508de8

File tree

4 files changed

+231
-5
lines changed

4 files changed

+231
-5
lines changed

web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"@vitejs/plugin-react": "^4.3.1",
3737
"axios": "^1.7.2",
3838
"babel-jest": "^29.5.0",
39+
"chakra-react-select": "^5.0.2",
3940
"diff": "^7.0.0",
4041
"eslint-plugin-unused-imports": "^2.0.0",
4142
"framer-motion": "^8.4.3",

web/src/components/common/Auth.tsx

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useState, useRef, useEffect } from 'react';
22
import { Button, Input, Box, VStack, Image, CloseButton, HStack, Text, Progress } from '@chakra-ui/react';
3+
import { Select, CreatableSelect } from "chakra-react-select";
34
import { login } from '../../state/auth/reducer'
45
import { dispatch } from '../../state/dispatch'
56
import {auth, auth as authModule} from '../../app/api'
@@ -11,6 +12,7 @@ import { captureEvent, GLOBAL_EVENTS } from '../../tracking';
1112
import { capture } from '../../helpers/screenCapture/extensionCapture';
1213
import { TelemetryToggle } from './Settings';
1314
import { getParsedIframeInfo } from '../../helpers/origin';
15+
import { toast } from '../../app/toast';
1416

1517
interface HighlightItem {
1618
content: React.ReactNode;
@@ -109,9 +111,34 @@ const Auth = () => {
109111
const session_jwt = useSelector(state => state.auth.session_jwt)
110112
const [email, setEmail] = useState("");
111113
const [authJWT, setAuthJWT] = useState("");
114+
const [isFirstTimeUser, setIsFirstTimeUser] = useState(false);
112115
const [otp, setOTP] = useState("");
116+
const [discoveryMethod, setDiscoveryMethod] = useState("");
113117
const isOTPMode = authJWT ? true : false
114118
const handleVerifyOtp = () => {
119+
if (!otp) {
120+
return toast({
121+
title: 'Invalid code',
122+
description: "Please enter a valid code",
123+
status: 'warning',
124+
duration: 5000,
125+
isClosable: true,
126+
position: 'bottom-right',
127+
})
128+
}
129+
if (isFirstTimeUser && !discoveryMethod) {
130+
return toast({
131+
title: 'Please fill all the fields',
132+
description: "Please tell us how you found us!",
133+
status: 'warning',
134+
duration: 5000,
135+
isClosable: true,
136+
position: 'bottom-right',
137+
})
138+
}
139+
if (discoveryMethod) {
140+
captureEvent(GLOBAL_EVENTS.user_discovery_method, { email, discoveryMethod })
141+
}
115142
console.log('Login params are', authJWT, otp, session_jwt)
116143
captureEvent(GLOBAL_EVENTS.otp_attempted, { email, otp, authJWT })
117144
authModule.login(authJWT, otp, session_jwt).then(({ session_jwt, profile_id, email, is_new_user }) => {
@@ -121,7 +148,7 @@ const Auth = () => {
121148
email,
122149
}))
123150
if (is_new_user) {
124-
captureEvent(GLOBAL_EVENTS.user_signup, { email, profile_id })
151+
captureEvent(GLOBAL_EVENTS.user_signup, { email, profile_id, discoveryMethod })
125152
} else {
126153
captureEvent(GLOBAL_EVENTS.user_login, { email, profile_id })
127154
}
@@ -135,8 +162,9 @@ const Auth = () => {
135162
const handleSignin = () => {
136163
// capture email_entered event
137164
captureEvent(GLOBAL_EVENTS.email_entered, { email })
138-
authModule.verifyEmail(email).then(({auth_jwt}) => {
165+
authModule.verifyEmail(email).then(({auth_jwt, first}) => {
139166
setAuthJWT(auth_jwt)
167+
setIsFirstTimeUser(first)
140168
captureEvent(GLOBAL_EVENTS.otp_received, { email, auth_jwt })
141169
}).catch((error) => {
142170
captureEvent(GLOBAL_EVENTS.otp_sending_failed, { email })
@@ -231,6 +259,43 @@ const Auth = () => {
231259
}}
232260
borderColor={"minusxBW.600"}
233261
/>
262+
{ isFirstTimeUser ?
263+
<>
264+
How did you find us?
265+
<CreatableSelect
266+
chakraStyles={{container: (base) => ({...base, width: "100%"})}}
267+
tagColorScheme="purple"
268+
placeholder="How did you find us?"
269+
onChange={(value) => setDiscoveryMethod(value)}
270+
options={[
271+
{
272+
label: "Instagram",
273+
value: "Instagram",
274+
},
275+
{
276+
label: "LinkedIn",
277+
value: "LinkedIn",
278+
},
279+
{
280+
label: "Twitter",
281+
value: "Twitter",
282+
},
283+
{
284+
label: "Google",
285+
value: "Google",
286+
},
287+
{
288+
label: "YouTube",
289+
value: "YouTube",
290+
},
291+
{
292+
label: "Friends/Colleagues",
293+
value: "Friends/Colleagues",
294+
},
295+
]}
296+
/>
297+
</> : null
298+
}
234299
<Button colorScheme="minusxBW" variant="outline" onClick={handleVerifyOtp} width="100%" aria-label="Verify Code">
235300
Verify Code
236301
</Button>

web/src/tracking/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const GLOBAL_EVENTS = {
1010
"otp_failed": "global/otp_failed",
1111
"otp_success": "global/otp_success",
1212
"user_signup": "global/user_signup",
13+
"user_discovery_method": "global/user_discovery_method",
1314
"user_login": "global/user_login",
1415
"billing_checkout": "global/billing_checkout",
1516
"billing_portal": "global/billing_portal",

0 commit comments

Comments
 (0)