diff --git a/src/components/landing/CTAReg.tsx b/src/components/landing/CTAReg.tsx index 2c4d023..df995ee 100644 --- a/src/components/landing/CTAReg.tsx +++ b/src/components/landing/CTAReg.tsx @@ -5,6 +5,7 @@ import { Terminal, ArrowRight, Radio } from 'lucide-react'; import Link from 'next/link'; import animation from '@/src/animation'; +import { trackRegisterClick } from '@/src/utils/trackRegisterClick'; const eventID = process.env.EVENT_ID || process.env.NEXT_PUBLIC_EVENT_ID; const data = require(`../../data/${eventID}/index.json`); @@ -52,6 +53,14 @@ const LandingJoinMissionControl = ({ UTMSource }: { UTMSource?: string }) => { {/* Primary Action */} + trackRegisterClick(event, { + ctaLocation: UTMSource ? `cta_reg_${UTMSource}` : 'cta_reg', + url: registerUrl, + }) + } className="group relative px-8 py-4 bg-sky-digital text-black font-bold font-heading text-lg tracking-wider uppercase overflow-hidden" >
diff --git a/src/components/landing/Header.tsx b/src/components/landing/Header.tsx index 3bdd375..bc90419 100644 --- a/src/components/landing/Header.tsx +++ b/src/components/landing/Header.tsx @@ -14,6 +14,7 @@ if (typeof window !== 'undefined') { import { AlertTriangle, Radio, Terminal, ChevronRight, Crosshair, Banknote, Users, ShieldCheck, Award, Zap } from 'lucide-react'; import animations from '../../animation'; +import { trackRegisterClick } from '../../utils/trackRegisterClick'; const eventID = process.env.EVENT_ID || process.env.NEXT_PUBLIC_EVENT_ID; const data = require(`../../data/${eventID}/index.json`); @@ -356,8 +357,14 @@ const LandingHeader = () => {
{ if (typeof window !== 'undefined' && (window as any).gtag) (window as any).gtag('event', 'register_cta_click', { cta_location: 'countdown' }); }} + onClick={(event) => + trackRegisterClick(event, { + ctaLocation: 'countdown', + url: 'https://register.inctf.in', + }) + } > REGISTER NOW @@ -398,9 +405,25 @@ const LandingHeader = () => {
Powered by TCS & Co-Powered by NIQ
- TCS Logo + + TCS Logo +
- NIQ Logo + + NIQ Logo +
diff --git a/src/components/shared/TopBar/MobileMenu.tsx b/src/components/shared/TopBar/MobileMenu.tsx index ff6639b..5ef113e 100644 --- a/src/components/shared/TopBar/MobileMenu.tsx +++ b/src/components/shared/TopBar/MobileMenu.tsx @@ -3,6 +3,7 @@ import styled from '@emotion/styled'; import Link from 'next/link'; import SocialMediaLinks from '../SocialMediaLinks'; +import { trackRegisterClick } from '../../../utils/trackRegisterClick'; import { ChevronDown, ChevronUp, X } from 'lucide-react'; const SideBarMenu = styled.div` @@ -120,10 +121,15 @@ const MobileMenu = ({ onClose, config }) => { {cta && ( { + target="_blank" + rel="noopener noreferrer" + onClick={(event) => { onClose?.(); - if (typeof window !== 'undefined' && (window as any).gtag) { - (window as any).gtag('event', 'register_cta_click', { cta_location: 'mobile_nav' }); + if (cta.link) { + trackRegisterClick(event, { + ctaLocation: 'mobile_nav', + url: cta.link, + }); } }} className="block w-full" diff --git a/src/components/shared/TopBar/index.tsx b/src/components/shared/TopBar/index.tsx index 02438ee..8bb2d8f 100644 --- a/src/components/shared/TopBar/index.tsx +++ b/src/components/shared/TopBar/index.tsx @@ -6,6 +6,7 @@ import Modal from 'react-modal'; import { clearAllBodyScrollLocks } from 'body-scroll-lock'; import Logo from '../Logo'; +import { trackRegisterClick } from '../../../utils/trackRegisterClick'; import MobileMenu from './MobileMenu'; import TopBarSearch from './search'; @@ -312,10 +313,11 @@ const TopBar = ({ UTMSource = null }) => { { - if (typeof window !== 'undefined' && (window as any).gtag) { - (window as any).gtag('event', 'register_cta_click', { cta_location: 'top_bar' }); - } + onClick={(event) => { + trackRegisterClick(event, { + ctaLocation: 'top_bar', + url: topbarConfig?.CTA?.link, + }); }} > @@ -353,10 +355,11 @@ const TopBar = ({ UTMSource = null }) => { href={topbarConfig.CTA.link} target="_blank" className="px-3 py-1 border border-alert-crimson bg-alert-crimson/10 text-alert-crimson font-bold uppercase tracking-wider text-xs rounded-none hover:bg-alert-crimson hover:text-white transition-all duration-300" - onClick={() => { - if (typeof window !== 'undefined' && (window as any).gtag) { - (window as any).gtag('event', 'register_cta_click', { cta_location: 'top_bar_mobile' }); - } + onClick={(event) => { + trackRegisterClick(event, { + ctaLocation: 'top_bar_mobile', + url: topbarConfig.CTA.link, + }); }} > Register diff --git a/src/utils/trackRegisterClick.ts b/src/utils/trackRegisterClick.ts new file mode 100644 index 0000000..6300bb4 --- /dev/null +++ b/src/utils/trackRegisterClick.ts @@ -0,0 +1,57 @@ +import type { MouseEvent } from 'react'; + +type RegisterClickOptions = { + ctaLocation: string; + url: string; + target?: '_blank' | '_self'; +}; + +const NAVIGATION_FALLBACK_DELAY_MS = 500; + +export function trackRegisterClick( + event: MouseEvent, + { ctaLocation, url, target = '_blank' }: RegisterClickOptions, +) { + if (typeof window === 'undefined') { + return; + } + + const isModifiedClick = event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0; + if (isModifiedClick) { + return; + } + + const navigate = () => { + if (target === '_self') { + window.location.assign(url); + return; + } + + window.open(url, '_blank', 'noopener,noreferrer'); + }; + + if (typeof window.gtag !== 'function') { + return; + } + + event.preventDefault(); + + let hasNavigated = false; + + const navigateOnce = () => { + if (hasNavigated) { + return; + } + + hasNavigated = true; + navigate(); + }; + + window.gtag('event', 'register_cta_click', { + cta_location: ctaLocation, + transport_type: 'beacon', + event_callback: navigateOnce, + }); + + window.setTimeout(navigateOnce, NAVIGATION_FALLBACK_DELAY_MS); +} \ No newline at end of file