diff --git a/components/dashboard/TopReferrers.tsx b/components/dashboard/TopReferrers.tsx index 04f1e19..abf1353 100644 --- a/components/dashboard/TopReferrers.tsx +++ b/components/dashboard/TopReferrers.tsx @@ -2,7 +2,6 @@ import { useState, useEffect } from 'react' import { logger } from '@/lib/utils/logger' -import Image from 'next/image' import { formatNumber } from '@ciphera-net/ui' import { getReferrerDisplayName, getReferrerFavicon, getReferrerIcon, mergeReferrersByDisplayName } from '@/lib/utils/icons' import Link from 'next/link' @@ -48,14 +47,21 @@ export default function TopReferrers({ referrers, collectReferrers = true, siteI const useFavicon = faviconUrl && !faviconFailed.has(referrer) if (useFavicon) { return ( - setFaviconFailed((prev) => new Set(prev).add(referrer))} - unoptimized + onLoad={(e) => { + // Google's favicon service returns a 16x16 default globe when no real favicon exists + const img = e.currentTarget + if (img.naturalWidth <= 16) { + setFaviconFailed((prev) => new Set(prev).add(referrer)) + } + }} /> ) } diff --git a/lib/utils/icons.tsx b/lib/utils/icons.tsx index e1c7d4f..af5867c 100644 --- a/lib/utils/icons.tsx +++ b/lib/utils/icons.tsx @@ -6,6 +6,7 @@ import { DeviceTablet, Desktop, Link, + CursorClick, } from '@phosphor-icons/react' import { SiGoogle, @@ -122,12 +123,16 @@ const SI = { size: 16 } as const export function getReferrerIcon(referrerName: string) { if (!referrerName) return const lower = referrerName.toLowerCase() + // Direct traffic + if (lower === 'direct') return + // Browsers as referrers (e.g. googlechrome.com, firefox.com) + if (lower.includes('googlechrome') || lower.includes('chrome')) return Chrome // Social / platforms if (lower.includes('google') && !lower.includes('gemini')) return - if (lower.includes('facebook')) return + if (lower.includes('facebook') || lower === 'fb') return if (lower.includes('twitter') || lower.includes('t.co') || lower.includes('x.com')) return if (lower.includes('linkedin')) return - if (lower.includes('instagram')) return + if (lower.includes('instagram') || lower === 'ig') return if (lower.includes('github')) return if (lower.includes('youtube')) return if (lower.includes('reddit')) return @@ -183,6 +188,10 @@ const REFERRER_DISPLAY_OVERRIDES: Record = { threads: 'Threads', tumblr: 'Tumblr', quora: 'Quora', + ig: 'Instagram', + fb: 'Facebook', + yt: 'YouTube', + googlechrome: 'Google Chrome', 't.co': 'X', 'x.com': 'X', // AI assistants and search tools @@ -239,7 +248,12 @@ export function getReferrerDisplayName(referrer: string): string { const trimmed = referrer.trim() if (trimmed === '') return '' const hostname = getReferrerHostname(trimmed) - if (!hostname) return trimmed + if (!hostname) { + // Plain names without a dot (e.g. "Ig", "Direct") — check override map before returning raw + const overrideByPlain = REFERRER_DISPLAY_OVERRIDES[trimmed.toLowerCase()] + if (overrideByPlain) return overrideByPlain + return trimmed + } const overrideByHostname = REFERRER_DISPLAY_OVERRIDES[hostname] if (overrideByHostname) return overrideByHostname const label = getReferrerLabel(hostname)