diff --git a/web/components/account/auth-forms/auth-root.tsx b/web/components/account/auth-forms/auth-root.tsx index 5ac9fd011..45ccfa8ea 100644 --- a/web/components/account/auth-forms/auth-root.tsx +++ b/web/components/account/auth-forms/auth-root.tsx @@ -43,6 +43,7 @@ export const AuthRoot: FC = observer((props) => { const [email, setEmail] = useState(emailParam ? emailParam.toString() : ""); const [errorInfo, setErrorInfo] = useState(undefined); const [isPasswordAutoset, setIsPasswordAutoset] = useState(true); + const [isExistingEmail, setIsExistingEmail] = useState(false); // hooks const { config } = useInstance(); @@ -101,6 +102,7 @@ export const AuthRoot: FC = observer((props) => { setAuthStep(EAuthSteps.PASSWORD); } } + setIsExistingEmail(response.existing); }) .catch((error) => { const errorhandler = authErrorHandler(error?.error_code?.toString(), data?.email || undefined); @@ -138,6 +140,7 @@ export const AuthRoot: FC = observer((props) => { { setEmail(""); setAuthStep(EAuthSteps.EMAIL); diff --git a/web/components/account/auth-forms/password.tsx b/web/components/account/auth-forms/password.tsx index f84c2913e..ee6a9b267 100644 --- a/web/components/account/auth-forms/password.tsx +++ b/web/components/account/auth-forms/password.tsx @@ -8,7 +8,12 @@ import { Button, Input, Spinner } from "@plane/ui"; // components import { ForgotPasswordPopover, PasswordStrengthMeter } from "@/components/account"; // constants -import { FORGOT_PASSWORD } from "@/constants/event-tracker"; +import { + FORGOT_PASSWORD, + SIGN_IN_WITH_CODE, + SIGN_IN_WITH_PASSWORD, + SIGN_UP_WITH_PASSWORD, +} from "@/constants/event-tracker"; // helpers import { EAuthModes, EAuthSteps } from "@/helpers/authentication.helper"; import { API_BASE_URL } from "@/helpers/common.helper"; @@ -68,6 +73,7 @@ export const AuthPasswordForm: React.FC = observer((props: Props) => { const redirectToUniqueCodeSignIn = async () => { handleAuthStep(EAuthSteps.UNIQUE_CODE); + captureEvent(SIGN_IN_WITH_CODE); }; const passwordSupport = @@ -114,7 +120,10 @@ export const AuthPasswordForm: React.FC = observer((props: Props) => { className="mt-5 space-y-4" method="POST" action={`${API_BASE_URL}/auth/${mode === EAuthModes.SIGN_IN ? "sign-in" : "sign-up"}/`} - onSubmit={() => setIsSubmitting(true)} + onSubmit={() => { + setIsSubmitting(true); + captureEvent(mode === EAuthModes.SIGN_IN ? SIGN_IN_WITH_PASSWORD : SIGN_UP_WITH_PASSWORD); + }} onError={() => setIsSubmitting(false)} > diff --git a/web/components/account/auth-forms/unique-code.tsx b/web/components/account/auth-forms/unique-code.tsx index 2db106c44..e84422090 100644 --- a/web/components/account/auth-forms/unique-code.tsx +++ b/web/components/account/auth-forms/unique-code.tsx @@ -1,10 +1,13 @@ import React, { useEffect, useState } from "react"; import { CircleCheck, XCircle } from "lucide-react"; import { Button, Input, Spinner } from "@plane/ui"; +// constants +import { CODE_VERIFIED } from "@/constants/event-tracker"; // helpers import { EAuthModes } from "@/helpers/authentication.helper"; import { API_BASE_URL } from "@/helpers/common.helper"; // hooks +import { useEventTracker } from "@/hooks/store"; import useTimer from "@/hooks/use-timer"; // services import { AuthService } from "@/services/auth.service"; @@ -15,6 +18,7 @@ const authService = new AuthService(); type TAuthUniqueCodeForm = { mode: EAuthModes; email: string; + isExistingEmail: boolean; handleEmailClear: () => void; generateEmailUniqueCode: (email: string) => Promise<{ code: string } | undefined>; }; @@ -30,9 +34,9 @@ const defaultValues: TUniqueCodeFormValues = { }; export const AuthUniqueCodeForm: React.FC = (props) => { - const { mode, email, handleEmailClear, generateEmailUniqueCode } = props; + const { mode, email, handleEmailClear, generateEmailUniqueCode, isExistingEmail } = props; // hooks - // const { captureEvent } = useEventTracker(); + const { captureEvent } = useEventTracker(); // derived values const defaultResetTimerValue = 5; // states @@ -73,7 +77,13 @@ export const AuthUniqueCodeForm: React.FC = (props) => { className="mt-5 space-y-4" method="POST" action={`${API_BASE_URL}/auth/${mode === EAuthModes.SIGN_IN ? "magic-sign-in" : "magic-sign-up"}/`} - onSubmit={() => setIsSubmitting(true)} + onSubmit={() => { + setIsSubmitting(true); + captureEvent(CODE_VERIFIED, { + state: "SUCCESS", + first_time: isExistingEmail, + }); + }} onError={() => setIsSubmitting(false)} > diff --git a/web/components/onboarding/create-workspace.tsx b/web/components/onboarding/create-workspace.tsx index 57da9fc5a..d9db3cbd8 100644 --- a/web/components/onboarding/create-workspace.tsx +++ b/web/components/onboarding/create-workspace.tsx @@ -5,7 +5,7 @@ import { IUser, IWorkspace, TOnboardingSteps } from "@plane/types"; // ui import { Button, CustomSelect, Input, Spinner, TOAST_TYPE, setToast } from "@plane/ui"; // constants -import { WORKSPACE_CREATED } from "@/constants/event-tracker"; +import { E_ONBOARDING, WORKSPACE_CREATED } from "@/constants/event-tracker"; import { ORGANIZATION_SIZE, RESTRICTED_URLS } from "@/constants/workspace"; // hooks import { useEventTracker, useUserProfile, useWorkspace } from "@/hooks/store"; @@ -66,10 +66,10 @@ export const CreateWorkspace: React.FC = (props) => { captureWorkspaceEvent({ eventName: WORKSPACE_CREATED, payload: { - ...res, + workspace_id: res.id, state: "SUCCESS", first_time: true, - element: "Onboarding", + element: E_ONBOARDING, }, }); await fetchWorkspaces(); @@ -81,7 +81,7 @@ export const CreateWorkspace: React.FC = (props) => { payload: { state: "FAILED", first_time: true, - element: "Onboarding", + element: E_ONBOARDING, }, }); setToast({ diff --git a/web/components/onboarding/profile-setup.tsx b/web/components/onboarding/profile-setup.tsx index f6a254007..1b04ec8d6 100644 --- a/web/components/onboarding/profile-setup.tsx +++ b/web/components/onboarding/profile-setup.tsx @@ -13,7 +13,7 @@ import { PasswordStrengthMeter } from "@/components/account"; import { UserImageUploadModal } from "@/components/core"; import { OnboardingHeader, SwitchOrDeleteAccountDropdown } from "@/components/onboarding"; // constants -import { USER_DETAILS } from "@/constants/event-tracker"; +import { E_ONBOARDING, USER_DETAILS, USER_PERSONALIZATION } from "@/constants/event-tracker"; // helpers import { getPasswordStrength } from "@/helpers/password.helper"; // hooks @@ -141,7 +141,13 @@ export const ProfileSetup: React.FC = observer((props) => { ]); captureEvent(USER_DETAILS, { state: "SUCCESS", - element: "Onboarding", + element: E_ONBOARDING, + }); + captureEvent(USER_PERSONALIZATION, { + use_case: formData.use_case, + role: formData.role, + state: "SUCCESS", + element: E_ONBOARDING, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -155,7 +161,7 @@ export const ProfileSetup: React.FC = observer((props) => { } catch { captureEvent(USER_DETAILS, { state: "FAILED", - element: "Onboarding", + element: E_ONBOARDING, }); setToast({ type: TOAST_TYPE.ERROR, @@ -179,7 +185,7 @@ export const ProfileSetup: React.FC = observer((props) => { } catch { captureEvent(USER_DETAILS, { state: "FAILED", - element: "Onboarding", + element: E_ONBOARDING, }); setToast({ type: TOAST_TYPE.ERROR, @@ -199,9 +205,11 @@ export const ProfileSetup: React.FC = observer((props) => { updateUserProfile(profileUpdatePayload), totalSteps > 2 && stepChange({ profile_complete: true }), ]); - captureEvent(USER_DETAILS, { + captureEvent(USER_PERSONALIZATION, { + use_case: formData.use_case, + role: formData.role, state: "SUCCESS", - element: "Onboarding", + element: E_ONBOARDING, }); setToast({ type: TOAST_TYPE.SUCCESS, @@ -213,9 +221,9 @@ export const ProfileSetup: React.FC = observer((props) => { finishOnboarding(); } } catch { - captureEvent(USER_DETAILS, { + captureEvent(USER_PERSONALIZATION, { state: "FAILED", - element: "Onboarding", + element: E_ONBOARDING, }); setToast({ type: TOAST_TYPE.ERROR, diff --git a/web/constants/event-tracker.ts b/web/constants/event-tracker.ts index 7edfccba5..bc3a3d7ad 100644 --- a/web/constants/event-tracker.ts +++ b/web/constants/event-tracker.ts @@ -192,11 +192,14 @@ export const SETUP_PASSWORD = "Password setup"; export const PASSWORD_CREATE_SELECTED = "Password created"; export const PASSWORD_CREATE_SKIPPED = "Skipped to setup"; export const SIGN_IN_WITH_PASSWORD = "Sign in with password"; +export const SIGN_UP_WITH_PASSWORD = "Sign up with password"; +export const SIGN_IN_WITH_CODE = "Sign in with magic link"; export const FORGOT_PASSWORD = "Forgot password clicked"; export const FORGOT_PASS_LINK = "Forgot password link generated"; export const NEW_PASS_CREATED = "New password created"; // Onboarding Events export const USER_DETAILS = "User details added"; +export const USER_PERSONALIZATION = "User personalization added"; export const USER_ONBOARDING_COMPLETED = "User onboarding completed"; // Product Tour Events export const PRODUCT_TOUR_STARTED = "Product tour started"; @@ -222,3 +225,6 @@ export const SNOOZED_NOTIFICATIONS = "Snoozed notifications viewed"; export const ARCHIVED_NOTIFICATIONS = "Archived notifications viewed"; // Groups export const GROUP_WORKSPACE = "Workspace_metrics"; + +//Elements +export const E_ONBOARDING = "Onboarding"; \ No newline at end of file diff --git a/web/pages/accounts/forgot-password.tsx b/web/pages/accounts/forgot-password.tsx index 00cf0982e..ba307cc08 100644 --- a/web/pages/accounts/forgot-password.tsx +++ b/web/pages/accounts/forgot-password.tsx @@ -115,7 +115,7 @@ const ForgotPasswordPage: NextPageWithLayout = () => { New to Plane?{" "} captureEvent(NAVIGATE_TO_SIGNUP, {})} + onClick={() => captureEvent(NAVIGATE_TO_SIGNUP)} className="font-semibold text-custom-primary-100 hover:underline" > Create an account diff --git a/web/pages/accounts/reset-password.tsx b/web/pages/accounts/reset-password.tsx index a7e73ae76..7566b357d 100644 --- a/web/pages/accounts/reset-password.tsx +++ b/web/pages/accounts/reset-password.tsx @@ -9,6 +9,8 @@ import { Button, Input } from "@plane/ui"; // components import { AuthBanner, PasswordStrengthMeter } from "@/components/account"; import { PageHead } from "@/components/core"; +// constants +import { NEW_PASS_CREATED } from "@/constants/event-tracker"; // helpers import { EAuthenticationErrorCodes, @@ -19,6 +21,8 @@ import { } from "@/helpers/authentication.helper"; import { API_BASE_URL } from "@/helpers/common.helper"; import { getPasswordStrength } from "@/helpers/password.helper"; +// hooks +import { useEventTracker } from "@/hooks/store"; // layouts import DefaultLayout from "@/layouts/default-layout"; // lib @@ -66,6 +70,7 @@ const ResetPasswordPage: NextPageWithLayout = () => { // hooks const { resolvedTheme } = useTheme(); + const { captureEvent } = useEventTracker(); const handleShowPassword = (key: keyof typeof showPassword) => setShowPassword((prev) => ({ ...prev, [key]: !prev[key] })); @@ -132,6 +137,7 @@ const ResetPasswordPage: NextPageWithLayout = () => {
captureEvent(NEW_PASS_CREATED)} action={`${API_BASE_URL}/auth/reset-password/${uidb64?.toString()}/${token?.toString()}/`} > diff --git a/web/pages/sign-in.tsx b/web/pages/sign-in.tsx index 281b504ff..3e3fcd664 100644 --- a/web/pages/sign-in.tsx +++ b/web/pages/sign-in.tsx @@ -51,7 +51,7 @@ const SignInPage: NextPageWithLayout = observer(() => { New to Plane?{" "} captureEvent(NAVIGATE_TO_SIGNUP, {})} + onClick={() => captureEvent(NAVIGATE_TO_SIGNUP)} className="font-semibold text-custom-primary-100 hover:underline" > Create an account