Ensures 100% coverage regardless of which provider (c8/istanbul/v8)
is used by the CI.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 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>
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>
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>
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>
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>