diff --git a/app/client/src/components/editorComponents/DraggableComponent.tsx b/app/client/src/components/editorComponents/DraggableComponent.tsx index 0ace1e967d..6cd6ad770b 100644 --- a/app/client/src/components/editorComponents/DraggableComponent.tsx +++ b/app/client/src/components/editorComponents/DraggableComponent.tsx @@ -18,6 +18,7 @@ import { useShowPropertyPane, useWidgetDragResize, } from "utils/hooks/dragResizeHooks"; +import AnalyticsUtil from "utils/AnalyticsUtil"; // FontSizes array in DefaultTheme.tsx // Change this to toggle the size of delete and move handles. @@ -126,6 +127,10 @@ const DraggableComponent = (props: DraggableComponentProps) => { ); const deleteWidget = () => { + AnalyticsUtil.logEvent("WIDGET_DELETE", { + widgetName: props.widgetName, + widgetType: props.type, + }); showPropertyPane && showPropertyPane(); updateWidget && updateWidget(WidgetOperations.DELETE, props.widgetId, { @@ -153,6 +158,10 @@ const DraggableComponent = (props: DraggableComponentProps) => { isCurrentWidgetDragging: monitor.isDragging(), }), begin: () => { + AnalyticsUtil.logEvent("WIDGET_DRAG", { + widgetName: props.widgetName, + widgetType: props.type, + }); showPropertyPane && showPropertyPane(undefined, true); selectWidget && selectWidget(props.widgetId); setIsDragging && setIsDragging(true); @@ -161,6 +170,10 @@ const DraggableComponent = (props: DraggableComponentProps) => { if (monitor.didDrop()) { showPropertyPane && showPropertyPane(props.widgetId, true); } + AnalyticsUtil.logEvent("WIDGET_DROP", { + widgetName: props.widgetName, + widgetType: props.type, + }); setIsDragging && setIsDragging(false); }, canDrag: () => { diff --git a/app/client/src/components/editorComponents/ResizableComponent.tsx b/app/client/src/components/editorComponents/ResizableComponent.tsx index c116c6aa4b..aad7c8ff25 100644 --- a/app/client/src/components/editorComponents/ResizableComponent.tsx +++ b/app/client/src/components/editorComponents/ResizableComponent.tsx @@ -40,6 +40,7 @@ import { BottomLeftHandleStyles, BottomRightHandleStyles, } from "./ResizeStyledComponents"; +import AnalyticsUtil from "utils/AnalyticsUtil"; export type ResizableComponentProps = ContainerWidgetProps & { paddingOffset: number; @@ -245,6 +246,15 @@ export const ResizableComponent = memo((props: ResizableComponentProps) => { showPropertyPane && propertyPaneState.widgetId !== props.widgetId && showPropertyPane(props.widgetId, true); + + AnalyticsUtil.logEvent("WIDGET_RESIZE_END", { + widgetName: props.widgetName, + widgetType: props.type, + startHeight: dimensions.height, + startWidth: dimensions.width, + endHeight: newDimensions.height, + endWidth: newDimensions.width, + }); }; const handleResizeStart = () => { @@ -253,6 +263,10 @@ export const ResizableComponent = memo((props: ResizableComponentProps) => { selectedWidget !== props.widgetId && selectWidget(props.widgetId); showPropertyPane && showPropertyPane(props.widgetId, true); + AnalyticsUtil.logEvent("WIDGET_RESIZE_START", { + widgetName: props.widgetName, + widgetType: props.type, + }); }; return ( diff --git a/app/client/src/constants/ReduxActionConstants.tsx b/app/client/src/constants/ReduxActionConstants.tsx index 1e5728f8f0..ab0f58c063 100644 --- a/app/client/src/constants/ReduxActionConstants.tsx +++ b/app/client/src/constants/ReduxActionConstants.tsx @@ -258,12 +258,14 @@ export interface ShowPropertyPanePayload { callForDragOrResize: boolean; } -export type PageListPayload = Array<{ +export interface Page { pageName: string; pageId: string; isDefault: boolean; latest?: boolean; -}>; +} + +export type PageListPayload = Array; export type ApplicationPayload = { id: string; diff --git a/app/client/src/pages/AppViewer/viewer/SideNavItem.tsx b/app/client/src/pages/AppViewer/viewer/SideNavItem.tsx index a9c2ed9443..07fdfbb74e 100644 --- a/app/client/src/pages/AppViewer/viewer/SideNavItem.tsx +++ b/app/client/src/pages/AppViewer/viewer/SideNavItem.tsx @@ -2,6 +2,7 @@ import React, { ReactNode } from "react"; import styled from "styled-components"; import { NavLink, useRouteMatch } from "react-router-dom"; import { MenuItem, Classes } from "@blueprintjs/core"; +import AnalyticsUtil from "utils/AnalyticsUtil"; const Content = styled.div<{ collapsed: boolean }>` display: flex; @@ -34,7 +35,17 @@ export const SideNavItem = (props: SideNavItemProps) => { ); return ( - + { + AnalyticsUtil.logEvent("PAGE_SWITCH", { + pageName: props.text, + pageId: props.id, + mode: "VIEW", + }); + }} + > { const onEditPageName = (name: string) => { props.updatePage(props.id, name); + AnalyticsUtil.logEvent("PAGE_RENAME", { + pageName: props.name, + newName: name, + pageId: props.id, + }); }; const pageIcon = props.isDefault ? ( MenuIcons.HOMEPAGE_ICON({ width: 28, height: 28 }) diff --git a/app/client/src/pages/Editor/PageListSidebar/index.tsx b/app/client/src/pages/Editor/PageListSidebar/index.tsx index 05701b3c38..fc3bf72559 100644 --- a/app/client/src/pages/Editor/PageListSidebar/index.tsx +++ b/app/client/src/pages/Editor/PageListSidebar/index.tsx @@ -4,12 +4,14 @@ import { useSelector, useDispatch } from "react-redux"; import { ReduxActionTypes, PageListPayload, + Page, } from "constants/ReduxActionConstants"; import { AppState } from "reducers"; import { PAGE_LIST_EDITOR_URL } from "constants/routes"; import { ContextDropdownOption } from "components/editorComponents/ContextDropdown"; import PageListItem from "./PageListItem"; import CreatePageButton from "./CreatePageButton"; +import AnalyticsUtil from "utils/AnalyticsUtil"; /** Page List */ @@ -34,9 +36,14 @@ const PageListSidebar = () => { /* Navigation */ const { pageId } = useParams(); const history = useHistory(); - const switchPage = (id: string): void => { - if (id !== pageId) { - history.push(PAGE_LIST_EDITOR_URL(applicationId, id)); + const switchPage = (page: Page): void => { + AnalyticsUtil.logEvent("PAGE_SWITCH", { + pageName: page.pageName, + pageId: page.pageId, + mode: "EDIT", + }); + if (page.pageId !== pageId) { + history.push(PAGE_LIST_EDITOR_URL(applicationId, page.pageId)); } }; @@ -61,6 +68,9 @@ const PageListSidebar = () => { name, }, }); + AnalyticsUtil.logEvent("CREATE_PAGE", { + pageName: name, + }); } }; @@ -82,13 +92,16 @@ const PageListSidebar = () => { } }; - const deletePage = (pageId: string): void => { + const deletePage = (page: Page): void => { dispatch({ type: ReduxActionTypes.DELETE_PAGE_INIT, payload: { - pageId, + pageId: page.pageId, }, }); + AnalyticsUtil.logEvent("DELETE_PAGE", { + pageName: page.pageName, + }); }; const setPageAsDefault = (pageId: string, applicationId?: string): void => { @@ -117,7 +130,7 @@ const PageListSidebar = () => { }, { value: "delete", - onSelect: () => deletePage(page.pageId), + onSelect: () => deletePage(page), intent: "danger", label: "Delete", }, @@ -128,7 +141,7 @@ const PageListSidebar = () => { name={page.pageName} id={page.pageId} updatePage={updatePage} - switchPage={switchPage} + switchPage={() => switchPage(page)} active={page.pageId === pageId} isDefault={defaultPageId === page.pageId} contextActions={pageActions} diff --git a/app/client/src/pages/Editor/PropertyPane/index.tsx b/app/client/src/pages/Editor/PropertyPane/index.tsx index 3a4f5a1e25..1c702b9034 100644 --- a/app/client/src/pages/Editor/PropertyPane/index.tsx +++ b/app/client/src/pages/Editor/PropertyPane/index.tsx @@ -28,6 +28,7 @@ import { theme } from "constants/DefaultTheme"; import { WidgetProps } from "widgets/BaseWidget"; import PropertyPaneTitle from "pages/Editor/PropertyPaneTitle"; import PropertyControl from "pages/Editor/PropertyPane/PropertyControl"; +import AnalyticsUtil from "utils/AnalyticsUtil"; const PropertySectionLabel = styled.div` text-transform: uppercase; @@ -152,6 +153,14 @@ class PropertyPane extends Component< propertyName, !isDynamic, ); + if (this.props.widgetProperties) { + AnalyticsUtil.logEvent("WIDGET_TOGGLE_JS_PROP", { + widgetType: this.props.widgetProperties.type, + widgetName: this.props.widgetProperties.widgetName, + propertyName: propertyName, + propertyState: !isDynamic ? "JS" : "NORMAL", + }); + } }; onPropertyChange(propertyName: string, propertyValue: any) { @@ -160,6 +169,14 @@ class PropertyPane extends Component< propertyName, propertyValue, ); + if (this.props.widgetProperties) { + AnalyticsUtil.logEvent("WIDGET_PROPERTY_UPDATE", { + widgetType: this.props.widgetProperties.type, + widgetName: this.props.widgetProperties.widgetName, + propertyName: propertyName, + updatedValue: propertyValue, + }); + } } } diff --git a/app/client/src/pages/Editor/WidgetCard.tsx b/app/client/src/pages/Editor/WidgetCard.tsx index 562ed3cd5d..8228c89249 100644 --- a/app/client/src/pages/Editor/WidgetCard.tsx +++ b/app/client/src/pages/Editor/WidgetCard.tsx @@ -8,6 +8,7 @@ import { useWidgetDragResize, useShowPropertyPane, } from "utils/hooks/dragResizeHooks"; +import AnalyticsUtil from "utils/AnalyticsUtil"; type CardProps = { details: WidgetCardProps; @@ -68,10 +69,18 @@ const WidgetCard = (props: CardProps) => { isDragging: monitor.isDragging(), }), begin: () => { + AnalyticsUtil.logEvent("WIDGET_CARD_DRAG", { + widgetType: props.details.type, + widgetName: props.details.widgetCardName, + }); showPropertyPane && showPropertyPane(undefined); setIsDragging && setIsDragging(true); }, end: () => { + AnalyticsUtil.logEvent("WIDGET_CARD_DROP", { + widgetType: props.details.type, + widgetName: props.details.widgetCardName, + }); setIsDragging && setIsDragging(false); }, }); diff --git a/app/client/src/sagas/userSagas.tsx b/app/client/src/sagas/userSagas.tsx index 13cf39b284..7a51aa3f10 100644 --- a/app/client/src/sagas/userSagas.tsx +++ b/app/client/src/sagas/userSagas.tsx @@ -35,6 +35,7 @@ import { invitedUserSignupError, invitedUserSignupSuccess, } from "actions/userActions"; +import AnalyticsUtil from "utils/AnalyticsUtil"; export function* createUserSaga( action: ReduxActionWithPromise, @@ -287,6 +288,7 @@ export function* fetchUserSaga(action: ReduxAction) { export function* setCurrentUserSaga(action: ReduxAction) { const me = yield call(fetchUserSaga, action); if (me) { + AnalyticsUtil.identifyUser(me.id, me); resetAuthExpiration(); yield put({ type: ReduxActionTypes.SET_CURRENT_USER_SUCCESS, diff --git a/app/client/src/utils/AnalyticsUtil.tsx b/app/client/src/utils/AnalyticsUtil.tsx index cd0fe8c45a..7eca0e5e7f 100644 --- a/app/client/src/utils/AnalyticsUtil.tsx +++ b/app/client/src/utils/AnalyticsUtil.tsx @@ -1,8 +1,23 @@ +// Events export type EventName = | "PAGE_VIEW" | "ADD_COMPONENT" | "DELETE_COMPONENT" - | "RESIZE_COMPONENT"; + | "RESIZE_COMPONENT" + | "WIDGET_DRAG" + | "WIDGET_DROP" + | "WIDGET_DELETE" + | "WIDGET_RESIZE_START" + | "WIDGET_RESIZE_END" + | "WIDGET_PROPERTY_UPDATE" + | "WIDGET_TOGGLE_JS_PROP" + | "WIDGET_CARD_DRAG" + | "WIDGET_CARD_DROP" + | "CREATE_PAGE" + | "PAGE_RENAME" + | "PAGE_SWITCH" + | "DELETE_PAGE"; + export type Gender = "MALE" | "FEMALE"; export interface User { userId: string; @@ -90,12 +105,18 @@ class AnalyticsUtil { static logEvent(eventName: EventName, eventData: any) { const windowDoc: any = window; - windowDoc.analytics.track(eventName, eventData); + if (windowDoc.analytics) { + windowDoc.analytics.track(eventName, eventData); + } else { + console.log("Event fired", eventName, eventData); + } } static identifyUser(userId: string, userData: User) { const windowDoc: any = window; - windowDoc.analytics.identify(userId, userData); + if (windowDoc.analytics) { + windowDoc.analytics.identify(userId, userData); + } } }