mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 23:00:03 +00:00
feat(cli): associate signed-in HeyGen account with telemetry (#2020)
* feat(cli): associate signed-in HeyGen account with telemetry Sign-in telemetry currently attributes everything to the anonymous install id, so the sign-in funnel can be counted but a completed sign-in can't be tied to the account it produced. This associates the two. - On a completed sign-in, emit a PostHog `$identify` alias whose `$anon_distinct_id` is the install's anonymousId, so events recorded before sign-in stitch to the same person, and tag `auth_login_completed` with the account identity (the pre-plumbed `distinctId`). - `/v3/users/me` exposes no opaque user_id, so the identity key is the account email, falling back to username (single `identityKey` helper). - Both no-op under the `telemetry disable` opt-out and only fire after the user chooses to sign in. Privacy disclosure updated in lockstep, since this is the first PII the CLI attaches: the first-run telemetry notice and the telemetry section of docs/packages/cli.mdx now state that signing in links your account email to your usage. Tests: identifyUser payload + no-op, completion attribution incl. username fallback and no-identity-on-reject/empty. Verified end-to-end against the built CLI: pre-auth events anonymous, $identify carries $anon_distinct_id, completion carries the account email. * docs(cli): disclose the username identity fallback Review gating item: identityKey is `email ?? username`, but the first-run notice and cli.mdx said only "email", so an emailless account's username would reach PostHog undisclosed. `/v3/users/me` treats email as optional (pickString), so the fallback is live code, not dead — disclose it rather than assert an unverifiable email guarantee. Both surfaces now say "email, or username if the account has no email". Also soften the identityKey comment: it implied username is "less identifying", but HeyGen usernames are often email-shaped, so the note now states username is a fallback, not a privacy win.
This commit is contained in:
@@ -5,6 +5,12 @@ vi.mock("./client.js", () => ({
|
||||
trackEvent: (...args: unknown[]) => trackEvent(...args),
|
||||
}));
|
||||
|
||||
// identifyUser reads the install anonymousId; pin it so the $identify alias is
|
||||
// deterministic and the test never touches disk.
|
||||
vi.mock("./config.js", () => ({
|
||||
readConfig: () => ({ anonymousId: "anon-test-123", telemetryEnabled: true }),
|
||||
}));
|
||||
|
||||
const {
|
||||
trackRenderComplete,
|
||||
trackRenderError,
|
||||
@@ -17,6 +23,7 @@ const {
|
||||
trackAuthLoginStarted,
|
||||
trackAuthLoginCompleted,
|
||||
trackAuthLoginFailed,
|
||||
identifyUser,
|
||||
} = await import("./events.js");
|
||||
|
||||
describe("render telemetry events", () => {
|
||||
@@ -285,12 +292,26 @@ describe("auth login telemetry events", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("forwards an explicit distinctId to trackEvent for future user-level attribution", () => {
|
||||
trackAuthLoginCompleted("oauth", "heygen-user-123");
|
||||
it("forwards an explicit distinctId to trackEvent for user-level attribution", () => {
|
||||
trackAuthLoginCompleted("oauth", "alice@example.com");
|
||||
expect(trackEvent).toHaveBeenCalledWith(
|
||||
"auth_login_completed",
|
||||
{ method: "oauth" },
|
||||
"heygen-user-123",
|
||||
"alice@example.com",
|
||||
);
|
||||
});
|
||||
|
||||
it("identifyUser emits a $identify alias linking the anon install to the identity", () => {
|
||||
identifyUser("alice@example.com");
|
||||
expect(trackEvent).toHaveBeenCalledWith(
|
||||
"$identify",
|
||||
{ $anon_distinct_id: "anon-test-123" },
|
||||
"alice@example.com",
|
||||
);
|
||||
});
|
||||
|
||||
it("identifyUser is a no-op when there is no identity to attach", () => {
|
||||
identifyUser("");
|
||||
expect(trackEvent).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user