Skip to main content
Before you start
Language

Cloudflare Workers

Add cside fingerprinting through a customer-managed Cloudflare Worker that injects the browser script into HTML responses.

Use this guide when you want to deploy cside fingerprinting at the Cloudflare edge. This is a customer-managed Worker recipe. cside does not need to manage your Cloudflare account for this setup.

Before you start

You need:

  • A Cloudflare zone that routes traffic for the pages you want to fingerprint
  • Permission to create or edit Workers and Worker routes
  • The cside fingerprinting script URL for your domain
  • A backend-only fingerprint API key generated in the cside dashboard
  • A backend endpoint that receives the token string extracted from the JSON response returned by /client
Check existing routes

Cloudflare allows only one Worker on a matching route. If another Worker already handles the same path, merge the logic or choose a narrower test route.

Start with a limited route, such as /login* or /checkout*, before routing the Worker across the full site. Keep the Worker fail-open so a cside or Worker issue does not block page delivery.

See Cloudflare’s Workers Routes guide for how to apply a Worker to a route.

Worker example

Store your cside script URL as CSIDE_FINGERPRINT_SCRIPT_URL in the Worker environment.

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(
              `<script src="${env.CSIDE_FINGERPRINT_SCRIPT_URL}" referrerpolicy="origin" data-src="6"></script>`,
              { html: true },
            );
          },
        })
        .transform(response);
    } catch {
      return response;
    }
  },
};

Token exchange

The Worker only injects the browser script. It does not create a session fingerprint by itself. Your application still calls sendClientTelemetry(externalIds?), receives { token } from /client, and sends that session token to your backend.

Generate a fingerprint API key in the cside dashboard before you wire the backend exchange. The key starts with cside_tgatv1_, is shown only once, and must be stored as a server-side secret. Do not embed it in browser code.

Call sendClientTelemetry from your page or app code after the script loads, then read the JSON response returned by /client:

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

if (result.errors) {
  console.error(result.errors);
  throw new Error("Telemetry request failed.");
}

const { token: sessionToken } = result;

if (!sessionToken) {
  throw new Error("No fingerprint session token was returned.");
}

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

/client returns JSON in the shape { "token": "..." }. You can also call sendClientTelemetry() with no arguments when you do not need to attach externalIds.

Your backend exchanges the session token with cside by calling the authenticated verification endpoint:

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"'"}'

Example backend handler:

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) {
    throw new Error(payload.error_message || "Fingerprint exchange failed.");
  }

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

See Retrieving datapoints for retrieval options.

Operational notes

  • Use narrow routes for the first rollout
  • Keep the Worker fail-open
  • Do not inject the script into non-HTML responses
  • Confirm your CSP allows the cside script URL and token exchange endpoint
  • Keep the fingerprint API key only in backend secrets
  • Move from test paths to full coverage after you see datapoints in cside
Was this page helpful?