Tracking7 min read

Bots, spam, and excluded traffic

Bot traffic can be a majority of raw hits on a small site. Mrkr filters it before a single row is written, so your numbers describe real visitors, not scripts.

How bot detection works

Every event passes through a layered set of checks before it becomes a session, a rollup counter, or a row anywhere. A request that fails any layer gets a normal-looking 200 OK response (so the tracker doesn't retry it) but is never stored as a visit:

  • Client-side tells the tracker itself reports: navigator.webdriver (browser automation), the page being a browser speculative pre-render, an empty navigator.languages, a zero-size viewport, or empty User-Agent Client Hints brands, all classic headless-browser signatures.
  • User-Agent shape and keywords: missing or implausibly short UAs, UAs that don't start with the standard browser prefix, and a long list of known crawler/scraper/monitoring-tool tokens (including AI training and assistant crawlers like GPTBot, ClaudeBot, and PerplexityBot, on the rare chance one executes JavaScript).
  • Header consistency: a User-Agent claiming to be a modern Chrome or Firefox is checked against the companion headers real browsers always send with it; a spoofed UA on a scripted HTTP client typically doesn't have them.
  • Cloudflare's bot score and threat score, where available.
  • Datacenter and cloud-hosting network origin: traffic from AWS, GCP, Azure, and similar hosting providers, matched carefully to avoid false-positiving Apple Private Relay users.
  • Origin and fetch-metadata checks: the request must carry browser-only headers that prove it came from an actual page load on your configured domain, not a replayed or forged request.
  • Referrer-spam blocklist: a curated list of domains that exist purely to plant themselves in analytics dashboards.
  • A geo/timezone mismatch check: catches a specific residential-proxy pattern (an American browser timezone reported from a non-American IP on a Linux desktop).
  • Per-IP rate limiting: a cap on events per minute from a single address, well above what a real person browsing generates.

Your dashboard's bot-filtering panel shows a 14-day total of blocked events, broken down by which check caught them and what kind of client tripped it, useful both for confirming filtering is working and for spotting if it's ever too aggressive.

AI crawler visibility

AI assistants and model-training crawlers fetch raw HTML directly and don't execute JavaScript, so the browser tracker never sees them: they're filtered out, not measured. If you want visibility into which AI crawlers are hitting your site (ChatGPT-User, ClaudeBot, PerplexityBot, GPTBot, and others, categorized as an assistant fetch, a search-index crawl, or model-training collection), that's a separate, opt-in integration: your backend or edge logs forward each crawler's User-Agent and path to a dedicated endpoint, which classifies it and rolls it up for the AI-crawlers dashboard page. Crawler hits write only their own counters and never count toward your plan's pageview quota.

Excluded paths

Independent of bot filtering, you can exclude specific pages entirely (admin panels, internal tools, staging routes) from Settings. Patterns are simple globs (* matches any run of characters including /, ? matches one character, matching is case-insensitive), for example /admin/* or /preview-*. Up to 50 patterns per site. Every event carrying that path is dropped before any other check runs, not just the pageview, so an excluded route never counts toward bot statistics, your pageview quota, or anything else.

Excluding your own traffic

There's no dedicated "don't track my own visits" toggle (no IP allowlist or first-party opt-out cookie). Two things get you most of the way there: excluded paths for internal-only routes your team uses, and the fact that testing from a domain that doesn't match what's configured for the site (a bare localhost, for instance) is already excluded by the origin check described above. If you regularly browse your own production site from a fixed office IP and want it excluded entirely, the closest option today is testing against a staging domain that isn't the one configured for the live site.