From 3ea7f44fd19766c748871f990b9fd20d387368e0 Mon Sep 17 00:00:00 2001 From: rouggy Date: Fri, 24 Jul 2026 16:20:23 +0200 Subject: [PATCH] telemetry: use station callsign as the PostHog distinct_id (dedupe users) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The random per-install UUID lives in the LOCAL SQLite, so one operator running OpsLog on several machines (laptop / desktop / Maestro) or after a reinstall counted as several distinct "users" — making the user total unreliable. Use the station callsign as distinct_id when set (public in ham radio, stable across all of an op's machines); the install UUID stays as a fallback and rides along as an install_id property so per-machine detail isn't lost. --- telemetry.go | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/telemetry.go b/telemetry.go index beca88f..77d9975 100644 --- a/telemetry.go +++ b/telemetry.go @@ -85,15 +85,27 @@ func (a *App) sendTelemetryHeartbeat() { return // already counted today } + // distinct_id identifies the USER. Prefer the station callsign — it's stable + // across every machine/reinstall the same operator runs, so one op counts as + // one user (a callsign is public in amateur radio). The random per-install ID + // is only a fallback until a callsign is configured; without it the same op on + // a laptop + desktop + Maestro showed up as three "users". install_id rides + // along as a property so multiple machines under one callsign stay visible. + installID := a.telemetryInstallID() + distinctID := installID + if call := a.activeCallsign(); call != "" { + distinctID = call + } payload := map[string]any{ "api_key": posthogAPIKey, "event": "app_opened", - "distinct_id": a.telemetryInstallID(), + "distinct_id": distinctID, "properties": map[string]any{ - "version": appVersion, - "os": runtime.GOOS, - "arch": runtime.GOARCH, - "$lib": "opslog", + "version": appVersion, + "os": runtime.GOOS, + "arch": runtime.GOARCH, + "install_id": installID, + "$lib": "opslog", }, "timestamp": time.Now().UTC().Format(time.RFC3339), }