From 508bb006a8a6781257a01ec0fa790ff179181b70 Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Mon, 23 Mar 2026 12:23:10 +0100 Subject: [PATCH] fix(referrers): replace low-res Google favicon globe with proper icons Detect Google's 16x16 default globe fallback via naturalWidth on load and fall back to Phosphor icons. Add Chrome icon for googlechrome.github.io, CursorClick for Direct, and abbreviation support (ig, fb, yt). --- components/dashboard/TopReferrers.tsx | 12 +++++++++--- lib/utils/icons.tsx | 20 +++++++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) 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)