Data collected
On every page (aggregate counts only)
One beacon per page view and per widget open carrying: page path (no query string), utm_source / utm_medium / utm_campaign, and a device class. The server adds a country code from the IP address and drops the IP. Stored as daily totals per page, campaign, country and device, capped at 500 paths and 50 campaign values per day.
When a visitor sends feedback
- Always: rating and/or message, page URL and title, referrer, UTM tags, device class, browser, language, timezone, viewport, page timing.
- Problem reports and ratings of 1–2 add: last 20 failed requests (method, URL without query, status, duration), last 50 console errors/warnings (≤300 chars each), last 20 JavaScript errors, last 5 click targets as CSS selectors.
- Optional: an email or phone number the visitor chooses to leave, with their opt-in.
Redaction
Applied in the browser and again on the server to messages, console lines, error messages and request URLs: email addresses → [email]; bearer tokens, JWTs, API keys and 32+ character hex or base64 runs → [token]; 13–19 digit runs → [card]; query strings removed entirely.
Limits
Message ≤ 2,000 characters, contact ≤ 200, context ≤ 32 KB, request body ≤ 64 KB. Rate limits per visitor and per project; Cloudflare Turnstile checks run invisibly and failures are stored as spam rather than shown to the visitor.