PageSpeed monitoring, Polar billing, sidebar polish, frontend consistency audit #68
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { logger } from '@/lib/utils/logger'
|
import { logger } from '@/lib/utils/logger'
|
||||||
import Image from 'next/image'
|
|
||||||
import { formatNumber } from '@ciphera-net/ui'
|
import { formatNumber } from '@ciphera-net/ui'
|
||||||
import { getReferrerDisplayName, getReferrerFavicon, getReferrerIcon, mergeReferrersByDisplayName } from '@/lib/utils/icons'
|
import { getReferrerDisplayName, getReferrerFavicon, getReferrerIcon, mergeReferrersByDisplayName } from '@/lib/utils/icons'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
@@ -48,14 +47,21 @@ export default function TopReferrers({ referrers, collectReferrers = true, siteI
|
|||||||
const useFavicon = faviconUrl && !faviconFailed.has(referrer)
|
const useFavicon = faviconUrl && !faviconFailed.has(referrer)
|
||||||
if (useFavicon) {
|
if (useFavicon) {
|
||||||
return (
|
return (
|
||||||
<Image
|
// eslint-disable-next-line @next/next/no-img-element
|
||||||
|
<img
|
||||||
src={faviconUrl}
|
src={faviconUrl}
|
||||||
alt=""
|
alt=""
|
||||||
width={20}
|
width={20}
|
||||||
height={20}
|
height={20}
|
||||||
className="w-5 h-5 flex-shrink-0 rounded object-contain"
|
className="w-5 h-5 flex-shrink-0 rounded object-contain"
|
||||||
onError={() => setFaviconFailed((prev) => new Set(prev).add(referrer))}
|
onError={() => 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))
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
DeviceTablet,
|
DeviceTablet,
|
||||||
Desktop,
|
Desktop,
|
||||||
Link,
|
Link,
|
||||||
|
CursorClick,
|
||||||
} from '@phosphor-icons/react'
|
} from '@phosphor-icons/react'
|
||||||
import {
|
import {
|
||||||
SiGoogle,
|
SiGoogle,
|
||||||
@@ -122,12 +123,16 @@ const SI = { size: 16 } as const
|
|||||||
export function getReferrerIcon(referrerName: string) {
|
export function getReferrerIcon(referrerName: string) {
|
||||||
if (!referrerName) return <Globe className="text-neutral-400" />
|
if (!referrerName) return <Globe className="text-neutral-400" />
|
||||||
const lower = referrerName.toLowerCase()
|
const lower = referrerName.toLowerCase()
|
||||||
|
// Direct traffic
|
||||||
|
if (lower === 'direct') return <CursorClick className="text-neutral-500" />
|
||||||
|
// Browsers as referrers (e.g. googlechrome.com, firefox.com)
|
||||||
|
if (lower.includes('googlechrome') || lower.includes('chrome')) return <img src="/icons/browsers/chrome.svg" alt="Chrome" width={16} height={16} className="inline-block" />
|
||||||
// Social / platforms
|
// Social / platforms
|
||||||
if (lower.includes('google') && !lower.includes('gemini')) return <SiGoogle size={SI.size} color="#4285F4" />
|
if (lower.includes('google') && !lower.includes('gemini')) return <SiGoogle size={SI.size} color="#4285F4" />
|
||||||
if (lower.includes('facebook')) return <SiFacebook size={SI.size} color="#0866FF" />
|
if (lower.includes('facebook') || lower === 'fb') return <SiFacebook size={SI.size} color="#0866FF" />
|
||||||
if (lower.includes('twitter') || lower.includes('t.co') || lower.includes('x.com')) return <XIcon />
|
if (lower.includes('twitter') || lower.includes('t.co') || lower.includes('x.com')) return <XIcon />
|
||||||
if (lower.includes('linkedin')) return <LinkedInIcon />
|
if (lower.includes('linkedin')) return <LinkedInIcon />
|
||||||
if (lower.includes('instagram')) return <SiInstagram size={SI.size} color="#E4405F" />
|
if (lower.includes('instagram') || lower === 'ig') return <SiInstagram size={SI.size} color="#E4405F" />
|
||||||
if (lower.includes('github')) return <SiGithub size={SI.size} color="#fff" />
|
if (lower.includes('github')) return <SiGithub size={SI.size} color="#fff" />
|
||||||
if (lower.includes('youtube')) return <SiYoutube size={SI.size} color="#FF0000" />
|
if (lower.includes('youtube')) return <SiYoutube size={SI.size} color="#FF0000" />
|
||||||
if (lower.includes('reddit')) return <SiReddit size={SI.size} color="#FF4500" />
|
if (lower.includes('reddit')) return <SiReddit size={SI.size} color="#FF4500" />
|
||||||
@@ -183,6 +188,10 @@ const REFERRER_DISPLAY_OVERRIDES: Record<string, string> = {
|
|||||||
threads: 'Threads',
|
threads: 'Threads',
|
||||||
tumblr: 'Tumblr',
|
tumblr: 'Tumblr',
|
||||||
quora: 'Quora',
|
quora: 'Quora',
|
||||||
|
ig: 'Instagram',
|
||||||
|
fb: 'Facebook',
|
||||||
|
yt: 'YouTube',
|
||||||
|
googlechrome: 'Google Chrome',
|
||||||
't.co': 'X',
|
't.co': 'X',
|
||||||
'x.com': 'X',
|
'x.com': 'X',
|
||||||
// AI assistants and search tools
|
// AI assistants and search tools
|
||||||
@@ -239,7 +248,12 @@ export function getReferrerDisplayName(referrer: string): string {
|
|||||||
const trimmed = referrer.trim()
|
const trimmed = referrer.trim()
|
||||||
if (trimmed === '') return ''
|
if (trimmed === '') return ''
|
||||||
const hostname = getReferrerHostname(trimmed)
|
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]
|
const overrideByHostname = REFERRER_DISPLAY_OVERRIDES[hostname]
|
||||||
if (overrideByHostname) return overrideByHostname
|
if (overrideByHostname) return overrideByHostname
|
||||||
const label = getReferrerLabel(hostname)
|
const label = getReferrerLabel(hostname)
|
||||||
|
|||||||
Reference in New Issue
Block a user