Anthony Wentzel

Build a monitor, not a dashboard: the Cloudflare Zaraz false negative

A plain fetch said our tracking tags were missing. Cloudflare Zaraz only injects them for browser navigations. Lessons for landing page monitoring.

From 2026 · 2 min read · Published September 25, 2026

We recently audited a client's marketing funnel: dozens of landing pages, each supposed to carry the right form and the right tracking tags. The obvious landing page monitoring tool is a script that fetches every page and greps for what should be there.

Our first script reported that a big chunk of pages were missing their tags. That would have been a serious finding. It was also wrong.

The Cloudflare Zaraz false negative

The tags were injected at the edge by Cloudflare Zaraz. Edge injection only happens for requests that look like real browser navigations. A bare fetch from Node doesn't look like one, so Cloudflare served the page without the tags. The page was fine; our checker wasn't.

The fix is to ask for the page the way a browser does:

lib/pages.ts
const BROWSER_HEADERS: Record<string, string> = {
  "User-Agent":
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 " +
    "(KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
  "Sec-Fetch-Dest": "document", 
  "Sec-Fetch-Mode": "navigate", 
  "Sec-Fetch-Site": "none",
  "Sec-Fetch-User": "?1",
};

The Sec-Fetch-* headers are what actually signal "top-level navigation." With them, the edge behaves as it would for a visitor, and the tags show up.

Snapshots beat status

The second change was more important. A dashboard answers "what does the funnel look like right now?" That's rarely the useful question. The useful question is "what changed, and when?"

So the tool stores a daily snapshot of every page's checks and diffs consecutive days. Instead of "page X has no form," it can say "page X lost its form on the 14th." That sentence points directly at a deploy, a CMS edit, or a person. The current-state version just points at a mystery.

The shape of it

  • Fetch like a browser, or you're testing the wrong thing.
  • Persist every run. Storage is cheap; a missing history is expensive.
  • Report transitions, not states. Humans act on "it broke Tuesday," not on "it's broken."

A dashboard is something you look at. A monitor is something that tells you when to look.


Related: Zero of 129 pages indexed: a Next.js canonical URL bug · Facebook Pixel firing twice: one pixel, one init