-
Notifications
You must be signed in to change notification settings - Fork 20
Replace Segment with direct Mixpanel integration #1653
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: canary
Are you sure you want to change the base?
Replace Segment with direct Mixpanel integration #1653
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe pull request migrates analytics from Segment and FullStory to Mixpanel. Changes include removing the Segment dependency, updating Content-Security-Policy directives to allow Mixpanel domains, refactoring the analytics provider to integrate Mixpanel instead of Segment, and updating the privacy policy to reference Mixpanel exclusively. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 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: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/app/privacy/page.tsx (1)
8-85: Duplicate privacy notice content.The
PRIVACY_MDstring contains the entire privacy notice twice. Lines 8-85 contain the full notice, and lines 87-208 repeat nearly identical content. This will render the privacy page with duplicate sections.Remove one of the duplicated blocks to display the notice only once.
Also applies to: 87-208
🤖 Fix all issues with AI Agents
In @next.config.mjs:
- Line 16: The Content Security Policy in next.config.mjs still includes the
FullStory domain in the img-src directive; remove "https://rs.fullstory.com"
from the img-src entry in the contentSecurityPolicy (the img-src directive
string) so the CSP no longer references FullStory when that integration is
removed.
In @src/common/providers/AnalyticsProvider.tsx:
- Around line 89-91: The initial analytics.page() call can be dropped or guarded
because the Mixpanel script loads afterInteractive and analyticsReady() may
return false; either remove the useEffect (if you keep automatic page view
tracking via track_pageview:true) or replace the immediate call with a readiness
check/poll/callback that waits for analyticsReady() (or the mixpanel client to
be ready) before invoking analytics.page(); locate the useEffect with
analytics.page() in AnalyticsProvider and implement the chosen fix so the
initial page view is never silently dropped.
- Around line 24-26: The Mixpanel snippet constant MIXPANEL_SNIPPET currently
sets track_pageview:true which duplicates manual analytics.page() calls (see
analytics.page() usages). Fix by either changing track_pageview to false inside
MIXPANEL_SNIPPET so only manual analytics.page() calls fire, or remove/disable
the manual analytics.page() calls (the analytics.page() invocations) and keep
track_pageview:true; update the MIXPANEL_SNIPPET string accordingly if you
choose the first option.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
next.config.mjspackage.jsonsrc/app/privacy/page.tsxsrc/common/providers/AnalyticsProvider.tsx
💤 Files with no reviewable changes (1)
- package.json
🔇 Additional comments (7)
next.config.mjs (2)
13-13: LGTM on Mixpanel script-src addition.The CSP script-src directive correctly allows the Mixpanel CDN domain.
42-46: LGTM on Mixpanel connect-src additions.The required Mixpanel endpoints are correctly added for analytics, session replay, and decision APIs.
src/common/providers/AnalyticsProvider.tsx (4)
9-20: LGTM on the Mixpanel type declaration.The global type augmentation correctly defines the Mixpanel interface methods used in this file.
28-29: LGTM on the analytics ready guard.The guard correctly checks for both
windowexistence and that the Mixpaneltrackmethod is a function.
31-63: LGTM on the analytics methods.The
track,identify, andpagemethods are properly guarded against Mixpanel not being ready and include try-catch error handling.
99-101: Navigation page views depend on Mixpanel being loaded.After the initial load, subsequent navigation page views should work correctly since Mixpanel will likely be loaded by then. This is fine if the duplicate tracking issue is resolved.
src/app/privacy/page.tsx (1)
26-27: LGTM on Mixpanel analytics references.The usage analytics and device/browser info sections correctly reference Mixpanel as the sole analytics provider.
Also applies to: 106-107
| script-src 'self' 'unsafe-eval' 'unsafe-inline' https://challenges.cloudflare.com https://www.youtube.com https://www.youtube.com/iframe_api https://auth.privy.nounspace.com https://cdn.mxpnl.com; | ||
| style-src 'self' 'unsafe-inline' https://i.ytimg.com https://mint.highlight.xyz; | ||
| media-src 'self' blob: data: https://stream.warpcast.com https://stream.farcaster.xyz https://res.cloudinary.com/ https://*.cloudflarestream.com https://*.b-cdn.net; | ||
| img-src 'self' blob: data: https: https://ipfs.io https://rs.fullstory.com; |
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.
Leftover FullStory domain in img-src.
https://rs.fullstory.com remains in the img-src directive but FullStory is being removed in this PR. Consider removing it for consistency.
Proposed fix
- img-src 'self' blob: data: https: https://ipfs.io https://rs.fullstory.com;
+ img-src 'self' blob: data: https: https://ipfs.io;📝 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.
| img-src 'self' blob: data: https: https://ipfs.io https://rs.fullstory.com; | |
| img-src 'self' blob: data: https: https://ipfs.io; |
🤖 Prompt for AI Agents
In @next.config.mjs at line 16, The Content Security Policy in next.config.mjs
still includes the FullStory domain in the img-src directive; remove
"https://rs.fullstory.com" from the img-src entry in the contentSecurityPolicy
(the img-src directive string) so the CSP no longer references FullStory when
that integration is removed.
| * **Delete dashboard or Space:** Use in-app controls; dashboard data is wiped server-side, Space config removed from our DB (posts on Farcaster remain public). | ||
| * **California & GDPR rights:** You can request deletion, correction, or a copy of your personal data. We honour valid requests within 30 days. | ||
| * **Do-Not-Track signals:** We respect DNT headers by disabling Segment, Mixpanel, and Fullstory when DNT = 1. | ||
| * **Do-Not-Track signals:** We respect DNT headers by disabling Mixpanel when DNT = 1. |
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:
#!/bin/bash
# Search for DNT (Do Not Track) handling in the codebase
rg -n -i "do.?not.?track|navigator\.doNotTrack|DNT" --type=ts --type=tsxRepository: blankdotspace/space-system
Length of output: 97
🏁 Script executed:
#!/bin/bash
# Find and examine AnalyticsProvider.tsx
fd -n "AnalyticsProvider.tsx" -x cat {}Repository: blankdotspace/space-system
Length of output: 300
🏁 Script executed:
#!/bin/bash
# Check the privacy page to see the exact statements at lines 61 and 165
fd -n "page.tsx" src/app/privacy -x cat -n {}Repository: blankdotspace/space-system
Length of output: 300
🏁 Script executed:
#!/bin/bash
# Search for DNT handling - use broader approach without specific type filters
rg -i "do.?not.?track|navigator\.doNotTrack|DNT" -A 3 -B 1Repository: blankdotspace/space-system
Length of output: 2108
🏁 Script executed:
#!/bin/bash
# Find AnalyticsProvider.tsx file
fd "AnalyticsProvider"Repository: blankdotspace/space-system
Length of output: 112
🏁 Script executed:
#!/bin/bash
# Find and read the privacy page
fd "page.tsx" src/app/privacyRepository: blankdotspace/space-system
Length of output: 94
🏁 Script executed:
#!/bin/bash
# Read the AnalyticsProvider.tsx file
cat -n src/common/providers/AnalyticsProvider.tsxRepository: blankdotspace/space-system
Length of output: 5956
🏁 Script executed:
#!/bin/bash
# Read the privacy page to confirm exact lines
cat -n src/app/privacy/page.tsx | head -100Repository: blankdotspace/space-system
Length of output: 6842
🏁 Script executed:
#!/bin/bash
# Get more lines from privacy page to find line 165
cat -n src/app/privacy/page.tsx | sed -n '150,180p'Repository: blankdotspace/space-system
Length of output: 1514
🏁 Script executed:
#!/bin/bash
# Search the entire codebase for navigator.doNotTrack or similar DNT checks
rg "navigator\.doNotTrack|doNotTrack" -iRepository: blankdotspace/space-system
Length of output: 52
🏁 Script executed:
#!/bin/bash
# Search for any conditional Mixpanel initialization based on user preference
rg "mixpanel" -i -B 2 -A 2 | head -60Repository: blankdotspace/space-system
Length of output: 6574
Remove false DNT claim from privacy notice or implement DNT handling.
The privacy notice (lines 61 and 165) claims "We respect DNT headers by disabling Mixpanel when DNT = 1", but AnalyticsProvider.tsx contains no DNT handling whatsoever. Mixpanel is initialized unconditionally without checking navigator.doNotTrack. Either implement DNT support by detecting the Do-Not-Track signal and conditionally disabling Mixpanel initialization, or remove this claim from the privacy notice.
| const MIXPANEL_SNIPPET = MIXPANEL_TOKEN | ||
| ? `(function (f, b) { if (!b.__SV) { var e, g, i, h; window.mixpanel = b; b._i = []; b.init = function (e, f, c) { function g(a, d) { var b = d.split("."); 2 == b.length && ((a = a[b[0]]), (d = b[1])); a[d] = function () { a.push([d].concat(Array.prototype.slice.call(arguments, 0))); }; } var a = b; "undefined" !== typeof c ? (a = b[c] = []) : (c = "mixpanel"); a.people = a.people || []; a.toString = function (a) { var d = "mixpanel"; "mixpanel" !== c && (d += "." + c); a || (d += " (stub)"); return d; }; a.people.toString = function () { return a.toString(1) + ".people (stub)"; }; i = "disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking start_batch_senders people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove start_session_recording stop_session_recording".split(" "); for (h = 0; h < i.length; h++) g(a, i[h]); var j = "set set_once union unset remove delete".split(" "); a.get_group = function () { function b(c) { d[c] = function () { call2_args = arguments; call2 = [c].concat(Array.prototype.slice.call(call2_args, 0)); a.push([e, call2]); }; } for ( var d = {}, e = ["get_group"].concat( Array.prototype.slice.call(arguments, 0)), c = 0; c < j.length; c++) b(j[c]); return d; }; b._i.push([e, f, c]); }; b.__SV = 1.2; e = f.createElement("script"); e.type = "text/javascript"; e.async = !0; e.src = "undefined" !== typeof MIXPANEL_CUSTOM_LIB_URL ? MIXPANEL_CUSTOM_LIB_URL : "file:" === f.location.protocol && "//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\\/\\//) ? "https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js" : "//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js"; g = f.getElementsByTagName("script")[0]; g.parentNode.insertBefore(e, g); } })(document, window.mixpanel || []); mixpanel.init("${MIXPANEL_TOKEN}", {debug:${process.env.NODE_ENV !== "production"} ,track_pageview:true,persistence:"localStorage",autocapture:true,record_replay:true,record_replay_sample_rate:1,api_host:"https://api-js.mixpanel.com"}); if(mixpanel.start_session_recording){mixpanel.start_session_recording();}` | ||
| : ""; |
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.
Duplicate page view tracking.
The Mixpanel config sets track_pageview:true, which enables automatic page view tracking. However, manual analytics.page() calls on lines 90 and 100 will result in duplicate "Page View" events.
Consider either:
- Setting
track_pageview:falseand relying on manual tracking, or - Removing the manual
analytics.page()calls and relying on Mixpanel's automatic tracking.
🤖 Prompt for AI Agents
In @src/common/providers/AnalyticsProvider.tsx around lines 24 - 26, The
Mixpanel snippet constant MIXPANEL_SNIPPET currently sets track_pageview:true
which duplicates manual analytics.page() calls (see analytics.page() usages).
Fix by either changing track_pageview to false inside MIXPANEL_SNIPPET so only
manual analytics.page() calls fire, or remove/disable the manual
analytics.page() calls (the analytics.page() invocations) and keep
track_pageview:true; update the MIXPANEL_SNIPPET string accordingly if you
choose the first option.
| useEffect(() => { | ||
| if (writeKey) { | ||
| segment.load({ writeKey }).catch((e) => { | ||
| console.error(e); | ||
| }); | ||
| } | ||
| }, [writeKey]); | ||
| analytics.page(); | ||
| }, []); |
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.
Initial page view may be silently dropped.
This effect runs immediately on mount, but the Mixpanel script uses strategy="afterInteractive" and may not be loaded yet. The analyticsReady() guard will silently return, dropping the initial page view.
If automatic page view tracking via track_pageview:true is kept, this can be removed entirely. Otherwise, consider polling or using a callback to ensure Mixpanel is ready before tracking.
🤖 Prompt for AI Agents
In @src/common/providers/AnalyticsProvider.tsx around lines 89 - 91, The initial
analytics.page() call can be dropped or guarded because the Mixpanel script
loads afterInteractive and analyticsReady() may return false; either remove the
useEffect (if you keep automatic page view tracking via track_pageview:true) or
replace the immediate call with a readiness check/poll/callback that waits for
analyticsReady() (or the mixpanel client to be ready) before invoking
analytics.page(); locate the useEffect with analytics.page() in
AnalyticsProvider and implement the chosen fix so the initial page view is never
silently dropped.
Summary
Testing
Codex Task
Summary by CodeRabbit
Documentation
Chores
✏️ Tip: You can customize this high-level summary in your review settings.