Seguimiento de crawlers de IA
Actualizado el 18 de octubre de 2026
Los crawlers de IA no ejecutan JavaScript, por lo que el script de Statsdot nunca los detecta. Para saber cuáles de ellos leen tu sitio, tu servidor debe reportar sus peticiones a Statsdot. A continuación, verás en el informe del sitio cada crawler con su número de peticiones y las páginas que más leen.
Solo se almacenan las peticiones cuyo user agent coincide con un crawler del directorio de crawlers de IA, junto con el crawler, la ruta sin cadena de consulta y el código de estado. Las peticiones de personas se ignoran incluso si tu servidor las envía, y no se almacena ninguna dirección IP.
1. Actívalo
En los ajustes del sitio, bajo Seguimiento de crawlers de IA, elige Activar y crear una clave. Copia la clave (empieza por sdb_). La clave solo puede reportar peticiones de crawlers; si se filtra, genera una nueva en el mismo lugar.
2. Conecta tu sitio
WordPress
En Ajustes > Statsdot del plugin, pega la clave en Seguimiento de crawlers de IA y guarda. Eso es todo.
Laravel
Añade este middleware al grupo web. Reporta después de que la respuesta haya sido enviada, por lo que los crawlers no sufren ralentizaciones:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Symfony\Component\HttpFoundation\Response;
class ReportAiCrawlers
{
private const TOKENS = ['gptbot', 'oai-searchbot', 'chatgpt-user', 'claudebot', 'claude-user', 'claude-searchbot', 'perplexitybot', 'perplexity-user', 'google-extended', 'googlebot', 'bingbot', 'applebot', 'meta-externalagent', 'bytespider', 'ccbot', 'amazonbot', 'duckassistbot', 'mistralai-user'];
public function handle(Request $request, Closure $next): Response
{
return $next($request);
}
public function terminate(Request $request, Response $response): void
{
$agent = strtolower((string) $request->userAgent());
foreach (self::TOKENS as $token) {
if (str_contains($agent, $token)) {
Http::timeout(2)->withHeaders(['X-Statsdot-Bot-Key' => config('services.statsdot.bot_key')])
->post('https://statsdot.com/api/bots', [
'user_agent' => $request->userAgent(),
'url' => $request->fullUrl(),
'status' => $response->getStatusCode(),
]);
return;
}
}
}
}
Pon la clave en .env como STATSDOT_BOT_KEY y en config/services.php como 'statsdot' => ['bot_key' => env('STATSDOT_BOT_KEY')]. Statsdot reconoce más crawlers que la lista corta anterior; amplíala con los tokens del directorio que te interesen.
PHP plano
Al final de tu controlador frontal (por ejemplo, index.php), después de que la página se haya enviado:
$agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
if (preg_match('/gptbot|oai-searchbot|chatgpt-user|claudebot|claude-user|claude-searchbot|perplexitybot|perplexity-user|googlebot|bingbot|applebot|meta-externalagent|bytespider|ccbot|amazonbot/i', $agent)) {
if (function_exists('fastcgi_finish_request')) {
fastcgi_finish_request();
}
$context = stream_context_create(['http' => [
'method' => 'POST',
'timeout' => 2,
'header' => "Content-Type: application/json\r\nX-Statsdot-Bot-Key: sdb_your_key\r\n",
'content' => json_encode([
'user_agent' => $agent,
'url' => 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'],
'status' => http_response_code(),
]),
]]);
@file_get_contents('https://statsdot.com/api/bots', false, $context);
}
Node.js y Express
const CRAWLERS = /gptbot|oai-searchbot|chatgpt-user|claudebot|claude-user|claude-searchbot|perplexitybot|perplexity-user|googlebot|bingbot|applebot|meta-externalagent|bytespider|ccbot|amazonbot/i;
app.use((req, res, next) => {
const agent = req.get('user-agent') || '';
if (CRAWLERS.test(agent)) {
res.on('finish', () => {
fetch('https://statsdot.com/api/bots', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-Statsdot-Bot-Key': process.env.STATSDOT_BOT_KEY },
body: JSON.stringify({ user_agent: agent, url: `${req.protocol}://${req.get('host')}${req.originalUrl}`, status: res.statusCode }),
}).catch(() => {});
});
}
next();
});
Next.js
En middleware.ts, reporta sin retrasar la respuesta:
import { NextResponse, type NextRequest, type NextFetchEvent } from 'next/server';
const CRAWLERS = /gptbot|oai-searchbot|chatgpt-user|claudebot|claude-user|claude-searchbot|perplexitybot|perplexity-user|googlebot|bingbot|applebot|meta-externalagent|bytespider|ccbot|amazonbot/i;
export function middleware(request: NextRequest, event: NextFetchEvent) {
const agent = request.headers.get('user-agent') ?? '';
if (CRAWLERS.test(agent)) {
event.waitUntil(fetch('https://statsdot.com/api/bots', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-Statsdot-Bot-Key': process.env.STATSDOT_BOT_KEY! },
body: JSON.stringify({ user_agent: agent, url: request.url }),
}).catch(() => {}));
}
return NextResponse.next();
}
El endpoint
POST https://statsdot.com/api/bots con la cabecera X-Statsdot-Bot-Key y un cuerpo JSON {"user_agent": "...", "url": "...", "status": 200}, o {"events": [...]} con hasta 100 peticiones. Responde con 202 y el número registrado. Hasta 600 peticiones por minuto por clave.
Límites
Cada cuenta registra hasta 100.000 peticiones de crawlers al mes en todos sus sitios; una vez superado este límite, no se registrarán más hasta el mes siguiente. Las peticiones de crawlers no cuentan para los eventos de tu plan. Se conservan durante el mismo tiempo que tus visitas (24 meses).