> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tryprofound.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuración de Cloudflare

> Enruta el tráfico de asistentes de IA a Profound Dynamic Bot Rendering con un solo Worker de Cloudflare, manteniendo el tráfico humano y de rastreadores de búsqueda en tu origen.

Esta guía agrega un Worker de Cloudflare a tu zona. El Worker inspecciona el `User-Agent`, reenvía a Profound las solicitudes de asistentes de IA que coinciden y transmite todo lo demás directamente a tu origen.

El Worker llama al endpoint general de Profound, `GET https://concierge.tryprofound.com/v1/concierge`, y proporciona el host y la ruta originales como encabezados.

<Warning>
  Un Worker en una ruta `/*` se ejecuta en cada solicitud a ese nombre de host, por lo que forma parte de la ruta de solicitudes de producción. El código reintenta en tu origen ante fallos de obtención, un plazo límite para los encabezados de respuesta y los estados `400`, `401`, `403`, `500`, `502`, `503` y `504`. Transmite los demás estados, incluidas las redirecciones, `404` y `429`. Adapta la lista de páginas públicas permitidas y el presupuesto de latencia, y luego prueba primero en un nombre de host de staging. Un fallo después de que comienza la transmisión de la respuesta no puede reemplazar de forma transparente un cuerpo enviado parcialmente.
</Warning>

## Requisitos previos

