Track all link clicks (internal + external) in analytics; v1.1.33

Replaces outbound-only tracking with a useLinkClickTracking hook that
captures every <a> click on the site. Stores as link_click events keyed
by destination URL, with an internal flag. Admin analytics page gains a
Link Clicks table sorted by count, showing type (internal/external).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 4.6 committed 2026-08-10 09:11:53 -04:00
1 parent abb4c87c41
commit bf3154378b
7 files changed
+73 -12

No files matched your search

+29 -8
View File
@@ -87,22 +87,43 @@ export function useUTMCapture() {
}, [])
}
// --- Outbound link clicks ---
export function useOutboundLinkTracking() {
// --- All link clicks (internal + external) ---
export function useLinkClickTracking() {
useEffect(() => {
function onClick(e: MouseEvent) {
if (!hasConsent()) return
const target = (e.target as HTMLElement).closest('a')
if (!target) return
const href = target.getAttribute('href') ?? ''
if (!href.startsWith('http') && !href.startsWith('//')) return
try {
const url = new URL(href)
if (url.hostname === window.location.hostname) return
sendEvent('outbound_click', { url: href, text: target.textContent?.trim().slice(0, 100) ?? '' })
} catch { /* ignore malformed */ }
if (!href || href.startsWith('#') || href.startsWith('mailto:') || href.startsWith('tel:')) return
let url: string
let internal: boolean
if (href.startsWith('http') || href.startsWith('//')) {
try {
const parsed = new URL(href)
if (parsed.hostname === window.location.hostname) {
url = parsed.pathname
internal = true
} else {
url = href
internal = false
}
} catch { return }
} else if (href.startsWith('/')) {
url = href.split('?')[0]
internal = true
} else {
return
}
sendEvent('link_click', { url: url.slice(0, 500), internal })
}
document.addEventListener('click', onClick, { capture: true })
return () => document.removeEventListener('click', onClick, { capture: true })
}, [])
}
/** @deprecated Use useLinkClickTracking instead */
export function useOutboundLinkTracking() { useLinkClickTracking() }