Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 3.8k
feat(landing): add HubSpot tracking script for hosted marketing site#5565
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
6819045b0a606b6ce1b5dc84d9fca0277f4e5937eb79d108ac9fa654ae92f4e6807b4ecb02ba724e9f458a9a3c9File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <LandingShell>{children}</LandingShell> | ||
| return ( | ||
| <LandingShell> | ||
| {children} | ||
| {/* HubSpot tracking — hosted only */} | ||
| {isHosted && ( | ||
| <> | ||
| <Script id='hs-script-loader' src={HUBSPOT_SCRIPT_SRC} strategy='afterInteractive' /> | ||
| <Suspense fallback={null}> | ||
| <HubspotPageViewTracker /> | ||
| </Suspense> | ||
| </> | ||
| )} | ||
waleedlatif1 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. waleedlatif1 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| </LandingShell> | ||
| ) | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.