diff --git a/apps/mobile/app/(app)/onboarding.tsx b/apps/mobile/app/(app)/onboarding.tsx index 065dff7..2d5e53c 100644 --- a/apps/mobile/app/(app)/onboarding.tsx +++ b/apps/mobile/app/(app)/onboarding.tsx @@ -159,6 +159,7 @@ export default function OnboardingScreen() { console.log('[Onboarding] Profile updated successfully, fetching user...'); await fetchUser(); console.log('[Onboarding] User fetched, navigating to home...'); + Events.profileUpdated(["name", "gender", "usage_reason", "show_explicit_content"]); Events.onboardingComplete(); router.replace('/'); } catch (err: any) { diff --git a/apps/mobile/app/(app)/profile.tsx b/apps/mobile/app/(app)/profile.tsx index 39af3e5..f421614 100755 --- a/apps/mobile/app/(app)/profile.tsx +++ b/apps/mobile/app/(app)/profile.tsx @@ -121,6 +121,7 @@ export default function ProfileScreen() { // Refresh user data and packs to reflect the change await fetchUser(); await fetchPacks(); + Events.profileUpdated(["show_explicit_content"]); } catch (error) { // Revert on error setShowExplicit(!value); @@ -174,6 +175,7 @@ export default function ProfileScreen() { await fetchUser(); setIsEditingName(false); + Events.profileUpdated(["name"]); } catch (error) { Alert.alert("Error", "Failed to update name. Please try again."); setNewName(user.name || ""); diff --git a/apps/mobile/app/_layout.tsx b/apps/mobile/app/_layout.tsx index 3bf709c..7edd825 100755 --- a/apps/mobile/app/_layout.tsx +++ b/apps/mobile/app/_layout.tsx @@ -6,9 +6,12 @@ import { initSentry, setUserContext, clearUserContext } from "../src/lib/sentry" initSentry(); // Initialize Analytics -import { initAnalytics, setUserId, clearUserId, logScreenView } from "../src/lib/analytics"; +import { initAnalytics, setUserId, clearUserId, logScreenView, Events } from "../src/lib/analytics"; initAnalytics(); +// Track cold start immediately +Events.appOpened("cold"); + // Import push notification utilities import { clearPushToken, @@ -17,8 +20,8 @@ import { handleNotificationResponse, } from "../src/lib/notifications"; -import React, { useEffect } from "react"; -import { Platform, View } from "react-native"; +import React, { useEffect, useRef } from "react"; +import { Platform, View, AppState, AppStateStatus } from "react-native"; // Suppress useLayoutEffect warning on server-side rendering if (Platform.OS === "web" && typeof window === "undefined") { @@ -50,6 +53,7 @@ const queryClient = new QueryClient(); export default function RootLayout() { const { fetchUser, setUser } = useAuthStore(); const pathname = usePathname(); + const appState = useRef(AppState.currentState); // Track screen views useEffect(() => { @@ -58,6 +62,18 @@ export default function RootLayout() { } }, [pathname]); + // Track warm starts when app comes back from background + useEffect(() => { + const subscription = AppState.addEventListener("change", (nextAppState: AppStateStatus) => { + if (appState.current.match(/inactive|background/) && nextAppState === "active") { + Events.appOpened("warm"); + } + appState.current = nextAppState; + }); + + return () => subscription.remove(); + }, []); + useEffect(() => { // Fetch user on mount fetchUser();