← Back

Connect Your Cloudflare Website to Agent & LLM Analytics (Using a Worker)

Are You on an Enterprise Cloudflare Plan?
If so, use the Cloudflare Logpush integration to connect your website instead.

Overview

This guide shows you how to use a Cloudflare Worker that calls the REST API to connect your website to Agent & LLM Analytics. This tracks pageviews, REST calls, MCP calls, and agentic commerce calls for ACP and UCP. Please contact us if you need help.

Step 1: Create a Worker

const KNOWN_AGENTS_ACCESS_TOKEN = "YOUR_ACCESS_TOKEN"
const MAX_ANALYTICS_BODY_BYTES = 250000

export default {
    async fetch(request, env, ctx) {
        const clonedRequest = getClonedBodyIfPossible(request)
        const startTime = Date.now()
        const response = await fetch(request)
        const duration = Date.now() - startTime
        const clonedResponse = getClonedBodyIfPossible(response)
        ctx.waitUntil(
            Promise.resolve()
                .then(() => {
                    return trackVisit(request, response, duration, clonedRequest, clonedResponse)
                })
                .catch(() => {})
        )
        return response
    },
}

function getClonedBodyIfPossible(requestOrResponse) {
    const contentType = requestOrResponse.headers.get("content-type")
    const contentLength = requestOrResponse.headers.get("content-length")
    if (contentType?.toLowerCase().includes("json") != true || Number(contentLength) > MAX_ANALYTICS_BODY_BYTES) {
        return undefined
    }
    try {
        return requestOrResponse.clone()
    } catch {
        return undefined
    }
}

async function getJSONBody(requestOrResponse) {
    if (!requestOrResponse) {
        return undefined
    }
    try {
        return await requestOrResponse.json()
    } catch {
        return undefined
    }
}

async function trackVisit(request, response, duration, clonedRequest, clonedResponse) {
    const requestBody = await getJSONBody(clonedRequest)
    const responseBody = await getJSONBody(clonedResponse)
    const isUCPRequest = request.headers.get("ucp-agent") != undefined
    const isACPRequest = !isUCPRequest && request.headers.get("api-version") != undefined
    const mcpResult = responseBody?.result
    const acpResponseBody = isACPRequest ? mcpResult?.structuredContent ?? mcpResult ?? responseBody : undefined
    const ucpResponseBody = isUCPRequest ? mcpResult?.structuredContent ?? mcpResult ?? responseBody : undefined
    const requestURL = new URL(request.url)
    await fetch("https://api.knownagents.com/visits", {
        method: "POST",
        headers: {
            "Authorization": `Bearer ${KNOWN_AGENTS_ACCESS_TOKEN}`,
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            request_path: requestURL.pathname + requestURL.search,
            request_method: request.method,
            response_status_code: response.status,
            response_headers: {
                "content-type": response.headers.get("content-type"),
                "mcp-session-id": response.headers.get("mcp-session-id"),
            },
            response_duration_in_milliseconds: duration,
            request_headers: {
                "cf-connecting-ip": request.headers.get("cf-connecting-ip"),
                "user-agent": request.headers.get("user-agent"),
                "referer": request.headers.get("referer"),
                "signature": request.headers.get("signature"),
                "signature-agent": request.headers.get("signature-agent"),
                "signature-input": request.headers.get("signature-input"),
                "api-version": request.headers.get("api-version"),
                "ucp-agent": request.headers.get("ucp-agent"),
                "mcp-session-id": request.headers.get("mcp-session-id"),
            },
            mcp_request_method: requestBody?.method,
            mcp_request_tool_name: requestBody?.params?.name,
            mcp_request_client_info_name: requestBody?.params?.clientInfo?.name,
            mcp_request_client_info_version: requestBody?.params?.clientInfo?.version,
            mcp_response_result_is_error: mcpResult?.isError,
            mcp_response_error_code: responseBody?.error?.code,
            mcp_response_error_message: responseBody?.error?.message,
            acp_response_body: acpResponseBody,
            ucp_response_body: ucpResponseBody,
        }),
    })
}

Step 2: Test Your Integration

If your website is correctly connected, you should see visits from a test agent in the realtime timeline within a few seconds.