diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9774b36..e5ef186 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -195,6 +195,7 @@ The website code lives under `src/`: - `src/client/` — browser-side TypeScript (search, filter, dark mode), Tailwind entry, and the vendored Outfit fonts under `fonts/` that social cards are rendered with. - `src/build/` — SSG pipeline (renders pages, compiles assets, emits JSON API, generates a social card per page). - `src/server/` — Express dev server. +- `src/tracking/` — API usage tracking; the root `middleware.ts` posts one Web Analytics custom event per JSON API request at the edge. Everything the catalog ships beyond the static site: diff --git a/README.md b/README.md index 256e1b3..c2e73bb 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,8 @@ curl https://modelparams.dev/api/v1/models/openai/gpt-5.5.json Schema at `https://modelparams.dev/api/v1/schema.json`, per the [Model Parameters convention](docs/model-parameters-schema.md). +API requests are counted at the edge and reported to Vercel Web Analytics as `api_request` custom events (endpoint, model, client type), so API usage lands in the same dashboard as page views. Off Vercel it's a no-op; see [`src/tracking/api-usage.ts`](src/tracking/api-usage.ts). + ### Validate a request POST the parameters you're about to send. You get back what's wrong — including combinations the provider rejects — and a corrected payload. diff --git a/middleware.ts b/middleware.ts new file mode 100644 index 0000000..73d8d87 --- /dev/null +++ b/middleware.ts @@ -0,0 +1,22 @@ +import { trackApiUsage } from "./src/tracking/api-usage.js"; + +/** + * Vercel Edge Middleware: counts requests to the JSON API, the MCP server, + * and the llms.txt companion files as Web Analytics custom events. Middleware + * runs before the CDN cache and before rewrites, so /mcp needs its own matcher + * entry even though it rewrites to /api/mcp. What gets recorded is documented + * in src/tracking/api-usage.ts. + */ +export const config = { + matcher: ["/api/:path*", "/mcp", "/llms.txt", "/llms-full.txt"], +}; + +interface MiddlewareContext { + waitUntil(promise: Promise): void; +} + +export default function middleware(request: Request, context: MiddlewareContext): void { + const pending = trackApiUsage(request); + if (pending) context.waitUntil(pending); + // Returning nothing lets the request fall through to the static files. +} diff --git a/src/tracking/api-usage.ts b/src/tracking/api-usage.ts new file mode 100644 index 0000000..3bb850b --- /dev/null +++ b/src/tracking/api-usage.ts @@ -0,0 +1,169 @@ +/** + * Server-side usage tracking for the JSON API, reported to Vercel Web + * Analytics so API traffic shows up in the same dashboard as page views. + * + * The API is static files on Vercel's CDN, so the Web Analytics