@protal-ai/next
v0.3.0
Published
Protal Server SDK for Next.js. Captures server-side AI crawlers and agents (GPTBot, ClaudeBot, ChatGPT-User, etc.) plus dev-tool discovery probes (/llms.txt, /openapi.json, /.well-known/mcp.json).
Maintainers
Readme
@protal-ai/next
Protal Server SDK for Next.js — captures AI crawlers (GPTBot, ClaudeBot,
PerplexityBot, CCBot, Bytespider, Meta-ExternalAgent…) plus user-triggered
fetchers (ChatGPT-User, Claude-User, Perplexity-User) plus dev-tool discovery
probes (/llms.txt, /openapi.json, /.well-known/mcp.json) on the server
side, without sitting in your request path.
Drops into your project's proxy.ts (Next.js 16+) or middleware.ts
(Next.js 13 – 15) — same export shape, different filename.
Install
npm install @protal-ai/next
# or
pnpm add @protal-ai/nextUse (no existing proxy / middleware)
Create proxy.ts at your project root (next to package.json):
import { protalSDK } from "@protal-ai/next";
export default protalSDK({ siteId: "tnt_xxx" });
export const config = { matcher: ["/((?!_next/|api/internal/).*)"] };Replace tnt_xxx with the site id shown on your Protal Install SDK
dashboard.
Next.js 13 – 15: name the file
middleware.tsinstead. Same content.
Use (you already have a proxy / middleware)
import { logProtalEvent } from "@protal-ai/next";
import { NextResponse, type NextRequest } from "next/server";
export function proxy(req: NextRequest) { // or `middleware` on Next 13 – 15
logProtalEvent(req, { siteId: "tnt_xxx" });
// … your existing logic …
return NextResponse.next();
}
export const config = { matcher: ["/((?!_next/|api/internal/).*)"] };What it does
On every request that matches your matcher:
- Check
User-Agentagainst the AI-UA regex AND the request path against the agent-discovery file regex (~100 µs total). - If either matches, POST a small JSON event to
https://protal.ai/api/collect/v1/middlewarewithkeepalive: true. - Return
NextResponse.next()regardless — Protal errors never block the request.
The path-based signal catches dev-tool / MCP-client traffic (Cursor, Claude Code, Copilot, custom agents) that often use generic User-Agent strings we wouldn't otherwise recognise.
SLA contract
The edge handler is wrapped in try/catch end-to-end. Any internal exception
— network failure, malformed input, runtime API change — is swallowed and the
request continues normally. Our outage cannot take down your site.
Options
protalSDK({
siteId: string, // required: 12-char site id from Protal dashboard
collectUrl?: string, // override the collector base (default: https://protal.ai)
})Migrating from 0.1.x / 0.2.x
protalPixel was renamed to protalSDK in 0.3.0. The old name is still
exported as a deprecated alias and will be removed in 1.0.0 — update your
import when convenient:
- import { protalPixel } from "@protal-ai/next";
- export default protalPixel({ siteId: "..." });
+ import { protalSDK } from "@protal-ai/next";
+ export default protalSDK({ siteId: "..." });License
MIT.
