Skip to content

Use stable PostHog identity for newsletter signups#6588

Closed
Alek99 wants to merge 3 commits into
mainfrom
fix-posthog-newsletter-distinct-id
Closed

Use stable PostHog identity for newsletter signups#6588
Alek99 wants to merge 3 commits into
mainfrom
fix-posthog-newsletter-distinct-id

Conversation

@Alek99

@Alek99 Alek99 commented May 30, 2026

Copy link
Copy Markdown
Member

Summary

  • stop using email as the PostHog distinct ID for demo/intro form tracking
  • capture newsletter signups in PostHog with email in $set person properties
  • only call posthog.identify when a canonical non-email ID is provided
  • add track_newsletter_posthog_subscription(email, contact_uuid) as the new preferred API for newsletter tracking
  • preserve track_newsletter_posthog_submission(form_data) for backwards compatibility (now uses the improved _capture_posthog_person_event under the hood)

cc @Alek99

Testing

  • uv run ruff format packages/reflex-components-internal/src/reflex_components_internal/blocks/telemetry/posthog.py packages/reflex-components-internal/src/reflex_components_internal/blocks/telemetry/__init__.py packages/reflex-site-shared/src/reflex_site_shared/backend/signup.py
  • uv run ruff check packages/reflex-components-internal/src/reflex_components_internal/blocks/telemetry/posthog.py packages/reflex-components-internal/src/reflex_components_internal/blocks/telemetry/__init__.py packages/reflex-site-shared/src/reflex_site_shared/backend/signup.py
  • uv run --package reflex-site-shared python - <<'PY' ... script assertions for newsletter PostHog payload

@Alek99 Alek99 requested a review from a team as a code owner May 30, 2026 00:10
@codspeed-hq

codspeed-hq Bot commented May 30, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 26 untouched benchmarks
⏩ 8 skipped benchmarks1


Comparing fix-posthog-newsletter-distinct-id (e1eb12f) with main (1224c43)

Open in CodSpeed

Footnotes

  1. 8 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@greptile-apps

greptile-apps Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR refactors PostHog newsletter tracking to stop using email as the distinct_id, instead routing PII through $set person properties on the captured event. A new track_newsletter_posthog_subscription(email, contact_uuid) function is added as the preferred API, and signup.py is migrated to it.

  • Introduces _capture_posthog_person_event, a shared helper that filters person properties into $set, strips them from direct event properties, and calls posthog.identify only when a canonical non-email ID (user_uuid, contact_uuid, etc.) is present.
  • track_newsletter_posthog_subscription emits a newsletter_subscribed event (previously newsletter_signup), changing the PostHog event name for all future newsletter signups from signup.py.
  • The old track_newsletter_posthog_submission is preserved for backward compatibility at the code level, but since signup.py was its only caller, no existing code path still emits newsletter_signup.

Confidence Score: 4/5

Safe to merge after verifying that no active PostHog dashboards, funnels, or cohorts rely on the newsletter_signup event name.

The tracking logic itself is correct — email is properly kept out of distinct_id and the identify call only fires when a canonical UUID is available. The one concern is the event name change from newsletter_signup to newsletter_subscribed: since signup.py was the only caller of the old function, all future newsletter signups land under the new name. Existing PostHog insights filtering on newsletter_signup will silently stop receiving data.

packages/reflex-site-shared/src/reflex_site_shared/backend/signup.py — the event name change here has analytics consequences worth confirming before merge.

Important Files Changed

Filename Overview
packages/reflex-components-internal/src/reflex_components_internal/blocks/telemetry/posthog.py Refactors PostHog tracking to keep PII out of distinct_id; adds _capture_posthog_person_event helper and track_newsletter_posthog_subscription. Logic is sound — identify is only called when a canonical non-email ID is present, email goes into $set person properties.
packages/reflex-components-internal/src/reflex_components_internal/blocks/telemetry/init.py Exports the new track_newsletter_posthog_subscription function alongside existing exports; straightforward change.
packages/reflex-site-shared/src/reflex_site_shared/backend/signup.py Migrates newsletter signup tracking to the new API; the event name changes from newsletter_signup to newsletter_subscribed, which silently breaks existing PostHog analytics.

