Skip to main content
Antes de empezar
Language

Cloudflare Workers

Agregue cside Device Intelligence con un Cloudflare Worker gestionado por el cliente que inyecta el script en respuestas HTML.

Use esta guía si quiere desplegar cside Device Intelligence en el edge de Cloudflare. Esta es una receta de Worker gestionada por el cliente. cside no necesita administrar su cuenta de Cloudflare para este setup.

Antes de empezar

Necesita:

  • Una zona de Cloudflare que enrute el tráfico de las páginas que quiere fingerprint
  • Permiso para crear o editar Workers y rutas de Worker
  • Device Intelligence activado para su equipo y la URL del script del equipo, que encontrará en la pestaña Cloudflare del panel de cside
  • Una clave API de Device Intelligence solo para backend generada en el dashboard de cside
  • Un endpoint backend que reciba la cadena del token extraída de la respuesta JSON devuelta por /client
Revise rutas existentes

Cloudflare permite solo un Worker en una ruta coincidente. Si otro Worker ya maneja la misma ruta, combine la lógica o elija una ruta de prueba más estrecha.

Despliegue recomendado

Empiece con una ruta limitada, como /login* o /checkout*, antes de aplicar el Worker a todo el sitio. Mantenga el Worker fail-open para que un problema de cside o del Worker no bloquee la entrega de páginas.

Consulte la guía de Workers Routes de Cloudflare para saber cómo aplicar un Worker a una ruta.

Ejemplo de Worker

Guarde su URL de script de cside como CSIDE_FINGERPRINT_SCRIPT_URL en el entorno del Worker.

function getFingerprintBootstrap(scriptURL) {
  return `<script>
(function () {
  const calls = [];
  let error;
  let timeoutID;

  function fallback(externalIds) {
    return error
      ? Promise.reject(error)
      : new Promise((resolve, reject) => {
          calls.push({ externalIds, resolve, reject });
        });
  }

  function rejectAll(nextError) {
    if (error) {
      return;
    }

    error = nextError;
    while (calls.length > 0) {
      calls.shift().reject(nextError);
    }
  }

  function flush(sendClientTelemetry) {
    while (calls.length > 0) {
      const call = calls.shift();
      Promise.resolve()
        .then(() => sendClientTelemetry(call.externalIds))
        .then(call.resolve, call.reject);
    }
  }

  window.sendClientTelemetry = window.sendClientTelemetry || fallback;

  const script = document.createElement("script");
  script.async = true;
  script.src = ${JSON.stringify(scriptURL)};
  script.referrerPolicy = "origin";
  script.setAttribute("data-src", "6");

  const fail = (nextError) => {
    clearTimeout(timeoutID);
    rejectAll(nextError);
  };

  script.onerror = () =>
    fail(new Error("cside client.js failed to load"));
  script.onload = () => {
    clearTimeout(timeoutID);
    const sendClientTelemetry = window.sendClientTelemetry;
    if (
      typeof sendClientTelemetry !== "function" ||
      sendClientTelemetry === fallback
    ) {
      rejectAll(new Error("cside telemetry unavailable"));
      return;
    }
    flush(sendClientTelemetry);
  };

  timeoutID = setTimeout(
    () => fail(new Error("cside client.js timed out while loading")),
    10000,
  );
  (document.head || document.documentElement).appendChild(script);
})();
</script>`;
}

export default {
  async fetch(request, env) {
    const response = await fetch(request);
    const contentType = response.headers.get("content-type") || "";

    if (!contentType.includes("text/html")) {
      return response;
    }

    try {
      return new HTMLRewriter()
        .on("head", {
          element(element) {
            element.append(
              getFingerprintBootstrap(env.CSIDE_FINGERPRINT_SCRIPT_URL),
              { html: true },
            );
          },
        })
        .transform(response);
    } catch {
      return response;
    }
  },
};

Intercambio de token

El Worker solo inyecta el script del navegador. No crea un fingerprint de sesión por sí solo. Su aplicación sigue llamando a sendClientTelemetry(externalIds?), recibe { token } desde /client y envía ese token de sesión a su backend.

Genere una clave API de Device Intelligence en el dashboard de cside antes de conectar el intercambio en backend. La clave empieza con cside_tgatv1_, se muestra solo una vez y debe guardarse como secreto del servidor. No la inserte en código de navegador.

Llame a sendClientTelemetry desde el código de su página o aplicación después de que cargue el script y luego lea la respuesta JSON devuelta por /client:

const result = await sendClientTelemetry({
  email: "user@example.com",
  userId: "1234567890",
});

if (result.errors) {
  console.error(result.errors);
  throw new Error("La solicitud de telemetría falló.");
}

const { token: sessionToken } = result;

if (!sessionToken) {
  throw new Error("No se devolvió ningún token de sesión de fingerprint.");
}

await fetch("/api/fingerprinting", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ sessionToken }),
});

/client devuelve JSON con la forma { "token": "..." }. También puede llamar a sendClientTelemetry() sin argumentos cuando no necesite adjuntar externalIds.

Su backend intercambia el token de sesión con cside llamando al endpoint de verificación autenticado:

curl https://api.cside.com/token/v2/verify \
  --request POST \
  --header "Authorization: Bearer $CSIDE_FINGERPRINT_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"token":"'"$CSIDE_FINGERPRINT_SESSION_TOKEN"'"}'

Ejemplo de handler backend:

app.post("/api/fingerprinting", async (request, reply) => {
  const { sessionToken } = request.body;

  const csideResponse = await fetch("https://api.cside.com/token/v2/verify", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.CSIDE_FINGERPRINT_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ token: sessionToken }),
  });

  const payload = await csideResponse.json();

  if (!csideResponse.ok) {
    // Los cuerpos de error son { error, code }; 429 también incluye retry-after: 60
    throw new Error(payload.error || "El intercambio de fingerprint falló.");
  }

  reply.code(csideResponse.status).send(payload);
});

Un 200 con "status": "failed" significa que cside no pudo evaluar la sesión; el motivo está en error_message. Consulte Recuperar datapoints para ver los códigos de error, el límite de solicitudes y las opciones de recuperación.

Notas operativas

  • Use rutas estrechas para el primer despliegue
  • Mantenga el Worker fail-open
  • No inyecte el script en respuestas que no sean HTML
  • Confirme que su CSP permite la URL del script de cside en script-src y https://edge.csidefd.com en connect-src
  • Mantenga la clave API de Device Intelligence solo en secretos del backend
  • Pase de rutas de prueba a cobertura completa después de ver datapoints en cside
Was this page helpful?