# Phantom Opens & Clicks from Email Security Scanners Date: 2026-07-03 ## In plain English (no tech background needed) When we send a marketing email, most of the businesses we email use a **security guard for their inbox** (Microsoft, Proofpoint, Mimecast, and similar). Before a real person ever sees our email, that guard **opens the email and clicks every link in it first**, just to make sure nothing is dangerous. Think of it like the mailroom in a big office opening and X-raying a package before handing it to the employee. Here is the problem: our tools can't easily tell the difference between the guard and a real person. When the guard opens the email, it counts as an "open." When the guard clicks the link to inspect it, it can count as a "click." So our reports can say *"30% of people opened it and some clicked!"* when in reality it was mostly robots checking for viruses, and **no actual human was interested**. That's why we don't trust "opens" or even raw "clicks" as proof that the campaign is working. A robot opening an email doesn't pay us. So instead we look at things a robot almost never does: - Did someone reach the **order page** for a service? - Did they **start checkout**? - Did they **actually pay**? Those are the numbers that matter. If a campaign shows lots of opens and clicks but nobody reached the order page, that's a strong sign it was mostly the robot security guards, not real customers. We also run a **filter** that spots the tell-tale signs of these robots and quietly ignores them, so our real numbers only count real people. Bottom line: **"opens" and "clicks" look impressive but are mostly robots. Real interest = order-page visits, checkouts, and payments.** ## The short version Email opens, and even *clicks*, are unreliable signals because **email security gateways automatically fetch and render every link in a message** to scan it for malware, before the human ever sees the email. Those automated fetches fire the same tracking pixels and, for the advanced scanners that drive a real headless browser, the same JavaScript pageviews/clicks that a human would. So a campaign can show 20-40% "opens" and a handful of "clicks" with **zero real human engagement**. This is why we treat **Listmonk opens as noise**, do our conversion tracking in **Umami with a bot filter**, and judge campaigns on **human clicks → order-page views → checkout → paid orders**, never on opens. ## Who does this and how | Gateway | Product | Behavior | | --- | --- | --- | | Microsoft | Defender for O365 "Safe Links" / ATP detonation | Rewrites every URL, fetches it, and **detonates** suspicious ones in a real browser sandbox. Very common on business/`outlook`/M365 tenants. | | Proofpoint | URL Defense (`urldefense.com` / `pphosted.com`) | Rewrites and pre-fetches every link; re-scans on click. | | Mimecast | URL Protect / Attachment Protect | Pre-fetches and rewrites links. | | Barracuda | Link Protect | Fetches links at delivery. | | Cisco / Symantec / MessageLabs | Secure Email / ClickTime | Scan-on-delivery and scan-on-click. | | Google | Gmail image proxy (`GoogleImageProxy`) | Pre-fetches images (inflates *opens*, not usually JS clicks). | Two distinct effects: 1. **Inflated opens.** Any gateway that loads the tracking pixel (or Gmail's image proxy caching it) counts as an "open" in Listmonk. This happens on a large fraction of B2B mail. Opens are therefore close to meaningless. 2. **Phantom clicks / pageviews.** The advanced scanners (Microsoft ATP, Proofpoint, Mimecast) run a **headless browser** that executes JavaScript. That fires a real Umami pageview and can trip click events, so the visit *looks* human. This is the dangerous one because it corrupts the metric we actually rely on (clicks), not just the one we already ignore (opens). Extra wrinkles: - Scanners often fetch **within seconds of delivery**, in bulk, from datacenter IPs, before any human could plausibly read the email. - They may fetch **every** link, so a "click" on a deep CTA can be a scanner walking all URLs, not a human choosing one. - Microsoft rewrites the URL, so the referrer/host can look like `*.safelinks.protection.outlook.com`; Proofpoint uses `urldefense.com`. ## How we defend against it ### 1. Listmonk click tracking is intentionally OFF on per-subscriber CTAs Our conversion CTAs are per-subscriber links (`?dot=`, `?npi=`, `{{ lp_link }}`). Listmonk's `@TrackLink` was removed from those (it caused a 404 + collapse bug), so **"0 clicks" in Listmonk is expected and not a real signal**. Real clicks are attributed in Umami via the `campaign-click` event. See the runbook incident "Jun 22 2026 — `@TrackLink` on per-subscriber CTAs". ### 2. Umami has a headless/scanner bot filter `site/public/js/pw-bot-filter.js` (loaded before the Umami script on every page, wired via `data-before-send="umamiBeforeSend"`) scores each visit for automation/headless signals and **drops the event when it looks like a bot**, so scanner traffic never reaches analytics. It is designed to **fail open**: any uncertainty counts as human, so we never undercount real people. Signals it uses (see the file for the full, commented list): - **Decisive (any one suppresses):** - `navigator.webdriver === true` (Selenium/Puppeteer/Playwright, Chrome headless) - Headless/automation user-agents (`HeadlessChrome`, `PhantomJS`, `Electron`, ...) - Known scanner UAs (`Proofpoint`, `Mimecast`, `Barracuda`, `Cisco`, `Symantec`, `MessageLabs`, `GoogleImageProxy`, `Microsoft Office`, ...) - Zero/collapsed screen or viewport, or a window bigger than the monitor (`outer-gt-screen`) — classic headless geometry - A **software WebGL rasterizer** (`SwiftShader`, `llvmpipe`, `swrast`) on a desktop-class UA — the single hardest signal to spoof; headless/VM scanners fall back to software rendering - Zero logical CPUs (`hardwareConcurrency === 0`) - **Soft (need two to corroborate):** tiny screen, low color depth, empty `navigator.languages`, no pointer/hover/touch input surface, no WebGL at all. The result is exposed as `window.pwIsBot` / `window.pwBotReasons` for debugging. ### 3. Server-side scanner exclusion Most known scanner user-agents are already excluded server-side, and the MX-tag pipeline classifies each recipient's receiving operator (`google`/`microsoft`/`proofpoint`/`mimecast`/`barracuda`/...) so campaign builders can throttle per operator. See `scripts/mx_tag_carriers.py`, `scripts/mail_reputation_monitor.py`, and `infra/cron/pw-mx-tag`. ### 4. We measure conversion, not opens The A/B scoreboard (`scripts/coupon_ab_scoreboard.py`) explicitly counts **human clicks (Umami, bot-filtered) + paid orders**, never opens. The funnel we watch is: ```text sent → accepted → HUMAN clicks (Umami) → order-page views → checkout starts → paid orders ``` ## What this means in practice - **Never celebrate an open rate.** On a B2B list heavy with Microsoft/Proofpoint MX, 20-40% opens can be almost entirely scanners. - **Even a raw click number can be inflated** if it comes from Listmonk link tracking or an un-filtered analytics setup. Trust the **Umami `campaign-click`** count (bot-filtered) and, above all, **order-page views and paid orders**. - **Instant, bulk, datacenter-sourced "engagement" right after send = scanners.** Real humans trickle in over hours/days from residential/mobile networks. - If a campaign shows opens/clicks but **zero order-page views**, that is the signature of scanner-only traffic, not a landing-page problem. ## Related docs - `docs/email-deliverability-runbook.md` — sending infra, warmup, incidents (including the `@TrackLink` click-tracking incident and the clean-pool decay fix). - `docs/email-no-sales-action-plan-2026-07-02.md` — conversion playbook; item #2 ("opens inflated by bots/scanners") is exactly this problem. - `site/public/js/pw-bot-filter.js` — the implementation. - `site/public/js/pw-analytics.js` — the `campaign-click` / `checkout-page-view` event definitions.