Reviews (3): Last reviewed commit: "Merge origin/main into fix-posthog-newsl..." | Re-trigger Greptile

Comment on lines +108 to 110
yield track_newsletter_posthog_subscription(email)
yield IndexState.send_contact_to_webhook(email)
yield IndexState.add_contact_to_loops(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.

P2 PostHog fires a newsletter_subscribed event even when email is None. If the user submits the form without an email address, email_to_validate is falsy and the if block is skipped entirely — so email stays None and tracking fires with an empty props object. The resulting event has no identity and no person properties, creating noise in PostHog analytics.

Suggested change
yield track_newsletter_posthog_subscription(email)
yield IndexState.send_contact_to_webhook(email)
yield IndexState.add_contact_to_loops(email)
if email:
yield track_newsletter_posthog_subscription(email)
yield IndexState.send_contact_to_webhook(email)
yield IndexState.add_contact_to_loops(email)

Comment on lines +79 to +84
if (Object.keys(personProps).length > 0) {{
eventProps.$set = personProps;
}}
if (canonicalDistinctId && canonicalDistinctId !== props.email) {{
posthog.identify(String(canonicalDistinctId), personProps);
}}

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.

P2 Double person-property write when canonical ID is present

When canonicalDistinctId is truthy, posthog.identify(canonicalDistinctId, personProps) is called and then posthog.capture(event_name, {..., $set: personProps}) is called immediately after with the same personProps in $set. PostHog merges both writes, so this is harmless in practice, but the $set payload on the capture event is redundant when identify already carries the same data. Removing the $set attachment when canonicalDistinctId is present would eliminate the duplicate write, though this is a minor analytics hygiene concern.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@masenf

masenf commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

@copilot resolve the merge conflicts in this pull request

Copilot AI commented Jun 11, 2026

Copy link
Copy Markdown

@copilot resolve the merge conflicts in this pull request

Resolved the merge conflicts in 84e6a63. The two conflicting areas were:

  1. posthog.py: main had added track_newsletter_posthog_submission(form_data) while this PR renamed/redesigned it as track_newsletter_posthog_subscription(email, contact_uuid). Resolved by keeping both — track_newsletter_posthog_subscription as the new preferred API and track_newsletter_posthog_submission for backwards compatibility (it now benefits from the improved _capture_posthog_person_event implementation).

  2. signup.py: kept this PR's version using track_newsletter_posthog_subscription(email) directly, removing the duplicate track_newsletter_posthog_submission call that the auto-merge had inserted.

Copilot AI requested a review from masenf June 11, 2026 21:10
@masenf

masenf commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

@copilot resolve the merge conflicts in this pull request

Copilot AI commented Jun 23, 2026

Copy link
Copy Markdown

@copilot resolve the merge conflicts in this pull request

Resolved in e1eb12f. The only conflict was in __init__.py — main had added from .leadpipe import get_leadpipe_trackers while this PR had added track_newsletter_posthog_subscription to the posthog import. Merged both into a single coherent import block.

},
)
return
yield track_newsletter_posthog_subscription(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.

P1 partner Event name change breaks existing PostHog analytics

track_newsletter_posthog_submission emitted newsletter_signup; track_newsletter_posthog_subscription emits newsletter_subscribed. Since signup.py was the only caller of the old function (no other callers found in the repo), all future newsletter signups will land under the new event name. Any existing PostHog dashboards, funnels, or cohorts that filter on newsletter_signup will silently stop receiving new data. Verify whether any PostHog insights need to be updated or duplicated to cover both event names before merging.

@masenf masenf closed this Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants