Dashboard filtering, automatic tracking, chart rebuild & settings modal #40

Merged
uz1mani merged 28 commits from staging into main 2026-03-07 00:21:04 +00:00
11 changed files with 252 additions and 563 deletions
Showing only changes of commit 53a0341925 - Show all commits

View File

@@ -11,6 +11,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
### 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.
- **Automatic outbound link tracking.** Pulse now tracks when visitors click links that take them to other websites. These show up as "outbound link" events in your Goals & Events panel — no setup needed. You can turn this off in your tracking snippet settings if you prefer.
- **Automatic file download tracking.** When a visitor clicks a link to a downloadable file — PDF, ZIP, Excel, Word, MP3, and 20+ other formats — Pulse records it as a "file download" event. Like outbound links, this works automatically with no setup required.
### Improved

View File

@@ -346,4 +346,39 @@
window.pulse = window.pulse || {};
window.pulse.track = trackCustomEvent;
// * Auto-track outbound link clicks and file downloads (on by default)
// * Opt-out: add data-no-outbound or data-no-downloads to the script tag
var trackOutbound = !script.hasAttribute('data-no-outbound');
var trackDownloads = !script.hasAttribute('data-no-downloads');
if (trackOutbound || trackDownloads) {
var FILE_EXT_REGEX = /\.(pdf|zip|gz|tar|xlsx|xls|csv|docx|doc|pptx|ppt|mp4|mp3|wav|avi|mov|exe|dmg|pkg|deb|rpm|iso|7z|rar)($|\?|#)/i;
document.addEventListener('click', function(e) {
var el = e.target;
// * Walk up from clicked element to find nearest <a> tag
while (el && el.tagName !== 'A') el = el.parentElement;
if (!el || !el.href) return;
try {
var url = new URL(el.href, location.href);
// * Skip non-http links (mailto:, tel:, javascript:, etc.)
if (url.protocol !== 'http:' && url.protocol !== 'https:') return;
// * Check file download first (download attribute or known file extension)
if (trackDownloads && (el.hasAttribute('download') || FILE_EXT_REGEX.test(url.pathname))) {
trackCustomEvent('file_download');
return;
}
// * Check outbound link (different hostname)
if (trackOutbound && url.hostname && url.hostname !== location.hostname) {
trackCustomEvent('outbound_link');
}
} catch (err) {
// * Invalid URL - skip silently
}
}, true); // * Capture phase: fires before default navigation
}
})();