Fix analytics data-loss bugs and clean up the admin dashboard; v2.2.4
Publish Container / build (push) Successful in 16m3s

- Self-heal consent desync: if the server's consent cookie and the
  client's localStorage flag fall out of sync, the client now notices
  and stops silently sending events into a void.
- Stop double-counting hard page loads in hit/visitor stats.
- Flush pending disk writes on SIGTERM/SIGINT so redeploys don't drop
  the last few events.
- Log rate-limiter drops once per window (diagnoses proxy misconfig).
- Widen the bot-detection allowlist to avoid flagging real browsers
  (Chrome-iOS, Samsung Browser, etc.) as bots.
- Stop merging distinct visitors who share an IP when a real session
  cookie is already present — only fall back to IP correlation when no
  cookie was sent at all.
- Include analyticsEvents/episodePlays in backup snapshots and restore
  them, so a restore no longer wipes engagement analytics.
- Regroup admin dashboard KPI cards by time scope (range vs all-time)
  and remove a duplicated Top Countries/States block.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5 committed 2026-09-24 14:06:02 -04:00
1 parent 8496e227b3
commit d1a68754a1
9 files changed
+183 -45

No files matched your search

+7 -1
View File
@@ -413,7 +413,13 @@ export function detectBot(userAgent) {
return { isBot: true, reason: 'http-client' }
}
if (/bot|crawler|spider|scraper|indexer|reader|fetcher|loader|agent|spyware|tracking|monitor/.test(ua)) {
if (!/chrome|firefox|safari|opera|edge|msie|trident|like gecko/.test(ua)) {
// Generic keywords like "reader" or "agent" can appear as substrings of
// otherwise-normal browser UAs (e.g. some webviews, regional browsers).
// Any UA carrying a real rendering-engine or vendor token is treated as
// a genuine browser rather than a bot, even if it also matches a keyword
// above — this list should stay a superset of the previous one so it
// only ever reduces false positives, never re-admits an actual bot.
if (!/chrome|firefox|safari|opera|edge|msie|trident|gecko|webkit|khtml|presto|crios|fxios|ucbrowser|samsungbrowser/.test(ua)) {
return { isBot: true, reason: 'bot-keyword' }
}
}