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:
1 parent
abb4c87c41
commit
bf3154378b
7 files changed
+73
-12
No files matched your search
+29
-8
@@ -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() }
|
||||
Reference in new issue
Block a user