Problem
The backend forwards a GA4 event for every websocket ping — SessionTracker.handlePing() calls tracker.sendEvent(userUUID, "CLIENT_PING", ...) on each ping (src/utils/socket-session-tracker.ts:119). The native client pings every 30 seconds, so one always-on screensaver machine generates ~2,880 client_ping GA events per day, all attributed to a single user_id.
Consequences:
- GA shows a persistent property-level warning: "Your property is losing data due to user-ID implementation issue — a significant number of activities were linked to the user ID …". The named UUID is just whoever currently has the most connected machine-hours (most recently a brand-new account with an always-on machine); the warning itself is triggered by our ping firehose, not by user misbehavior.
- GA flags this as a broken user-ID implementation, which it says can affect event measurement, attribution, and session recognition for the whole property.
- The ping events add no analytics value that we don't already capture:
CLIENT_END already reports duration_seconds for the session (socket-session-tracker.ts:152-159), and CLIENT_START marks session begin.
Proposed fix
Stop sending CLIENT_PING to GA entirely:
- Remove the
tracker.sendEvent(... "CLIENT_PING" ...) call from handlePing() in src/utils/socket-session-tracker.ts (keep the in-memory ping bookkeeping — it feeds the CLIENT_END duration metrics).
- Remove the
CLIENT_PING key from src/constants/google-analytics.constants.ts and its type usage.
- (There is also an already-commented-out CLIENT_PING send in
src/socket/remote-control.ts:530 that can be deleted.)
Session time-in-app remains measurable via CLIENT_START / CLIENT_END (duration_seconds). If finer-grained liveness is ever needed in GA, send a sampled/aggregated heartbeat (e.g. one event per hour per session), not per-ping.
Acceptance
- No
client_ping events arriving in GA4 for new sessions.
- GA user-ID implementation warning clears after a few days.
- Session duration metrics still present via
client_end.
Problem
The backend forwards a GA4 event for every websocket ping —
SessionTracker.handlePing()callstracker.sendEvent(userUUID, "CLIENT_PING", ...)on each ping (src/utils/socket-session-tracker.ts:119). The native client pings every 30 seconds, so one always-on screensaver machine generates ~2,880client_pingGA events per day, all attributed to a singleuser_id.Consequences:
CLIENT_ENDalready reportsduration_secondsfor the session (socket-session-tracker.ts:152-159), andCLIENT_STARTmarks session begin.Proposed fix
Stop sending
CLIENT_PINGto GA entirely:tracker.sendEvent(... "CLIENT_PING" ...)call fromhandlePing()insrc/utils/socket-session-tracker.ts(keep the in-memory ping bookkeeping — it feeds theCLIENT_ENDduration metrics).CLIENT_PINGkey fromsrc/constants/google-analytics.constants.tsand its type usage.src/socket/remote-control.ts:530that can be deleted.)Session time-in-app remains measurable via
CLIENT_START/CLIENT_END(duration_seconds). If finer-grained liveness is ever needed in GA, send a sampled/aggregated heartbeat (e.g. one event per hour per session), not per-ping.Acceptance
client_pingevents arriving in GA4 for new sessions.client_end.