-
Notifications
You must be signed in to change notification settings - Fork 27
Add language selection tracking to PostHog analytics #4127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Add language property to PostHog user identification in auth_context - Track language_changed event when user updates language in footer - Track language_changed event when user updates language in settings - Update language user property in PostHog on language change Fixes #4125 Co-authored-by: Sylvain <SylvainChevalier@users.noreply.github.com>
📝 WalkthroughWalkthroughThis PR integrates PostHog analytics to track language preference changes across the application. Three files are modified to capture language_changed events when users update their language, update user properties in PostHog, and include language in authentication context identification. Changes
Sequence DiagramsequenceDiagram
actor User
participant Component as Language Component
participant PostHog
participant Backend
User->>Component: Select language
Component->>PostHog: capture("language_changed",<br/>{previous_language, new_language})
PostHog->>PostHog: Log event
Component->>PostHog: setPersonProperties({language})
PostHog->>PostHog: Update user property
Component->>Backend: updateLanguagePreference()
Backend->>Backend: Save preference
Backend-->>Component: Success
Component->>Component: router.refresh()
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In
`@front_end/src/app/`(main)/accounts/settings/(general)/components/language_preferences.tsx:
- Around line 27-40: The PostHog events are emitted before
updateLanguagePreference completes, which can record a change that may fail;
modify the async handler (the anonymous function that checks
isPendingUpdateLanguage) to await updateLanguagePreference(language) and only
call posthog.capture("language_changed", ...) and posthog.setPersonProperties({
language }) after that promise resolves successfully; keep the existing guard
(isPendingUpdateLanguage) and call logError on rejection so analytics are not
sent on failure and person properties remain consistent with
user.language/currentLocale.
In `@front_end/src/app/`(main)/components/footer.tsx:
- Around line 169-183: The current updateLanguage handler calls posthog.capture
and posthog.setPersonProperties before confirming the preference persisted; move
both analytics calls into the success branch of updateLanguagePreference so they
run only after the promise resolves successfully. Specifically, modify
updateLanguage to call updateLanguagePreference(language, false).then(() => {
posthog.capture("language_changed", { previous_language: selectedLanguage,
new_language: language }); if (user) posthog.setPersonProperties({ language });
router.refresh(); }).catch(logError) so tracking and person property updates
happen after persistence succeeds.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
front_end/src/app/(main)/accounts/settings/(general)/components/language_preferences.tsxfront_end/src/app/(main)/components/footer.tsxfront_end/src/contexts/auth_context.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
front_end/src/contexts/auth_context.tsx (1)
front_end/scripts/add_missing_translations.mjs (1)
language(112-112)
front_end/src/app/(main)/accounts/settings/(general)/components/language_preferences.tsx (1)
front_end/src/hooks/use_server_action.ts (1)
useServerAction(3-40)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Build Docker Image
- GitHub Check: integration-tests
- GitHub Check: Frontend Checks
- GitHub Check: Backend Checks
🔇 Additional comments (1)
front_end/src/contexts/auth_context.tsx (1)
31-39: The code is correct as-is. TheCurrentUser.languagetype isstring | null(not allowing empty strings as sentinel values), andAPP_LANGUAGESdefines only actual locale codes: "en", "cs", "es", "pt", "zh", "zh-TW", and "original" (for untranslated content). Language values are never empty strings, so the||fallback tolocaleis appropriate and functions correctly. Using??instead would have no practical impact since empty strings are not used in the codebase.Likely an incorrect or invalid review comment.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| async (language: string) => { | ||
| if (!isPendingUpdateLanguage) { | ||
| const previousLanguage = user.language || currentLocale; | ||
|
|
||
| // Track language change in PostHog | ||
| posthog.capture("language_changed", { | ||
| previous_language: previousLanguage, | ||
| new_language: language, | ||
| }); | ||
|
|
||
| // Update user property for language | ||
| posthog.setPersonProperties({ language }); | ||
|
|
||
| updateLanguagePreference(language).catch(logError); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's check if the file exists and view the relevant lines
if [ -f "front_end/src/app/(main)/accounts/settings/(general)/components/language_preferences.tsx" ]; then
echo "=== File found. Checking lines 20-50 for context ==="
sed -n '20,50p' "front_end/src/app/(main)/accounts/settings/(general)/components/language_preferences.tsx"
else
echo "File not found at exact path. Searching for language_preferences file..."
find . -name "language_preferences.tsx" -type f 2>/dev/null | head -5
fiRepository: Metaculus/metaculus
Length of output: 1021
🏁 Script executed:
# Also search for the updateLanguagePreference function to understand its behavior
rg "updateLanguagePreference" --type tsx --type ts -A 10 -B 2Repository: Metaculus/metaculus
Length of output: 90
🏁 Script executed:
# Search for updateLanguagePreference without problematic file type flags
rg "updateLanguagePreference" -A 10 -B 2 | head -100Repository: Metaculus/metaculus
Length of output: 8295
🏁 Script executed:
# Also check imports in the language_preferences file
head -20 "front_end/src/app/(main)/accounts/settings/(general)/components/language_preferences.tsx"Repository: Metaculus/metaculus
Length of output: 785
🏁 Script executed:
# Get the full updateLanguagePreference function definition
sed -n '/export async function updateLanguagePreference/,/^}/p' "front_end/src/app/(main)/accounts/profile/actions.tsx" | head -30Repository: Metaculus/metaculus
Length of output: 504
Emit PostHog updates only after the preference save succeeds.
The event and person property update happen before updateLanguagePreference completes. If the server action fails, PostHog will record a language change that didn't persist, and the person property will drift from reality. Move analytics into the success callback.
✅ Suggested sequencing
- // Track language change in PostHog
- posthog.capture("language_changed", {
- previous_language: previousLanguage,
- new_language: language,
- });
-
- // Update user property for language
- posthog.setPersonProperties({ language });
-
- updateLanguagePreference(language).catch(logError);
+ updateLanguagePreference(language)
+ .then(() => {
+ // Track language change in PostHog
+ posthog.capture("language_changed", {
+ previous_language: previousLanguage,
+ new_language: language,
+ });
+
+ // Update user property for language
+ posthog.setPersonProperties({ language });
+ })
+ .catch(logError);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async (language: string) => { | |
| if (!isPendingUpdateLanguage) { | |
| const previousLanguage = user.language || currentLocale; | |
| // Track language change in PostHog | |
| posthog.capture("language_changed", { | |
| previous_language: previousLanguage, | |
| new_language: language, | |
| }); | |
| // Update user property for language | |
| posthog.setPersonProperties({ language }); | |
| updateLanguagePreference(language).catch(logError); | |
| async (language: string) => { | |
| if (!isPendingUpdateLanguage) { | |
| const previousLanguage = user.language || currentLocale; | |
| updateLanguagePreference(language) | |
| .then(() => { | |
| // Track language change in PostHog | |
| posthog.capture("language_changed", { | |
| previous_language: previousLanguage, | |
| new_language: language, | |
| }); | |
| // Update user property for language | |
| posthog.setPersonProperties({ language }); | |
| }) | |
| .catch(logError); |
🤖 Prompt for AI Agents
In
`@front_end/src/app/`(main)/accounts/settings/(general)/components/language_preferences.tsx
around lines 27 - 40, The PostHog events are emitted before
updateLanguagePreference completes, which can record a change that may fail;
modify the async handler (the anonymous function that checks
isPendingUpdateLanguage) to await updateLanguagePreference(language) and only
call posthog.capture("language_changed", ...) and posthog.setPersonProperties({
language }) after that promise resolves successfully; keep the existing guard
(isPendingUpdateLanguage) and call logError on rejection so analytics are not
sent on failure and person properties remain consistent with
user.language/currentLocale.
| const updateLanguage = (language: string) => { | ||
| // Track language change in PostHog | ||
| posthog.capture("language_changed", { | ||
| previous_language: selectedLanguage, | ||
| new_language: language, | ||
| }); | ||
|
|
||
| // Update user property for language | ||
| if (user) { | ||
| posthog.setPersonProperties({ language }); | ||
| } | ||
|
|
||
| updateLanguagePreference(language, false) | ||
| .then(() => router.refresh()) | ||
| .catch(logError); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, check if the footer.tsx file exists and read the relevant lines
fd "footer.tsx" --type fRepository: Metaculus/metaculus
Length of output: 182
🏁 Script executed:
# Search for the updateLanguage function in footer.tsx
rg -A 20 "const updateLanguage" front_end/src/app/\(main\)/components/footer.tsxRepository: Metaculus/metaculus
Length of output: 637
🏁 Script executed:
# Look for the updateLanguagePreference implementation
rg -B 5 -A 15 "updateLanguagePreference" front_end/src/app/\(main\)/components/footer.tsxRepository: Metaculus/metaculus
Length of output: 1634
🏁 Script executed:
# Search for similar PostHog analytics patterns in the settings component mentioned in scratchpad
find front_end -name "*settings*" -type f | head -20Repository: Metaculus/metaculus
Length of output: 391
🏁 Script executed:
# Find and read the updateLanguagePreference function
fd "profile" -type d front_end/src/app/\(main\)/accounts/ | head -5Repository: Metaculus/metaculus
Length of output: 233
🏁 Script executed:
# Search for the updateLanguagePreference implementation
rg -B 5 -A 20 "export.*updateLanguagePreference" front_end/src/app/\(main\)/accounts/Repository: Metaculus/metaculus
Length of output: 1785
🏁 Script executed:
# Check the settings_header component for similar PostHog patterns
rg -B 5 -A 15 "posthog.capture\|posthog.setPersonProperties" front_end/src/app/\(main\)/accounts/settings/components/settings_header.tsxRepository: Metaculus/metaculus
Length of output: 45
🏁 Script executed:
# Search for PostHog analytics patterns in settings components more broadly
rg "posthog.capture|posthog.setPersonProperties" front_end/src/app/\(main\)/accounts/settings/ -B 3 -A 3Repository: Metaculus/metaculus
Length of output: 1634
🏁 Script executed:
# Check if there are any error handling patterns in similar components
rg -B 10 -A 5 "updateLanguagePreference" front_end/src --type tsx | head -60Repository: Metaculus/metaculus
Length of output: 90
🏁 Script executed:
# Look at the full profile actions file to understand error scenarios
cat front_end/src/app/\(main\)/accounts/profile/actions.tsx | head -100Repository: Metaculus/metaculus
Length of output: 2375
🏁 Script executed:
# Read more of the profile actions to see error handling
cat front_end/src/app/\(main\)/accounts/profile/actions.tsxRepository: Metaculus/metaculus
Length of output: 3379
🏁 Script executed:
# Check the language_preferences settings component to see how it handles errors
cat front_end/src/app/\(main\)/accounts/settings/\(general\)/components/language_preferences.tsxRepository: Metaculus/metaculus
Length of output: 3466
Defer PostHog tracking until the language update succeeds.
The footer's language change handler sends language_changed and updates person properties before verifying the preference save succeeded. If updateLanguagePreference fails, analytics will be incorrect—claiming a change that never persisted. Move PostHog tracking into the success path after the preference is saved.
✅ Suggested sequencing
- // Track language change in PostHog
- posthog.capture("language_changed", {
- previous_language: selectedLanguage,
- new_language: language,
- });
-
- // Update user property for language
- if (user) {
- posthog.setPersonProperties({ language });
- }
-
- updateLanguagePreference(language, false)
- .then(() => router.refresh())
- .catch(logError);
+ updateLanguagePreference(language, false)
+ .then(() => {
+ // Track language change in PostHog
+ posthog.capture("language_changed", {
+ previous_language: selectedLanguage,
+ new_language: language,
+ });
+
+ // Update user property for language
+ if (user) {
+ posthog.setPersonProperties({ language });
+ }
+
+ router.refresh();
+ })
+ .catch(logError);🤖 Prompt for AI Agents
In `@front_end/src/app/`(main)/components/footer.tsx around lines 169 - 183, The
current updateLanguage handler calls posthog.capture and
posthog.setPersonProperties before confirming the preference persisted; move
both analytics calls into the success branch of updateLanguagePreference so they
run only after the promise resolves successfully. Specifically, modify
updateLanguage to call updateLanguagePreference(language, false).then(() => {
posthog.capture("language_changed", { previous_language: selectedLanguage,
new_language: language }); if (user) posthog.setPersonProperties({ language });
router.refresh(); }).catch(logError) so tracking and person property updates
happen after persistence succeeds.
🚀 Preview EnvironmentYour preview environment is ready!
Details
ℹ️ Preview Environment InfoIsolation:
Limitations:
Cleanup:
|
Adds language selection tracking to PostHog analytics.
Changes
Fixes #4125
Generated with Claude Code
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.