title
Cloudflare analytics ops - diagnose and remediate RUM
kind
sop
triggers
tools

Standard Operating Procedure: Cloudflare analytics ops

Use with agent-cloudflare-ops and the cloudflare-ops MCP profile. Do not guess live account state.

Install once per session: kit mcp cloudflare-ops --install (OAuth on first Cloudflare tool use). One profile only - do not stack cloud + ops.

Architecture (two modes)

ModeWhereBeaconIngest
Cloudflare Pages (proxied)Product infra/cloudflare WebAnalyticsSiteautoInstall: true - Cloudflare injects the snippetcloudflareinsights.com
GitHub Pages (grey-cloud DNS)edge-dns when githubPages is setFirst-party Worker on insights.<zone> serving beacon.min.js; product HTML embeds webAnalyticsSnippetMust stay on cloudflareinsights.com - Worker-proxied send.to 404s

Discover expected sites from edge-dns zones.yaml plus each product’s infra/cloudflare stack. Do not hard-code a fleet list in this kit.

MCP tools

ServerToolsUse for
cloudflare (Code Mode)search, execute, docsList RUM sites (GET /accounts/{id}/rum/site_info/list), Workers, DNS, GraphQL analytics. Never ?codemode=false.
cloudflare-observabilityobservability_keys, observability_values, query_worker_observabilityBeacon Worker logs and errors

search before execute unless the path is already known. Confirm keys/values before filtered observability queries.

Loop

  1. Inventory - execute RUM site list. Diff against Pulumi WebAnalyticsSite / githubPages origins. Flag duplicates (dashboard site vs stack site).
  2. Probe - GET https://insights.<zone>/beacon.min.js (GitHub Pages mode) must be 200. Product HTML must contain the snippet before </body>. Pages auto-install sites should not also embed a stale first-party snippet.
  3. Logs - For insights.* Workers, query observability (errors, 404s on /beacon.min.js).
  4. Hypotheses - Keep ≤5. Cheap probes first (HTTP status, snippet present, autoInstall vs grey-cloud).
  5. Fix in the owning repo - Pulumi for sites/Workers/DNS; product HTML for snippets. See ownership below.
  6. Prove - Re-list RUM sites, re-probe URLs, re-query logs. Unit tests alone are not proof for a live beacon.

Common failures

SymptomLikely causeFix where
No RUM data, Pages siteautoInstall false or site not on the proxied zoneProduct infra/cloudflare
No RUM data, GitHub PagesMissing snippet, wrong siteToken, or ingest pointed at the WorkerProduct HTML + edge-dns snippet output
insights.<zone>/beacon.min.js 404Worker or custom domain missingedge-dns GitHub Pages origin
Duplicate RUM sitesCreated in dashboard and PulumiImport the existing site; do not create a second
Beacon 200 but no eventsIngest URL rewritten to the Worker (send.to 404)Restore ingest to cloudflareinsights.com
OAuth / 403 on MCPProfile not installed or scopes too narrowRe-auth; Account Settings Read + Workers observability

Ownership (do not mutate IaC via MCP writes)

ResourceOwner
Zone, GitHub Pages origin DNS, insights.<zone> Worker, GH-Pages WebAnalyticsSiteedge-dns
Pages WebAnalyticsSite autoInstall: true, Observatory testsProduct infra/cloudflare
Grey-cloud snippet in HTMLProduct repo (index.html / layout)
Shared mzworthington.co.uk beacon reused by gpio-build-monitormzworthington stack + consumer HTML

execute write calls against those resources need explicit user approval. Default path is a Pulumi/HTML patch in the owner repo, then pulumi preview.

Secrets

Never put siteToken, API tokens, or OAuth codes in handovers, memory MCP, or chat summaries. Refer to Pulumi outputs by name.

Markdown source