Commit Graph

10 Commits

Author SHA1 Message Date
Serreau Jovann
b1ec125bb9 Achieve 100% coverage on analytics.js
- Add test for navigator.language falsy branch
- Add test for retry getOrCreateVisitor failing on second attempt
- Mark unreachable defensive guards (encrypt/decrypt/send with null encKey)
  with c8 ignore since they cannot be triggered via public API

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 20:17:21 +02:00
Serreau Jovann
59cf8dccde Fix linter warnings in analytics module: codePoint, const, optional chaining, Number.parseInt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:34:22 +01:00
Serreau Jovann
20a6be0504 Destructure browser globals from globalThis in analytics module
Fixes linter warnings for sessionStorage, navigator, document, location, screen, fetch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:11:15 +01:00
Serreau Jovann
73adc0a735 Use globalThis for TextEncoder, TextDecoder, and atob browser globals
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:08:37 +01:00
Serreau Jovann
a71493b87c Replace charCodeAt with codePointAt in analytics module
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:07:26 +01:00
Serreau Jovann
b062a5203b Use globalThis.atob/btoa in analytics module for linter compatibility
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:06:55 +01:00
Serreau Jovann
6ce56c11e0 Clear sessionStorage on 403 and retry with fresh visitor
When SECRET_ANALYTICS changes (deploy), old uid/hash become invalid.
On 403, clear session and auto-retry with a new visitor creation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 13:41:34 +01:00
Serreau Jovann
a139f86b90 Make analytics endpoint dynamic: /t/{token} derived from APP_SECRET
The endpoint path is now /t/<8-char hash of APP_SECRET> instead of
static /t. Token is injected via data-e attribute on body, read by JS.
Server validates token on every hit, returns 404 if invalid.
Changes with each APP_SECRET = impossible to hardcode in a blocker.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 12:22:59 +01:00
Serreau Jovann
d57669b5b9 Enable analytics tracking in dev and prod
Remove dev environment check — tracking runs everywhere.
Data won't mix since each environment has its own database.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 12:06:12 +01:00
Serreau Jovann
6438afadbf Add first-party analytics tracker with encrypted transmissions
Core system:
- AnalyticsUniqId entity (visitor identity with device/os/browser parsing)
- AnalyticsEvent entity (page views linked to visitor)
- POST /t endpoint with AES-256-GCM encrypted payloads
- HMAC-SHA256 visitor hash for anti-tampering
- Async processing via Messenger
- JS module: auto page_view tracking, setAuth for logged users
- Encryption key shared via data-k attribute on body
- setAuth only triggers when cookie consent is accepted
- Clean CSP: remove old tracker domains (Cloudflare, Umami)

100% first-party, no cookies, invisible to adblockers, RGPD-friendly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:07 +01:00