Engagement beacon
The wc.js landing-page script — what it collects, how it sends, privacy properties and manual integration.
Updated 2026-09-02
Install#
<script async src="https://app.whichclick.is/wc.js" data-endpoint="https://app.whichclick.is/api/protect/beacon"></script>The script reads wc_click_id from the URL, waits for interaction, and sends one beacon (via navigator.sendBeacon, falling back to fetch with keepalive) when the page is hidden or after 15 s.
Payload#
{ "click_id": "k3Zp9Qw1mR7tXc2b", "fingerprint": "5f2a…", "screen": "390x844", "timezone": "Europe/Istanbul", "languages": "tr-TR,en", "webdriver": false, "touch": true, "dwell_ms": 8200, "scroll": 62 }| Field | Used for |
|---|---|
fingerprint | Hash of canvas / fonts / UA data — reuse across many IPs indicates a farm |
screen, timezone, languages | Consistency with ValueTrack device, IP geo and Accept-Language |
webdriver, touch | Automation detection |
dwell_ms, scroll | Engagement; zero engagement plus other signals raises the score |
A click that never receives a beacon after 30 s gets a small "no engagement" weight (landing pages without the script are configurable to skip this).
Privacy#
- No cookies, no persistent identifiers, no PII. The fingerprint is a salted hash that cannot be reversed to device characteristics.
- The beacon is sent with
Content-Type: text/plainto avoid a CORS preflight; the endpoint accepts JSON or text. - Under GDPR / ePrivacy the beacon is a strictly necessary fraud-prevention measure; document it in your privacy notice. If your CMP blocks it before consent, protection still works from server-side signals.
Manual integration#
navigator.sendBeacon("https://app.whichclick.is/api/protect/beacon", JSON.stringify({ click_id, dwell_ms: 5000, scroll: 40 }));Responses: 200 {"ok":true}, 404 for an unknown click id (beacons for clicks older than 24 h are dropped).