diff --git a/apps/app/app/api/mixpanel/identify/route.ts b/apps/app/app/api/mixpanel/identify/route.ts
new file mode 100644
index 00000000..0a7a568e
--- /dev/null
+++ b/apps/app/app/api/mixpanel/identify/route.ts
@@ -0,0 +1,103 @@
+import { NextResponse } from "next/server";
+import { app, mixpanel } from "@/lib/env";
+import type { Mixpanel } from "mixpanel";
+const MixpanelLib = require("mixpanel");
+
+let mixpanelClient: Mixpanel | null = null;
+if (mixpanel.projectToken) {
+  mixpanelClient = MixpanelLib.init(mixpanel.projectToken);
+}
+
+async function getGeoData(ip: string | null) {
+  if (!ip) return {};
+  
+  try {
+    const response = await fetch(`http://ip-api.com/json/${ip}`);
+    const data = await response.json();
+    return {
+      $city: data.city,
+      $region: data.regionName,
+	  $country_code: data.countryCode,
+      $latitude: data.lat,
+      $longitude: data.lon,
+    };
+  } catch (error) {
+    console.error("Error getting geolocation:", error);
+    return {};
+  }
+}
+
+
+export async function POST(request: Request) {
+	console.log("mixpanel identify request", request);	
+  if (!mixpanelClient) {
+    return NextResponse.json(
+      { error: "Mixpanel not configured" },
+      { status: 500 }
+    );
+  }
+
+  try {
+    const { userId, anonymousId, properties } = await request.json();
+    const { first_time_properties, ...regularProperties } = properties;
+    console.log("mixpanel identify request", userId, anonymousId, properties, regularProperties);
+    // Create alias if needed
+    if (anonymousId !== userId) {
+      mixpanelClient.alias(userId, anonymousId);
+    }
+
+	const forwardedFor = request.headers.get("x-forwarded-for");
+
+	const ip =
+	  app.environment === "dev"
+		? "93.152.210.100" // Hardcoded development IP (truncated ip that resolves to San Francisco)
+		: forwardedFor
+		  ? forwardedFor.split(",")[0].trim()
+		  : "127.0.0.1";
+  
+	let geoData = {};
+	if (ip && ip !== "127.0.0.1" && ip !== "::1") {
+	  geoData = await getGeoData(ip);
+	}
+
+	// add geo data to regular properties
+	const setProperties = {
+		...regularProperties,
+		...geoData
+	}
+
+    // Track identify event
+    console.log("mixpanelClient.track('$identify', { distinct_id: userId, ...regularProperties })");
+    mixpanelClient.track('$identify', {
+      distinct_id: userId,
+      ...setProperties
+    });
+
+    // Set regular properties
+    mixpanelClient.people.set(userId, setProperties);
+
+    // Set first-time properties that should only be set once
+    if (first_time_properties) {
+      mixpanelClient.people.set_once(userId, first_time_properties);
+    }
+
+    return NextResponse.json({ status: "User identified successfully" });
+  } catch (error) {
+    console.error("Error identifying user:", error);
+    return NextResponse.json(
+      { error: "Internal Server Error" },
+      { status: 500 }
+    );
+  }
+}
+
+export async function OPTIONS() {
+  return new NextResponse(null, {
+    status: 200,
+    headers: {
+      "Access-Control-Allow-Origin": "*",
+      "Access-Control-Allow-Methods": "POST, OPTIONS",
+      "Access-Control-Allow-Headers": "Content-Type, Authorization",
+    },
+  });
+} 
\ No newline at end of file
diff --git a/apps/app/app/layout.tsx b/apps/app/app/layout.tsx
index 402bb163..550500d1 100644
--- a/apps/app/app/layout.tsx
+++ b/apps/app/app/layout.tsx
@@ -10,7 +10,6 @@ import Intercom from "@/components/intercom";
 import { AlarmCheck } from "lucide-react";
 import AlphaBanner from "@/components/header/alpha-banner";
 import { Metadata } from "next";
-import SessionTracker from "@/components/analytics/SessionTracker";
 import { MixpanelProvider } from "@/components/analytics/MixpanelProvider";
 import { VersionInfo } from '@/components/footer/version-info';
 
