Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 25 additions & 15 deletions packages/constants/src/event-tracker/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export const getProjectEventPayload = (payload: any) => ({
element: payload.element,
});


export const getPageEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.project,
Expand Down Expand Up @@ -208,35 +207,46 @@ export const AUTH_TRACKER_EVENTS = {
forgot_password: "forgot_password_clicked",
};

export const PRODUCT_TOUR_TRACKER_EVENTS = {
start: "product_tour_started",
complete: "product_tour_completed",
skip: "product_tour_skipped",
};

export const GLOBAL_VIEW_TOUR_TRACKER_EVENTS = {
export const GLOBAL_VIEW_TRACKER_EVENTS = {
create: "global_view_created",
update: "global_view_updated",
delete: "global_view_deleted",
open: "global_view_opened",
};
export const GLOBAL_VIEW_TRACKER_ELEMENTS = {
RIGHT_HEADER_ADD_BUTTON: "global_view_right_header_add_button",
HEADER_SAVE_VIEW_BUTTON: "global_view_header_save_view_button",
QUICK_ACTIONS: "global_view_quick_actions",
LIST_ITEM: "global_view_list_item",
};

export const PRODUCT_TOUR_TRACKER_EVENTS = {
complete: "product_tour_completed",
};
export const PRODUCT_TOUR_TRACKER_ELEMENTS = {
START_BUTTON: "product_tour_start_button",
SKIP_BUTTON: "product_tour_skip_button",
CREATE_PROJECT_BUTTON: "product_tour_create_project_button",
};

export const NOTIFICATION_TRACKER_EVENTS = {
archive: "notification_archived",
all_marked_read: "all_notifications_marked_read",
};
export const NOTIFICATION_TRACKER_ELEMENTS = {
MARK_ALL_AS_READ_BUTTON: "mark_all_as_read_button",
ARCHIVE_BUTTON: "archive_button",
MARK_READ_BUTTON: "mark_read_button",
};

export const USER_TRACKER_EVENTS = {
add_details: "user_details_added",
onboarding_complete: "user_onboarding_completed",
};

export const ONBOARDING_TRACKER_EVENTS = {
root: "onboarding",
step_1: "onboarding_step_1",
step_2: "onboarding_step_2",
export const ONBOARDING_TRACKER_ELEMENTS = {
PROFILE_SETUP_FORM: "onboarding_profile_setup_form",
};

export const SIDEBAR_TRACKER_EVENTS = {
click: "sidenav_clicked",
export const SIDEBAR_TRACKER_ELEMENTS = {
USER_MENU_ITEM: "sidenav_user_menu_item",
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
EIssueFilterType,
EIssuesStoreType,
ISSUE_DISPLAY_FILTERS_BY_PAGE,
EIssueLayoutTypes
EIssueLayoutTypes,
GLOBAL_VIEW_TRACKER_ELEMENTS,
} from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// types
Expand Down Expand Up @@ -228,7 +229,12 @@ export const GlobalIssuesHeader = observer(() => {
<></>
)}

<Button variant="primary" size="sm" onClick={() => setCreateViewModal(true)}>
<Button
variant="primary"
size="sm"
data-ph-element={GLOBAL_VIEW_TRACKER_ELEMENTS.RIGHT_HEADER_ADD_BUTTON}
onClick={() => setCreateViewModal(true)}
>
{t("workspace_views.add_view")}
</Button>
<div className="hidden md:block">
Expand Down
14 changes: 8 additions & 6 deletions web/app/(all)/onboarding/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import { USER_WORKSPACES_LIST } from "@/constants/fetch-keys";
// helpers
import { EPageTypes } from "@/helpers/authentication.helper";
// hooks
import { useUser, useWorkspace, useUserProfile, useEventTracker } from "@/hooks/store";
import { captureSuccess } from "@/helpers/event-tracker.helper";
import { useUser, useWorkspace, useUserProfile } from "@/hooks/store";
// wrappers
import { AuthenticationWrapper } from "@/lib/wrappers";
import { WorkspaceService } from "@/plane-web/services";
Expand All @@ -35,7 +36,6 @@ const OnboardingPage = observer(() => {
const [step, setStep] = useState<EOnboardingSteps | null>(null);
const [totalSteps, setTotalSteps] = useState<number | null>(null);
// store hooks
const { captureEvent } = useEventTracker();
const { isLoading: userLoader, data: user, updateCurrentUser } = useUser();
const { data: profile, updateUserProfile, finishUserOnboarding } = useUserProfile();
const { workspaces, fetchWorkspaces } = useWorkspace();
Expand Down Expand Up @@ -73,10 +73,12 @@ const OnboardingPage = observer(() => {

await finishUserOnboarding()
.then(() => {
captureEvent(USER_TRACKER_EVENTS.onboarding_complete, {
email: user.email,
user_id: user.id,
status: "SUCCESS",
captureSuccess({
eventName: USER_TRACKER_EVENTS.onboarding_complete,
payload: {
email: user.email,
user_id: user.id,
},
});
})
.catch(() => {
Expand Down
18 changes: 11 additions & 7 deletions web/core/components/home/root.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
// components
import useSWR from "swr";
// plane imports
import { PRODUCT_TOUR_TRACKER_EVENTS } from "@plane/constants";
import { ContentWrapper } from "@plane/ui";
import { cn } from "@plane/utils";
// components
import { TourRoot } from "@/components/onboarding";
// constants
// helpers
import { captureSuccess } from "@/helpers/event-tracker.helper";
// hooks
import { useUserProfile, useEventTracker, useUser } from "@/hooks/store";
import { useUserProfile, useUser } from "@/hooks/store";
import { useHome } from "@/hooks/store/use-home";
import useSize from "@/hooks/use-window-size";
// plane web components
import { HomePeekOverviewsRoot } from "@/plane-web/components/home";
// local imports
import { DashboardWidgets } from "./home-dashboard-widgets";
import { UserGreetingsView } from "./user-greetings";

Expand All @@ -21,7 +24,6 @@ export const WorkspaceHomeView = observer(() => {
const { workspaceSlug } = useParams();
const { data: currentUser } = useUser();
const { data: currentUserProfile, updateTourCompleted } = useUserProfile();
const { captureEvent } = useEventTracker();
const { toggleWidgetSettings, fetchWidgets } = useHome();
const [windowWidth] = useSize();

Expand All @@ -38,9 +40,11 @@ export const WorkspaceHomeView = observer(() => {
const handleTourCompleted = () => {
updateTourCompleted()
.then(() => {
captureEvent(PRODUCT_TOUR_TRACKER_EVENTS.complete, {
user_id: currentUser?.id,
state: "SUCCESS",
captureSuccess({
eventName: PRODUCT_TOUR_TRACKER_EVENTS.complete,
payload: {
user_id: currentUser?.id,
},
});
})
.catch((error) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
EViewAccess,
EUserPermissions,
EUserPermissionsLevel,
GLOBAL_VIEW_TOUR_TRACKER_EVENTS,
GLOBAL_VIEW_TRACKER_EVENTS,
} from "@plane/constants";
import { IIssueFilterOptions, TStaticViewTypes } from "@plane/types";
//ui
Expand All @@ -26,7 +26,8 @@ import { CreateUpdateWorkspaceViewModal } from "@/components/workspace";
// constants
// helpers
// hooks
import { useEventTracker, useGlobalView, useIssues, useLabel, useUser, useUserPermissions } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useGlobalView, useIssues, useLabel, useUser, useUserPermissions } from "@/hooks/store";
import { getAreFiltersEqual } from "../../../utils";

type Props = {
Expand All @@ -44,7 +45,6 @@ export const GlobalViewsAppliedFiltersRoot = observer((props: Props) => {
} = useIssues(EIssuesStoreType.GLOBAL);
const { workspaceLabels } = useLabel();
const { globalViewMap, updateGlobalView } = useGlobalView();
const { captureEvent } = useEventTracker();
const { data } = useUser();
const { allowPermissions } = useUserPermissions();

Expand Down Expand Up @@ -112,15 +112,25 @@ export const GlobalViewsAppliedFiltersRoot = observer((props: Props) => {
const handleUpdateView = () => {
if (!workspaceSlug || !globalViewId) return;

updateGlobalView(workspaceSlug.toString(), globalViewId.toString(), viewFilters).then((res) => {
if (res)
captureEvent(GLOBAL_VIEW_TOUR_TRACKER_EVENTS.update, {
view_id: res.id,
applied_filters: res.filters,
state: "SUCCESS",
element: "Spreadsheet view",
updateGlobalView(workspaceSlug.toString(), globalViewId.toString(), viewFilters)
.then((res) => {
if (res)
captureSuccess({
eventName: GLOBAL_VIEW_TRACKER_EVENTS.update,
payload: {
view_id: globalViewId,
},
});
})
.catch((error) => {
captureError({
eventName: GLOBAL_VIEW_TRACKER_EVENTS.update,
payload: {
view_id: globalViewId,
},
error: error,
});
});
});
};

// add a placeholder object instead of appliedFilters if it is undefined
Expand Down
46 changes: 24 additions & 22 deletions web/core/components/onboarding/profile-setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Image from "next/image";
import { useTheme } from "next-themes";
import { Controller, useForm } from "react-hook-form";
import { Eye, EyeOff } from "lucide-react";
import { E_PASSWORD_STRENGTH, ONBOARDING_TRACKER_EVENTS, USER_TRACKER_EVENTS } from "@plane/constants";
import { E_PASSWORD_STRENGTH, ONBOARDING_TRACKER_ELEMENTS, USER_TRACKER_EVENTS } from "@plane/constants";
// types
import { useTranslation } from "@plane/i18n";
import { IUser, TUserProfile, TOnboardingSteps } from "@plane/types";
Expand All @@ -20,7 +20,8 @@ import { OnboardingHeader, SwitchAccountDropdown } from "@/components/onboarding
// constants
// helpers
// hooks
import { useEventTracker, useUser, useUserProfile } from "@/hooks/store";
import { captureError, captureSuccess, captureView } from "@/helpers/event-tracker.helper";
import { useUser, useUserProfile } from "@/hooks/store";
// assets
import ProfileSetupDark from "@/public/onboarding/profile-setup-dark.webp";
import ProfileSetupLight from "@/public/onboarding/profile-setup-light.webp";
Expand Down Expand Up @@ -98,7 +99,6 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
// store hooks
const { updateCurrentUser } = useUser();
const { updateUserProfile } = useUserProfile();
const { captureEvent } = useEventTracker();
// form info
const {
getValues,
Expand Down Expand Up @@ -143,11 +143,12 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
updateUserProfile(profileUpdatePayload),
totalSteps > 2 && stepChange({ profile_complete: true }),
]);
captureEvent(USER_TRACKER_EVENTS.add_details, {
use_case: formData.use_case,
role: formData.role,
state: "SUCCESS",
element: ONBOARDING_TRACKER_EVENTS.step_1,
captureSuccess({
eventName: USER_TRACKER_EVENTS.add_details,
payload: {
use_case: formData.use_case,
role: formData.role,
},
});
setToast({
type: TOAST_TYPE.SUCCESS,
Expand All @@ -159,9 +160,8 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
finishOnboarding();
}
} catch {
captureEvent(USER_TRACKER_EVENTS.add_details, {
state: "FAILED",
element: ONBOARDING_TRACKER_EVENTS.step_1,
captureError({
eventName: USER_TRACKER_EVENTS.add_details,
});
setToast({
type: TOAST_TYPE.ERROR,
Expand All @@ -183,9 +183,8 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
formData.password && handleSetPassword(formData.password),
]).then(() => setProfileSetupStep(EProfileSetupSteps.USER_PERSONALIZATION));
} catch {
captureEvent(USER_TRACKER_EVENTS.add_details, {
state: "FAILED",
element: ONBOARDING_TRACKER_EVENTS.step_1,
captureError({
eventName: USER_TRACKER_EVENTS.add_details,
});
setToast({
type: TOAST_TYPE.ERROR,
Expand All @@ -205,11 +204,12 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
updateUserProfile(profileUpdatePayload),
totalSteps > 2 && stepChange({ profile_complete: true }),
]);
captureEvent(USER_TRACKER_EVENTS.add_details, {
use_case: formData.use_case,
role: formData.role,
state: "SUCCESS",
element: ONBOARDING_TRACKER_EVENTS.step_2,
captureSuccess({
eventName: USER_TRACKER_EVENTS.add_details,
payload: {
use_case: formData.use_case,
role: formData.role,
},
});
setToast({
type: TOAST_TYPE.SUCCESS,
Expand All @@ -221,9 +221,8 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
finishOnboarding();
}
} catch {
captureEvent(USER_TRACKER_EVENTS.add_details, {
state: "FAILED",
element: ONBOARDING_TRACKER_EVENTS.step_2,
captureError({
eventName: USER_TRACKER_EVENTS.add_details,
});
setToast({
type: TOAST_TYPE.ERROR,
Expand All @@ -235,6 +234,9 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {

const onSubmit = async (formData: TProfileSetupFormValues) => {
if (!user) return;
captureView({
elementName: ONBOARDING_TRACKER_ELEMENTS.PROFILE_SETUP_FORM,
});
if (profileSetupStep === EProfileSetupSteps.ALL) await handleSubmitProfileSetup(formData);
if (profileSetupStep === EProfileSetupSteps.USER_DETAILS) await handleSubmitUserDetail(formData);
if (profileSetupStep === EProfileSetupSteps.USER_PERSONALIZATION) await handleSubmitUserPersonalization(formData);
Expand Down
Loading