diff --git a/apps/sim/app/(landing)/hubspot-page-view-tracker.tsx b/apps/sim/app/(landing)/hubspot-page-view-tracker.tsx new file mode 100644 index 00000000000..2fbb35cf526 --- /dev/null +++ b/apps/sim/app/(landing)/hubspot-page-view-tracker.tsx @@ -0,0 +1,38 @@ +'use client' + +import { useEffect } from 'react' +import { usePathname, useSearchParams } from 'next/navigation' + +declare global { + interface Window { + _hsq?: unknown[][] + } +} + +// next/script dedupes by id and never reloads on remount, so this must be +// module-scope (not a ref) to survive LandingLayout unmounting/remounting. +let hasTrackedInitialPageView = false + +/** + * The HubSpot loader only auto-tracks the first page load; LandingLayout + * persists across client-side navigations, so HubSpot never sees the rest. + * Pushes a manual pageview through `_hsq` on every navigation after the first. + */ +export function HubspotPageViewTracker() { + const pathname = usePathname() + const searchParams = useSearchParams() + const query = searchParams.toString() + + useEffect(() => { + if (!hasTrackedInitialPageView) { + hasTrackedInitialPageView = true + return + } + + window._hsq = window._hsq || [] + window._hsq.push(['setPath', query ? `${pathname}?${query}` : pathname]) + window._hsq.push(['trackPageView']) + }, [pathname, query]) + + return null +} diff --git a/apps/sim/app/(landing)/layout.tsx b/apps/sim/app/(landing)/layout.tsx index 7e320fad1b8..740deccce9f 100644 --- a/apps/sim/app/(landing)/layout.tsx +++ b/apps/sim/app/(landing)/layout.tsx @@ -1,7 +1,13 @@ import type { ReactNode } from 'react' +import { Suspense } from 'react' import type { Metadata } from 'next' +import Script from 'next/script' +import { isHosted } from '@/lib/core/config/env-flags' import { SITE_URL } from '@/lib/core/utils/urls' import { LandingShell } from '@/app/(landing)/components' +import { HubspotPageViewTracker } from '@/app/(landing)/hubspot-page-view-tracker' + +const HUBSPOT_SCRIPT_SRC = 'https://js-na2.hs-scripts.com/246720681.js' as const /** * Route-group layout for the entire landing family - the home page, platform and @@ -24,5 +30,18 @@ export const metadata: Metadata = { } export default function LandingLayout({ children }: { children: ReactNode }) { - return {children} + return ( + + {children} + {/* HubSpot tracking — hosted only */} + {isHosted && ( + <> +