diff --git a/web/app/components/app/create-app-dialog/app-list/index.tsx b/web/app/components/app/create-app-dialog/app-list/index.tsx index 8b19f43034..bef0292668 100644 --- a/web/app/components/app/create-app-dialog/app-list/index.tsx +++ b/web/app/components/app/create-app-dialog/app-list/index.tsx @@ -28,6 +28,7 @@ import Input from '@/app/components/base/input' import { AppModeEnum } from '@/types/app' import { DSLImportMode } from '@/models/app' import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks' +import { trackEvent } from '@/app/components/base/amplitude' type AppsProps = { onSuccess?: () => void @@ -141,6 +142,16 @@ const Apps = ({ icon_background, description, }) + + // Track app creation from template + trackEvent('app_created', { + app_mode: mode, + creation_method: 'template', + template_id: currApp?.app.id, + template_name: currApp?.app.name, + has_description: !!description, + }) + setIsShowCreateModal(false) Toast.notify({ type: 'success', diff --git a/web/app/components/app/create-app-modal/index.tsx b/web/app/components/app/create-app-modal/index.tsx index 10fc099f9f..519b3469a5 100644 --- a/web/app/components/app/create-app-modal/index.tsx +++ b/web/app/components/app/create-app-modal/index.tsx @@ -30,6 +30,7 @@ import { getRedirection } from '@/utils/app-redirection' import FullScreenModal from '@/app/components/base/fullscreen-modal' import useTheme from '@/hooks/use-theme' import { useDocLink } from '@/context/i18n' +import { trackEvent } from '@/app/components/base/amplitude' type CreateAppProps = { onSuccess: () => void @@ -82,6 +83,14 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate, defaultAppMode }: icon_background: appIcon.type === 'emoji' ? appIcon.background : undefined, mode: appMode, }) + + // Track app creation success + trackEvent('app_created', { + app_mode: appMode, + creation_method: 'blank', + has_description: !!description, + }) + notify({ type: 'success', message: t('app.newApp.appCreated') }) onSuccess() onClose() diff --git a/web/app/components/app/create-from-dsl-modal/index.tsx b/web/app/components/app/create-from-dsl-modal/index.tsx index 0c137abb71..2af91d388d 100644 --- a/web/app/components/app/create-from-dsl-modal/index.tsx +++ b/web/app/components/app/create-from-dsl-modal/index.tsx @@ -28,6 +28,7 @@ import { getRedirection } from '@/utils/app-redirection' import cn from '@/utils/classnames' import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks' import { noop } from 'lodash-es' +import { trackEvent } from '@/app/components/base/amplitude' type CreateFromDSLModalProps = { show: boolean @@ -112,6 +113,13 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS return const { id, status, app_id, app_mode, imported_dsl_version, current_dsl_version } = response if (status === DSLImportStatus.COMPLETED || status === DSLImportStatus.COMPLETED_WITH_WARNINGS) { + // Track app creation from DSL import + trackEvent('app_created', { + app_mode, + creation_method: currentTab === CreateFromDSLModalTab.FROM_FILE ? 'dsl_file' : 'dsl_url', + has_warnings: status === DSLImportStatus.COMPLETED_WITH_WARNINGS, + }) + if (onSuccess) onSuccess() if (onClose) diff --git a/web/app/install/installForm.tsx b/web/app/install/installForm.tsx index 01bfd59b6d..44c8560b3c 100644 --- a/web/app/install/installForm.tsx +++ b/web/app/install/installForm.tsx @@ -19,6 +19,7 @@ import type { InitValidateStatusResponse, SetupStatusResponse } from '@/models/c import useDocumentTitle from '@/hooks/use-document-title' import { useDocLink } from '@/context/i18n' import { validPassword } from '@/config' +import { trackEvent } from '@/app/components/base/amplitude' const accountFormSchema = z.object({ email: z @@ -73,6 +74,15 @@ const InstallForm = () => { // Store tokens and redirect to apps if login successful if (loginRes.result === 'success') { + // Track initial setup completion + trackEvent('user_registration_success', { + method: 'initial_setup', + }) + trackEvent('user_login_success', { + method: 'initial_setup', + is_invite: false, + }) + router.replace('/apps') } else { diff --git a/web/app/signin/check-code/page.tsx b/web/app/signin/check-code/page.tsx index 67e268a761..4af2bdd1cc 100644 --- a/web/app/signin/check-code/page.tsx +++ b/web/app/signin/check-code/page.tsx @@ -11,6 +11,7 @@ import Toast from '@/app/components/base/toast' import { emailLoginWithCode, sendEMailLoginCode } from '@/service/common' import I18NContext from '@/context/i18n' import { resolvePostLoginRedirect } from '../utils/post-login-redirect' +import { trackEvent } from '@/app/components/base/amplitude' export default function CheckCode() { const { t, i18n } = useTranslation() @@ -44,6 +45,12 @@ export default function CheckCode() { setIsLoading(true) const ret = await emailLoginWithCode({ email, code, token, language }) if (ret.result === 'success') { + // Track login success event + trackEvent('user_login_success', { + method: 'email_code', + is_invite: !!invite_token, + }) + if (invite_token) { router.replace(`/signin/invite-settings?${searchParams.toString()}`) } diff --git a/web/app/signin/components/mail-and-password-auth.tsx b/web/app/signin/components/mail-and-password-auth.tsx index 2740a82782..ba37087719 100644 --- a/web/app/signin/components/mail-and-password-auth.tsx +++ b/web/app/signin/components/mail-and-password-auth.tsx @@ -12,6 +12,7 @@ import I18NContext from '@/context/i18n' import { noop } from 'lodash-es' import { resolvePostLoginRedirect } from '../utils/post-login-redirect' import type { ResponseError } from '@/service/fetch' +import { trackEvent } from '@/app/components/base/amplitude' type MailAndPasswordAuthProps = { isInvite: boolean @@ -63,6 +64,12 @@ export default function MailAndPasswordAuth({ isInvite, isEmailSetup, allowRegis body: loginData, }) if (res.result === 'success') { + // Track login success event + trackEvent('user_login_success', { + method: 'email_password', + is_invite: isInvite, + }) + if (isInvite) { router.replace(`/signin/invite-settings?${searchParams.toString()}`) } diff --git a/web/app/signup/set-password/page.tsx b/web/app/signup/set-password/page.tsx index d4fc36a232..1e176b8d2f 100644 --- a/web/app/signup/set-password/page.tsx +++ b/web/app/signup/set-password/page.tsx @@ -9,6 +9,7 @@ import Input from '@/app/components/base/input' import { validPassword } from '@/config' import type { MailRegisterResponse } from '@/service/use-common' import { useMailRegister } from '@/service/use-common' +import { trackEvent } from '@/app/components/base/amplitude' const ChangePasswordForm = () => { const { t } = useTranslation() @@ -54,6 +55,11 @@ const ChangePasswordForm = () => { }) const { result } = res as MailRegisterResponse if (result === 'success') { + // Track registration success event + trackEvent('user_registration_success', { + method: 'email', + }) + Toast.notify({ type: 'success', message: t('common.api.actionSuccess'),