Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fancy-baboons-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"lingo.dev": patch
---

fix posthog
31 changes: 29 additions & 2 deletions packages/cli/src/cli/utils/observability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ function determineDistinctId(email: string | null | undefined): {
const orgId = getOrgId();

if (email) {
const hashedEmail = crypto.createHash("sha256").update(email).digest("hex");
return {
distinct_id: hashedEmail,
distinct_id: email,
distinct_id_source: "email",
org_id: orgId,
};
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Expand Down Expand Up @@ -72,6 +71,7 @@ export default function trackEvent(
distinct_id: identityInfo.distinct_id,
properties: {
...properties,
$set: { ...(properties?.$set || {}), ...(email ? { email } : {}) },
$lib: "lingo.dev-cli",
$lib_version: process.env.npm_package_version || "unknown",
tracking_version: TRACKING_VERSION,
Expand Down Expand Up @@ -112,6 +112,33 @@ export default function trackEvent(
req.write(payload);
req.end();

// TODO: remove after 2026-03-25 — temporary alias to merge old hashed distinct_ids with new raw email
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Two-week migration window may be insufficient.

The TODO indicates removal after 2026-03-25, which is only ~13 days from now. Users who don't upgrade and run the CLI within this window will never trigger the alias, leaving their old hashed profiles orphaned.

Consider extending the window (e.g., 3-6 months) to maximize the number of users who upgrade and get their profiles merged, or plan to keep the alias logic until analytics confirms minimal unmerged profiles.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/cli/utils/observability.ts` at line 115, The temporary alias
removal date in the TODO for the "hashed distinct_ids with new raw email"
migration is too short; extend the migration window to 3–6 months (or until
analytics show negligible unmerged profiles) by updating the TODO date and any
associated expiry constant or config used by the alias logic (the alias/merge
code that handles old hashed distinct_ids -> new raw email); ensure the comment
and the config/constant that triggers removal reflect the new deadline and, if
present, add telemetry/metrics gating so the alias logic can be disabled only
after confirming low orphan rate.

if (email) {
const hashedEmail = crypto.createHash("sha256").update(email).digest("hex");
const aliasData = JSON.stringify({
api_key: POSTHOG_API_KEY,
event: "$create_alias",
distinct_id: email,
properties: {
alias: hashedEmail,
},
timestamp: new Date().toISOString(),
});

const aliasReq = https.request({
...options,
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(aliasData).toString(),
},
});
aliasReq.on("timeout", () => aliasReq.destroy());
aliasReq.on("error", () => {});
aliasReq.write(aliasData);
aliasReq.end();
setTimeout(() => { if (!aliasReq.destroyed) aliasReq.destroy(); }, REQUEST_TIMEOUT_MS);
}
Comment on lines +115 to +140
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

SDK lacks alias logic — legacy SDK profiles won't merge.

The SDK at packages/sdk/src/utils/observability.ts now uses raw email as distinct_id (matching this change), but it does not send the $create_alias event. SDK users who previously had events tracked under hashed email will have orphaned profiles that never get merged with their new raw-email identity.

Consider adding the same alias logic to the SDK module, or confirm that SDK analytics continuity is intentionally being sacrificed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/cli/utils/observability.ts` around lines 115 - 140, Add the
same alias emission implemented in the CLI to the SDK observability flow: when
email is present, compute hashedEmail =
crypto.createHash("sha256").update(email).digest("hex"), build aliasData JSON
containing api_key: POSTHOG_API_KEY, event: "$create_alias", distinct_id: email
and properties.alias: hashedEmail, then send it via https.request using the same
options/headers (Content-Type and Content-Length), attach the same
aliasReq.on("timeout", ...) and aliasReq.on("error", ...) handlers, write and
end the request, and enforce destruction after REQUEST_TIMEOUT_MS; ensure you
reference the same variables/names (email, hashedEmail, aliasData, aliasReq,
REQUEST_TIMEOUT_MS, POSTHOG_API_KEY, options) and place this logic alongside the
SDK's existing analytics send path so legacy hashed profiles merge with
raw-email identities.


setTimeout(() => {
if (!req.destroyed) {
req.destroy();
Expand Down
Loading