AI moderation report
The AI moderation report turns aggregated traffic quality data into a short, stakeholder-friendly report using Cloudflare Worker AI.
Flow
- Aggregate — The Worker queries Analytics Engine for the chosen period (last 24 hours or last 7 days): totals (submissions, real leads, bots, blocked, duplicate rate, avg suspicion/engagement), top suspicious sources, campaigns, referers, countries, and high-risk visitors. No raw submission rows are used.
- Summarize — The aggregated JSON is sent to Worker AI (model:
@cf/meta/llama-3-8b-instruct). - Parse — The AI response is parsed as JSON: summary, issues, campaign_problems, visitor_abuse, recommended_actions, blocking_recommendations.
API
GET /analytics/moderation/ai-report
| Param | Description |
|---|---|
period | last_24_hours (default) or last_7_days |
project | Optional project filter |
source | Optional source filter |
skip_ai | true to return only the data summary (no AI call) |
Response (200):
{
"period": "last_24_hours",
"summary": { "totals": {...}, "suspicious_sources": [...], ... },
"ai_report": {
"summary": "Executive paragraph...",
"issues": ["Issue 1", "..."],
"campaign_problems": ["..."],
"visitor_abuse": ["..."],
"recommended_actions": ["..."],
"blocking_recommendations": ["..."]
},
"generated_at": "2025-03-09T12:00:00.000Z"
}If Analytics Engine is not configured or the summary query fails, the API returns 503. If the AI binding is missing or the model fails, ai_report is null but summary is still returned when available.
Requirements
- Analytics Engine:
CLOUDFLARE_ACCOUNT_IDandCLOUDFLARE_ANALYTICS_ENGINE_API_TOKEN(for aggregation queries). - Worker AI: The
AIbinding must be configured inwrangler.toml(see Workers AI bindings).
Code layout
src/analytics/moderationQueries.ts—getModerationSummary(env, period)builds the aggregated summary.src/ai/moderationPrompt.ts— System and user prompts for the report.src/ai/aiClient.ts—generateModerationReport(env, summary)calls the model and parses JSON.src/worker/moderationReportWorker.ts—getModerationReport(env, options)orchestrates summary + AI.
Planned later: Slack webhook, daily email, and cron trigger (see AI moderation report roadmap).
How to test
1. Start the Worker locally
npm run devDefault dev URL is usually http://localhost:8787 (see wrangler output). Use the same origin for the requests below.
2. Auth
Analytics endpoints (including the AI report) require the analytics API key:
- Header:
Authorization: Bearer <key>orX-API-Key: <key> - Local dev: In
wrangler.tomlunder[env.development.vars],ANALYTICS_API_KEY = "dev-analytics-key-change-me"(or your override).
Use that value for <key> in the examples below.
3. Summary only (no AI) — works without Analytics Engine token
Use skip_ai=true to get only the aggregated summary. This still needs Analytics Engine to be configured for the summary; if not, you get 503.
curl -s -H "Authorization: Bearer dev-analytics-key-change-me" \
"http://localhost:8787/analytics/moderation/ai-report?skip_ai=true"Expected (200): JSON with period, summary (totals, suspicious_sources, etc.), ai_report: null, generated_at.
If Analytics Engine is not configured: 503 and body like {"error":"Analytics Engine not configured or query failed"}.
4. Full report (with AI)
Omit skip_ai so the Worker calls the AI after building the summary:
curl -s -H "Authorization: Bearer dev-analytics-key-change-me" \
"http://localhost:8787/analytics/moderation/ai-report"Expected (200): Same as above but ai_report is an object with summary, issues, campaign_problems, visitor_abuse, recommended_actions, blocking_recommendations (strings/arrays). If the AI binding is missing or the model fails, ai_report can be null while summary is still present.
5. Optional query params
| Param | Example | Effect |
|---|---|---|
period | last_7_days | Use last 7 days instead of last 24 hours. |
project | my-project | Filter by project (blob1). |
source | google | Filter by source (blob2). |
skip_ai | true | Return only summary; do not call AI. |
Example:
curl -s -H "Authorization: Bearer dev-analytics-key-change-me" \
"http://localhost:8787/analytics/moderation/ai-report?period=last_7_days&skip_ai=true"6. Requirements by scenario
| Scenario | Analytics Engine (SQL API) | AI binding |
|---|---|---|
Summary only (skip_ai=true) | Required (account ID + API token) | Not needed |
| Full report (with AI) | Required | Required ([ai] in wrangler; enabled in dev) |
For Analytics Engine in dev, set secrets (or use a .dev.vars with):
CLOUDFLARE_ACCOUNT_ID— your Cloudflare account ID.CLOUDFLARE_ANALYTICS_ENGINE_API_TOKEN— token with Account Analytics Read (create in Cloudflare dashboard → Analytics → Workers Analytics Engine → API tokens).
Without these, the summary query returns null and the API responds with 503.