diff --git a/apps/sim/app/(auth)/components/utm-cookie-setter.tsx b/apps/sim/app/(auth)/components/utm-cookie-setter.tsx new file mode 100644 index 000000000..efd8f9ae5 --- /dev/null +++ b/apps/sim/app/(auth)/components/utm-cookie-setter.tsx @@ -0,0 +1,33 @@ +'use client' + +import { useEffect } from 'react' +import { useSearchParams } from 'next/navigation' + +const UTM_KEYS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content'] as const +const COOKIE_NAME = 'sim_utm' +const COOKIE_MAX_AGE = 3600 // 1 hour + +export function UtmCookieSetter() { + const searchParams = useSearchParams() + + useEffect(() => { + const hasUtm = UTM_KEYS.some((key) => searchParams.get(key)) + if (!hasUtm) return + + const utmData: Record = {} + for (const key of UTM_KEYS) { + const value = searchParams.get(key) + if (value) { + utmData[key] = value + } + } + + utmData.referrer_url = document.referrer || '' + utmData.landing_page = window.location.pathname + utmData.created_at = Date.now().toString() + + document.cookie = `${COOKIE_NAME}=${encodeURIComponent(JSON.stringify(utmData))}; path=/; max-age=${COOKIE_MAX_AGE}; SameSite=Lax` + }, [searchParams]) + + return null +} diff --git a/apps/sim/app/(auth)/layout.tsx b/apps/sim/app/(auth)/layout.tsx index aaa76e0bf..a1d1b9948 100644 --- a/apps/sim/app/(auth)/layout.tsx +++ b/apps/sim/app/(auth)/layout.tsx @@ -1,7 +1,8 @@ 'use client' -import { useEffect } from 'react' +import { Suspense, useEffect } from 'react' import AuthBackground from '@/app/(auth)/components/auth-background' +import { UtmCookieSetter } from '@/app/(auth)/components/utm-cookie-setter' import Nav from '@/app/(landing)/components/nav/nav' // Helper to detect if a color is dark @@ -28,6 +29,9 @@ export default function AuthLayout({ children }: { children: React.ReactNode }) }, []) return ( + + +
{/* Header - Nav handles all conditional logic */}