@@ -27,7 +26,6 @@ const RootLayout = ({ children }: RootLayoutProperties) => (
     <body className="bg-sidebar">
       <DesignSystemProvider defaultTheme="dark">
         <MixpanelProvider>
-          <SessionTracker />
           <AlphaBanner />
           <SidebarProvider>
             <GlobalSidebar>
diff --git a/apps/app/app/page.tsx b/apps/app/app/page.tsx
index 376b2582..30fff8e4 100644
--- a/apps/app/app/page.tsx
+++ b/apps/app/app/page.tsx
@@ -5,6 +5,7 @@ import { type ReactElement, Suspense } from "react";
 import FeaturedPipelines from "@/components/welcome/featured";
 import { validateEnv } from "@/lib/env";
 import {validateServerEnv} from "@/lib/serverEnv";
+import ClientSideTracker from "@/components/analytics/ClientSideTracker";
 
 const App = async ({
   searchParams,
@@ -16,6 +17,7 @@ const App = async ({
 
   return (
     <div>
+      <ClientSideTracker eventName="home_page_viewed" />
       <div className="flex-shrink-0">
         <Suspense>
           <Welcome />
diff --git a/apps/app/components/analytics/MixpanelProvider.tsx b/apps/app/components/analytics/MixpanelProvider.tsx
index fbbaed91..f3b8a560 100644
--- a/apps/app/components/analytics/MixpanelProvider.tsx
+++ b/apps/app/components/analytics/MixpanelProvider.tsx
@@ -3,12 +3,57 @@
 import { ReactNode, useEffect } from 'react';
 import mixpanel from 'mixpanel-browser';
 import { mixpanel as mixpanelConfig } from '@/lib/env';
+import { usePrivy } from '@privy-io/react-auth';
+
+async function identifyUser(userId: string, anonymousId: string, user: any) {
+  try {
+    const payload = {
+      userId,
+      anonymousId,
+      properties: {
+        $name: userId,
+        distinct_id: userId,
+        $email: user?.email?.address,
+        user_id: userId,
+        user_type: 'authenticated',
+        $last_login: new Date().toISOString(),
+        authenticated: true,
+        first_time_properties: {
+          $first_login: new Date().toISOString(),
+          first_wallet_address: user?.wallet?.address,
+          first_email: user?.email?.address
+        }
+      }
+    };
+    
+    const response = await fetch('/api/mixpanel/identify', {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      body: JSON.stringify(payload)
+    });
+
+    if (!response.ok) {
+      throw new Error(`Failed to identify user: ${response.statusText}`);
+    }
+  } catch (error) {
+    console.error("Error in identifyUser:", error);
+  }
+}
 
 export function MixpanelProvider({ children }: { children: ReactNode }) {
+  const { user, authenticated, ready } = usePrivy();
+
   useEffect(() => {    
     if (mixpanelConfig.projectToken) {
       try {
-        mixpanel.init(mixpanelConfig.projectToken, { debug: true, ignore_dnt: true });
+        mixpanel.init(mixpanelConfig.projectToken, { 
+          debug: true, 
+          ignore_dnt: true,
+          track_pageview: true,
+          persistence: 'localStorage'
+        });
         console.log('Mixpanel initialized successfully');
       } catch (error) {
         console.error('Error initializing Mixpanel:', error);
@@ -18,5 +63,29 @@ export function MixpanelProvider({ children }: { children: ReactNode }) {
     }
   }, []);
 
+  // Handle user identification
+  useEffect(() => {
+    if (!ready) return;
+
+    const handleIdentification = async () => {
+      let distinctId;
+      
+      if (authenticated && user?.id) {
+        distinctId = user.id;
+        // Use server-side identification
+        const anonymousId = localStorage.getItem('mixpanel_anonymous_id') || crypto.randomUUID();
+        await identifyUser(user.id, anonymousId, user);
+        mixpanel.identify(user.id);
+      } else {
+        // For anonymous users
+        distinctId = localStorage.getItem('mixpanel_anonymous_id') || crypto.randomUUID();
+        localStorage.setItem('mixpanel_anonymous_id', distinctId);
+        mixpanel.identify(distinctId);
+      }
+    };
+
+    handleIdentification();
+  }, [user, authenticated, ready]);
+
   return <>{children}</>;
 }
\ No newline at end of file
diff --git a/apps/app/components/analytics/SessionTracker.tsx b/apps/app/components/analytics/SessionTracker.tsx
index 048f0115..7e1c58c4 100644
--- a/apps/app/components/analytics/SessionTracker.tsx
+++ b/apps/app/components/analytics/SessionTracker.tsx
@@ -3,46 +3,48 @@
 import { useEffect } from 'react';
 import track from '@/lib/track';
 import { usePrivy } from '@privy-io/react-auth';
-import mixpanel from 'mixpanel-browser';
-import { mixpanel as mixpanelConfig } from '@/lib/env';
 
-function identifyUser(userId: string, anonymousId: string, user: any) {
+async function identifyUser(userId: string, anonymousId: string, user: any) {
   try {
-    console.log("identifyUser userId:", userId);
-    
-    // First, create the alias if it doesn't exist
-    if (anonymousId !== userId) {
-      console.log("mixpanel.alias", userId, anonymousId);
-      mixpanel.alias(userId, anonymousId);
-    }
-
-    // Then identify the user
-    mixpanel.identify(userId);
-    
-    // Set user properties
-    const userProperties = {
-      $name: userId,  // This helps ensure the user shows up in Mixpanel
-      distinct_id: userId,
-      user_id: userId,
-      user_type: 'authenticated',
-      $last_login: new Date().toISOString(),
-      authenticated: true
+    const payload = {
+      userId,
+      anonymousId,
+      properties: {
+        $name: userId,
+        distinct_id: userId,
+        $email: user?.email?.address,
+        user_id: userId,
+        user_type: 'authenticated',
+        $last_login: new Date().toISOString(),
+        authenticated: true,
+        first_time_properties: {
+          $first_login: new Date().toISOString(),
+          first_wallet_address: user?.wallet?.address,
+          first_email: user?.email?.address
+        }
+      }
     };
     
-    // Set regular properties that can change
-    console.log("Setting user properties:", userProperties);
-    mixpanel.people.set(userProperties);
-    mixpanel.register(userProperties);
-
-    // Set first login timestamp - will only be set once
-    mixpanel.people.set_once({
-      $first_login: new Date().toISOString(),
-      first_wallet_address: user?.wallet?.address,
-      first_email: user?.email?.address
+    console.log("Sending identify request:", payload);
+    
+    const response = await fetch('/api/mixpanel/identify', {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      body: JSON.stringify(payload)
     });
 
+    if (!response.ok) {
+      const errorData = await response.json();
+      throw new Error(`Failed to identify user: ${errorData.error || response.statusText}`);
+    }
+
+    const data = await response.json();
+    console.log("Identify response:", data);
+
   } catch (error) {
-    console.error("Error identifying user:", error);
+    console.error("Error in identifyUser:", error);
   }
 }
 
@@ -56,9 +58,7 @@ async function handleDistinctId(user: any) {
 
   // Only handle user identification if there is an authenticated user
   if (user?.id) {
-    if (distinctId !== user.id) {
-      identifyUser(user.id, distinctId, user);
-    }
+    await identifyUser(user.id, distinctId, user);
     localStorage.setItem('mixpanel_user_id', user.id);
     localStorage.setItem('mixpanel_distinct_id', user.id);
     distinctId = user.id;
@@ -117,8 +117,7 @@ function handleSessionEnd() {
 
 export default function SessionTracker() {
   const { user, authenticated, ready } = usePrivy();
-
-  // Existing session tracking
+  
   useEffect(() => {
     if (!ready) return;
 
@@ -134,9 +133,16 @@ export default function SessionTracker() {
 
     initSession();
 
-    return () => {
+    // Only handle session end when leaving the page
+    const handleBeforeUnload = () => {
       handleSessionEnd();
     };
+
+    window.addEventListener('beforeunload', handleBeforeUnload);
+
+    return () => {
+      window.removeEventListener('beforeunload', handleBeforeUnload);
+    };
   }, [user, authenticated, ready]);
 
   return null;