DataLook Docs

Security & CSP

What the browser script can and can't do, the Content-Security-Policy directives it needs, and why the proxy install is the strongest setup.

A script in your <head> runs with full page privileges, so it's fair to ask what ours actually does before you ship it. This page is the honest answer, plus the exact CSP directives to lock it down.

What the script can and can't do

The SDK is a single minified IIFE. You can read the whole thing — it's served unobfuscated at https://cdn.datalook.app/s.js.

PropertyStatus
eval, Function(), innerHTMLNone. Nothing dynamic to inject into.
Cookies / localStorageNot used. The visitor id is hashed server-side; the browser stores no identifier.
Active fingerprinting (canvas, WebGL, fonts)None.
Credentials on requestsOmitted (credentials: 'omit'). No cookies ride along.
Global footprintOne global, window.analytics. No prototype patching.
Failure isolationSends are wrapped in try/catch; a bot context gets no-op stubs. A failure can't throw into your render.
PII in custom propertiesKeys matching email / phone / password / ssn are dropped in the browser and again server-side.

One global we do touch

To track route changes in single-page apps, the SDK wraps history.pushState and replaceState (it calls your original and preserves its return value). This is standard for SPA analytics. It's the only host global we touch.

What we collect from the browser

Beyond the URL, referrer, and UTM tags, each event carries a small env object: screen and viewport size, device pixel ratio, color depth, language, and timezone. This is passive context, not active fingerprinting — but it's not nothing, so we name it here rather than hide it. No PII, no canvas hashes, no font enumeration.

Content-Security-Policy

The SDK needs no unsafe-inline and no unsafe-eval — it's an external script that only loads and sends data. If you run a CSP, allow our origin for loading (script-src) and sending (connect-src):

script-src 'self' https://cdn.datalook.app;
connect-src 'self' https://cdn.datalook.app;

connect-src covers both navigator.sendBeacon and the fetch fallback.

The proxy install needs no third-party origin at all

Once you've done the first-party proxy setup, the script and the collector both come from your own domain — so the directives collapse to:

script-src 'self';
connect-src 'self';

There's no external origin to allowlist, nothing for an ad blocker to match, and a tighter CSP. It's the strongest of the two setups on every axis.

Why there's no SRI hash

Subresource Integrity pins a script to a fixed hash. We ship fixes and improvements to s.js on the CDN, so a pinned hash would break the moment we update — the same constraint every auto-updating analytics script lives with. Instead, the script is small enough to read end to end, and the proxy install lets you serve it from infrastructure you control.

Transport details

  • navigator.sendBeacon(<endpoint>, body) with a fetch({ keepalive: true }) fallback.
  • Content-Type: text/plain so the request is a CORS simple request — no preflight to misconfigure.
  • The endpoint is resolved relative to the script's URL (see the proxy overview).

What's next

  • Lock down the third-party origin entirely with the first-party proxy.
  • The full privacy stance (cookieless ids, IP handling) lives on the marketing site's privacy page.

On this page