Skip to content

AI moderation report

The AI moderation report turns aggregated traffic quality data into a short, stakeholder-friendly report using Cloudflare Worker AI.

Flow

  1. 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.
  2. Summarize — The aggregated JSON is sent to Worker AI (model: @cf/meta/llama-3-8b-instruct).
  3. Parse — The AI response is parsed as JSON: summary, issues, campaign_problems, visitor_abuse, recommended_actions, blocking_recommendations.

API

GET /analytics/moderation/ai-report

ParamDescription
periodlast_24_hours (default) or last_7_days
projectOptional project filter
sourceOptional source filter
skip_aitrue to return only the data summary (no AI call)

Response (200):

json
{
  "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_ID and CLOUDFLARE_ANALYTICS_ENGINE_API_TOKEN (for aggregation queries).
  • Worker AI: The AI binding must be configured in wrangler.toml (see Workers AI bindings).

Code layout

  • src/analytics/moderationQueries.tsgetModerationSummary(env, period) builds the aggregated summary.
  • src/ai/moderationPrompt.ts — System and user prompts for the report.
  • src/ai/aiClient.tsgenerateModerationReport(env, summary) calls the model and parses JSON.
  • src/worker/moderationReportWorker.tsgetModerationReport(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

bash
npm run dev

Default 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> or X-API-Key: <key>
  • Local dev: In wrangler.toml under [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.

bash
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:

bash
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

ParamExampleEffect
periodlast_7_daysUse last 7 days instead of last 24 hours.
projectmy-projectFilter by project (blob1).
sourcegoogleFilter by source (blob2).
skip_aitrueReturn only summary; do not call AI.

Example:

bash
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

ScenarioAnalytics Engine (SQL API)AI binding
Summary only (skip_ai=true)Required (account ID + API token)Not needed
Full report (with AI)RequiredRequired ([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.