* Una cuenta de Cloudflare con Workers habilitado en la zona
* Un registro DNS con proxy existente para el nombre de host y un origen accesible a través de él. Usa una [Worker Route](https://developers.cloudflare.com/workers/configuration/routing/routes/), no un Worker Custom Domain.
* Un inventario de las rutas de Worker existentes y superpuestas. Conserva su lógica en lugar de reemplazarla. Si combinarlas requiere un cambio de diseño, detente y revísalo por separado.
* Un modo de fallo de ruta registrado y una verificación de capacidad frente a los [límites de Workers](https://developers.cloudflare.com/workers/platform/limits/). Usa fail-open para el agotamiento de cuota solo cuando omitir el Worker preserve la seguridad existente. Fail-closed también puede afectar al tráfico humano, antes de que se ejecute el catch de JavaScript.
* Permiso para agregar rutas de Worker para el nombre de host
* Tu clave de API de Dynamic Bot Rendering, un dominio registrado, una política de servicio y una página de prueba publicada conocida. Consulta [Antes de empezar](/es/dynamic-bot-rendering/overview#before-you-start).

## Configuración

<Steps>
  <Step title="Crea el Worker">
    En el panel de Cloudflare, abre **Workers & Pages → Create → Create Worker**. Asígnale el nombre `profound-bot-rendering` y despliega el marcador de posición para que el Worker exista.
  </Step>

  <Step title="Agrega el código del Worker">
    En el nuevo Worker, abre **Edit code** y agrega lo siguiente. Reemplaza las cuatro rutas de ejemplo con páginas públicas revisadas. No sobrescribas la lógica de Worker existente.

    ```js theme={null}
    const CONCIERGE_ENDPOINT = 'https://concierge.tryprofound.com/v1/concierge';

    // Keep this list in sync with the supported assistants in the Profound docs.
    const BOT_RE = /duckassistbot|chatgpt-user|gemini-deep-research|perplexity-user|amzn-user|mistralai-user|claude-user|claude-code|codex/i;

    // Explicit public pages only. Review each path before extending this list.
    const PUBLIC_PATHS = new Set(['/', '/pricing', '/docs', '/docs/getting-started']);
    const UPSTREAM_TIMEOUT_MS = 2000; // Example header deadline; leave time for origin fallback.
    const FORWARDED_HEADERS = ['user-agent', 'accept', 'accept-encoding', 'accept-language'];

    // Statuses that mean "Profound could not serve this" rather than "the origin
    // said so". 404 is deliberately absent: Profound fails open internally and
    // returns your origin's own status, so a 404 is your real 404.
    const FAILOVER_STATUSES = new Set([400, 401, 403, 500, 502, 503, 504]);

    async function failOpen(request) {
      // A subrequest to the same zone goes to the origin without re-running this Worker.
      const originResponse = await fetch(request);
      const response = new Response(originResponse.body, originResponse);
      response.headers.set('x-concierge-cdn-failover', '1');
      return response;
    }

    export default {
      async fetch(request, env) {
        const url = new URL(request.url);
        const userAgent = request.headers.get('user-agent') || '';

        // Loop protection: Profound stamps this on its own origin fetches.
        // Passing it through means those fetches reach the origin directly.
        if (request.headers.has('x-concierge-request')) return fetch(request);

        if (request.method !== 'GET') return fetch(request);
        if (request.headers.has('cookie') || request.headers.has('authorization')) return fetch(request);

        const isAssistant = BOT_RE.test(userAgent);
        if (!isAssistant || !PUBLIC_PATHS.has(url.pathname)) return fetch(request);

        // Copy only required negotiation headers, never viewer credentials or identity.
        const headers = new Headers();
        for (const name of FORWARDED_HEADERS) {
          const value = request.headers.get(name);
          if (value !== null) headers.set(name, value);
        }

        headers.set('x-concierge-api-key', env.PROFOUND_CONCIERGE_KEY);
        headers.set('x-concierge-host', url.hostname);
        headers.set('x-concierge-url', url.pathname + url.search);

        const controller = new AbortController();
        const timeout = setTimeout(() => controller.abort(), UPSTREAM_TIMEOUT_MS);
        try {
          const response = await fetch(CONCIERGE_ENDPOINT, {
            method: 'GET',
            headers,
            redirect: 'manual', // pass redirects through instead of following them
            cache: 'no-store', // also verify the endpoint owner's cache policy
            signal: controller.signal,
          });

          if (FAILOVER_STATUSES.has(response.status)) {
            if (response.body) void response.body.cancel().catch(() => {});
            controller.abort();
            return failOpen(request);
          }
          const result = new Response(response.body, response);
          result.headers.set('cache-control', 'no-store');
          return result;
        } catch {
          return failOpen(request);
        } finally {
          clearTimeout(timeout);
        }
      },
    };
    ```

    El ejemplo concede 2 segundos para los encabezados de respuesta de Profound. Elige un valor acotado que deje tiempo suficiente para la respuesta de tu origen dentro del presupuesto de latencia del asistente. El plazo termina cuando llegan los encabezados; no limita la transmisión del cuerpo de la respuesta. Workers admite [AbortController](https://developers.cloudflare.com/workers/runtime-apis/web-standards/).
  </Step>

  <Step title="Guarda la clave de API como secreto">
    Abre **Settings → Variables and Secrets**, agrega un secreto llamado `PROFOUND_CONCIERGE_KEY` y pega tu clave de API. Guarda y despliega.

    Usa un secreto en lugar de una variable de entorno en texto plano. Los secretos son de solo escritura una vez guardados, por lo que la clave permanece oculta en el panel.

    Para hacer lo mismo con Wrangler:

    ```bash theme={null}
    npx wrangler secret put PROFOUND_CONCIERGE_KEY
    ```
  </Step>

  <Step title="Asocia el Worker a tu nombre de host">
    Abre **Settings → Domains & Routes → Add route**, introduce el patrón para el tráfico de tus páginas y selecciona la zona.

    ```text theme={null}
    www.example.com/*
    ```

    Si tu sitio sirve recursos desde el mismo nombre de host, el Worker igualmente se ejecuta en ellos y los devuelve con una obtención simple del origen. Para mantener el Worker completamente fuera de esa ruta, acota el patrón de ruta en lugar de depender de la verificación de rutas del código.
  </Step>

  <Step title="Verifica">
    Comprueba el enrutamiento y luego verifica por separado la página publicada conocida y el tráfico excluido:

    ```bash theme={null}
    curl -sD - -o /dev/null https://www.example.com/pricing -A 'chatgpt-user'
    ```

    Comprueba el estado HTTP, un `x-concierge-request-id` válido y `x-concierge-bot-kind: chatgpt-user`. En tu página de prueba publicada, exige también `x-concierge-cache: HIT` y el cuerpo HTML esperado. Una solicitud normal de navegador debería permanecer en la ruta de tu origen. Prueba también solicitudes que no sean `GET`, de API, de recursos y con credenciales.

    Las comprobaciones completas y el significado de los encabezados están en [Verificar y solucionar problemas](/es/dynamic-bot-rendering/verify-and-troubleshoot).
  </Step>
</Steps>

## Caché

La llamada ascendente del Worker nunca debe almacenarse en caché. Todas las páginas usan la misma URL ascendente, `https://concierge.tryprofound.com/v1/concierge`, y el host, la ruta y la consulta que identifican la página viajan solo en encabezados de confianza. Si esa URL se almacenara en caché sin esos encabezados en la clave de caché, distintas páginas o hosts colisionarían, y agregar `User-Agent` a la clave no lo solucionaría.

El ejemplo usa la [configuración de fetch `cache: 'no-store'`](https://developers.cloudflare.com/workers/runtime-apis/fetch/) y marca las respuestas devueltas por Profound con `Cache-Control: no-store`. [Cloudflare evalúa el almacenamiento en caché según la URL de la subsolicitud fetch](https://developers.cloudflare.com/workers/reference/how-the-cache-works/), no según la URL del visitante, por lo que las reglas de caché de tu propia zona no se aplican a la llamada ascendente.

Antes del despliegue, envía solicitudes repetidas de asistente a dos rutas publicadas y a una variante con consulta de cada una, y confirma que cada respuesta incluye un `x-concierge-request-id` nuevo. Revisa también cualquier otra capa de caché delante de tu sitio para comprobar la separación entre asistentes y humanos, y qué sucede con las entradas en caché después de publicar un reemplazo, despublicar o pausar. No agregues una clave de caché basada solo en `User-Agent` como solución alternativa. Si necesitas almacenar en caché las respuestas de Profound en tu edge, comunícate primero con el soporte de Profound: la clave de caché debe incluir la identidad del host, la ruta y la consulta, y debe invalidarse cuando cambien las publicaciones.

## Cómo protege el Worker tu sitio

* **Los encabezados ascendentes están en una lista de permitidos.** Para las solicitudes enrutadas, el Worker copia solo `User-Agent`, `Accept`, `Accept-Encoding` y `Accept-Language`, y luego establece la clave, el host y la ruta de confianza. No copia la identidad `x-concierge-*` ni las credenciales proporcionadas por el cliente. Las solicitudes que llevan cookies o autorización omiten Profound por completo. Las solicitudes ordinarias que se omiten conservan sus encabezados para tu origen.
* **La protección contra bucles no es autenticación.** El marcador se puede falsificar; nunca lo uses para omitir reglas de WAF o controles de acceso. Consulta los [requisitos previos de contenido público](/es/dynamic-bot-rendering/overview#before-you-start).
* **La protección contra bucles funciona en ambos sentidos.** Profound marca con `x-concierge-request` sus propias obtenciones de origen, y el Worker las transmite directamente. Profound también rechaza cualquier solicitud entrante que lleve ese encabezado, por lo que incluso una regla mal configurada interrumpe una sola solicitud en lugar de entrar en bucle.
* **La clave nunca llega al navegador.** Se guarda en un secreto del Worker y solo se adjunta en la llamada ascendente.
* **Las redirecciones se transmiten.** `redirect: 'manual'` devuelve una redirección al asistente en lugar de seguirla, por lo que el manejo de redirecciones sigue siendo decisión de tu origen.
