feat(x): stamp platform=desktop on all analytics events

Registered as a posthog-js super property in the renderer and merged
into every posthog-node capture/identify in main, plus set as a person
property. Segments desktop traffic from the legacy web dashboard's
anonymous autocapture if it ever shares the PostHog project. Desktop
app only — the web app is legacy and intentionally untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Arjun 2026-07-15 07:50:39 +05:30
parent 86589dbe50
commit 1c895c7db6
3 changed files with 14 additions and 13 deletions

View file

@ -16,7 +16,7 @@
## Event catalog
All PostHog events include `app_version` automatically. Main-process events add it in `packages/core/src/analytics/posthog.ts`; renderer events get it from the `analytics:bootstrap` IPC payload and an initialization-time `before_send` hook.
All PostHog events include `app_version` and `platform: 'desktop'` automatically. Main-process events add them in `packages/core/src/analytics/posthog.ts`; renderer events get them from the `analytics:bootstrap` IPC payload via `posthog.register` (plus an initialization-time `before_send` hook for `app_version`). `platform` guards against the legacy web dashboard's autocapture (`apps/rowboat`, unidentified by design) muddying desktop dashboards if it ever shares the project.
### `llm_usage`
@ -192,6 +192,7 @@ Persistent across sessions for the same user. Set via `posthog.people.set` or as
| `email` | main on identify | From `/v1/me`; powers PostHog cohort match + integrations |
| `plan`, `status` | main on identify | Subscription state |
| `api_url` | both processes (init + identify) | Distinguishes prod / staging / custom — assign meaning in PostHog dashboard. `https://api.x.rowboatlabs.com` = production |
| `platform` | both processes (init + identify) | Always `desktop` from this app; segments desktop users from any other surface |
| `app_version` | both processes (init + identify) | Electron app version; also included automatically on every event |
| `signed_in` | renderer | `true` while rowboat OAuth is connected |
| `{provider}_connected` | renderer | One of `gmail`, `calendar`, `slack`, `rowboat` |

View file

@ -11,18 +11,16 @@ export function configureAnalyticsContext(props: { appVersion?: string; apiUrl?:
appVersion = props.appVersion?.trim() || undefined
apiUrl = props.apiUrl?.trim() || undefined
const eventProperties = appVersionProperties()
if (Object.keys(eventProperties).length > 0) {
posthog.register(eventProperties)
}
// `platform` distinguishes desktop events from any other surface (e.g. the
// web dashboard's autocapture) sharing the PostHog project.
const eventProperties = { platform: 'desktop', ...appVersionProperties() }
posthog.register(eventProperties)
const personProperties = {
...(apiUrl ? { api_url: apiUrl } : {}),
...eventProperties,
}
if (Object.keys(personProperties).length > 0) {
posthog.people.set(personProperties)
}
posthog.people.set(personProperties)
}
export function identifyUser(userId: string, properties?: Record<string, unknown>) {

View file

@ -30,7 +30,7 @@ function getClient(): PostHog | null {
// distinguishes prod / staging / custom — meaning is assigned in PostHog).
client.identify({
distinctId: getInstallationId(),
properties: { api_url: API_URL, ...appVersionProperties() },
properties: { api_url: API_URL, ...baseProperties() },
});
} catch (err) {
console.error('[Analytics] Failed to init PostHog:', err);
@ -43,8 +43,10 @@ function activeDistinctId(): string {
return identifiedUserId ?? getInstallationId();
}
function appVersionProperties(): Record<string, string> {
return APP_VERSION ? { app_version: APP_VERSION } : {};
// Stamped on every event so desktop traffic is distinguishable from any other
// surface (e.g. the web dashboard's autocapture) sharing the PostHog project.
function baseProperties(): Record<string, string> {
return { platform: 'desktop', ...(APP_VERSION ? { app_version: APP_VERSION } : {}) };
}
export function capture(event: string, properties?: Record<string, unknown>): void {
@ -56,7 +58,7 @@ export function capture(event: string, properties?: Record<string, unknown>): vo
event,
properties: {
...properties,
...appVersionProperties(),
...baseProperties(),
},
});
} catch (err) {
@ -76,7 +78,7 @@ export function identify(userId: string, properties?: Record<string, unknown>):
properties: {
...properties,
api_url: API_URL,
...appVersionProperties(),
...baseProperties(),
},
});
identifiedUserId = userId;