diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f51b4d..6edade6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [0.13.0-alpha] - 2026-03-02 +### Added + +- **AI traffic source identification.** Pulse now automatically recognizes visitors coming from AI tools — ChatGPT, Perplexity, Claude, Gemini, Copilot, DeepSeek, Grok, Meta AI, You.com, and Phind. These sources appear in your Top Referrers with proper brand icons and display names instead of raw domain URLs. If someone clicks a link in an AI chat to visit your site, you'll see exactly which AI tool sent them. + ### Improved - **Cleaner internal API code.** The analytics data-fetching layer has been streamlined — 13 near-identical endpoint functions were consolidated using a shared pattern, cutting roughly half the code while keeping every feature working exactly as before. This makes it easier to add new analytics endpoints in the future and reduces the chance of inconsistencies between them. diff --git a/lib/utils/icons.tsx b/lib/utils/icons.tsx index da7f3cd..f3cca87 100644 --- a/lib/utils/icons.tsx +++ b/lib/utils/icons.tsx @@ -30,7 +30,8 @@ import { FaGlobe } from 'react-icons/fa' import { FaXTwitter } from 'react-icons/fa6' -import { SiBrave } from 'react-icons/si' +import { SiBrave, SiOpenai, SiPerplexity, SiAnthropic, SiGooglegemini } from 'react-icons/si' +import { RiRobot2Fill } from 'react-icons/ri' import { MdDeviceUnknown, MdSmartphone, MdTabletMac, MdDesktopWindows } from 'react-icons/md' export function getBrowserIcon(browserName: string) { @@ -79,7 +80,17 @@ export function getReferrerIcon(referrerName: string) { if (lower.includes('github')) return if (lower.includes('youtube')) return if (lower.includes('reddit')) return - + // AI assistants and search tools + if (lower.includes('chatgpt') || lower.includes('openai')) return + if (lower.includes('perplexity')) return + if (lower.includes('claude') || lower.includes('anthropic')) return + if (lower.includes('gemini')) return + if (lower.includes('copilot')) return + if (lower.includes('deepseek')) return + if (lower.includes('grok') || lower.includes('x.ai')) return + if (lower.includes('phind')) return + if (lower.includes('you.com')) return + // Try to use a generic globe or maybe check if it is a URL return } @@ -111,6 +122,17 @@ const REFERRER_DISPLAY_OVERRIDES: Record = { quora: 'Quora', 't.co': 'X', 'x.com': 'X', + // AI assistants and search tools + openai: 'ChatGPT', + perplexity: 'Perplexity', + claude: 'Claude', + anthropic: 'Claude', + gemini: 'Gemini', + copilot: 'Copilot', + deepseek: 'DeepSeek', + grok: 'Grok', + 'you': 'You.com', + phind: 'Phind', } /**