-
Notifications
You must be signed in to change notification settings - Fork 1
chore: fire pixel on app clicks #78
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: develop
Are you sure you want to change the base?
Conversation
📝 WalkthroughWalkthroughPreserves UrlObject href parts and reconstructs absolute URLs; distinguishes anchors/mailto/tel/external/non-root links; prefixes language for internal root links; adds app.shapeshift.com click path that calls global __adrsbl and opens in a new tab with router fallback; centralizes click handling; excludes Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant LocalizedLink
participant Router
participant Window
participant Analytics as "__adrsbl"
User->>LocalizedLink: click(href, event)
alt anchor / mailto / tel / external / non-root internal
LocalizedLink->>LocalizedLink: call user onClick (if any)
Note right of LocalizedLink: allow default/browser behavior (no client routing)
else host == app.shapeshift.com
LocalizedLink->>LocalizedLink: build fullUrl (from string or UrlObject)
LocalizedLink->>Analytics: invoke __adrsbl() (optional)
Analytics-->>LocalizedLink: return
LocalizedLink->>Window: window.open(fullUrl, "_blank")
alt open blocked / error
LocalizedLink->>Router: router.push(fullUrl) (fallback)
end
else internal root-relative
LocalizedLink->>LocalizedLink: normalize href (prepend lang, preserve query/hash)
LocalizedLink->>Router: router.push(localized href)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
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: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
app/[lang]/_components/LocalizedLink.tsx(1 hunks)tsconfig.json(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T02:04:59.408Z
Learnt from: thesmithdao
PR: shapeshift/website-frontend#66
File: app/[lang]/page.tsx:262-296
Timestamp: 2025-09-02T02:04:59.408Z
Learning: User thesmithdao prefers to avoid refactoring to LocalizedLink components for landing info cards in app/[lang]/page.tsx, preferring to keep the implementation clean with plain anchor tags.
Applied to files:
app/[lang]/_components/LocalizedLink.tsx
🧬 Code graph analysis (1)
app/[lang]/_components/LocalizedLink.tsx (1)
app/[lang]/_utils/i18nconfig.ts (2)
getLanguageFromPath(59-64)DEFAULT_LANGUAGE(52-52)
905db99 to
1e90018
Compare
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: 0
🧹 Nitpick comments (1)
app/[lang]/_components/LocalizedLink.tsx (1)
93-101: Previous critical issue resolved; consider minor optimization.The past issue with UrlObject navigation has been correctly fixed—both
window.openand the fallbackwindow.location.assignnow usefullUrlFromObj(hrefObj)to generate the complete absolute URL. Well done!Minor optimization: the absolute URL is computed twice (lines 93-95 and line 98). You could compute it once before the outer
tryblock to reduce duplication:} e.preventDefault() + const absolute = hrefObj + ? fullUrlFromObj(hrefObj) + : hrefString || (typeof href === 'string' ? href : '') try { - const absolute = hrefObj - ? fullUrlFromObj(hrefObj) - : hrefString || (typeof href === 'string' ? href : '') window.open(absolute, '_blank', 'noopener,noreferrer') } catch { - const absolute = hrefObj ? fullUrlFromObj(hrefObj) : hrefString if (absolute) { window.location.assign(absolute) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
app/[lang]/_components/LocalizedLink.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: thesmithdao
PR: shapeshift/website-frontend#66
File: app/[lang]/page.tsx:262-296
Timestamp: 2025-09-02T02:04:59.408Z
Learning: User thesmithdao prefers to avoid refactoring to LocalizedLink components for landing info cards in app/[lang]/page.tsx, preferring to keep the implementation clean with plain anchor tags.
📚 Learning: 2025-09-02T02:04:59.408Z
Learnt from: thesmithdao
PR: shapeshift/website-frontend#66
File: app/[lang]/page.tsx:262-296
Timestamp: 2025-09-02T02:04:59.408Z
Learning: User thesmithdao prefers to avoid refactoring to LocalizedLink components for landing info cards in app/[lang]/page.tsx, preferring to keep the implementation clean with plain anchor tags.
Applied to files:
app/[lang]/_components/LocalizedLink.tsx
🧬 Code graph analysis (1)
app/[lang]/_components/LocalizedLink.tsx (1)
app/[lang]/_utils/i18nconfig.ts (2)
getLanguageFromPath(59-64)DEFAULT_LANGUAGE(52-52)
🔇 Additional comments (3)
app/[lang]/_components/LocalizedLink.tsx (3)
48-57: Verify undefined/null query parameter handling.When a query parameter value is
undefinedornull, line 56 appends an empty string (e.g.,?key=). Confirm this is the intended behavior—typically, such values are omitted from query strings entirely. If omission is preferred, remove theelseclause:for (const [k, v] of Object.entries(obj.query as Record<string, unknown>)) { if (Array.isArray(v)) { for (const item of v) { params.append(k, String(item)) } } else if (v !== undefined && v !== null) { params.append(k, String(v)) - } else { - params.append(k, '') } }
109-130: LGTM: External link detection is comprehensive.The logic correctly identifies external links, anchors, mailto, tel, and non-root paths, bypassing localization for these cases. The conditional
onClickon line 126 properly applieshandleClickonly for app links while preserving the originalonClickfor other external links.
132-145: LGTM: Localization preserves URL structure correctly.The localization logic correctly:
- Detects existing language prefixes (line 133)
- Prepends the current language only when needed and not default (lines 138-140)
- Preserves UrlObject properties (query, hash) by returning a modified UrlObject (lines 142-144) instead of stringifying
This ensures Next.js Link receives the appropriate href format and all URL components are maintained.
0xApotheosis
left a 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.
Both internal and external links seem to be working as expected. Some minor tweaks requested.
1e90018 to
c3a80ae
Compare
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: 1
🧹 Nitpick comments (1)
app/[lang]/_components/LocalizedLink.tsx (1)
93-103: Simplify the fallback chain for consistency.Line 96 includes a redundant fallback
(typeof href === 'string' ? href : '')sincehrefStringis already set tohrefwhen it's a string (line 33). The catch block (line 99) doesn't include this fallback, creating an inconsistency.Consider simplifying line 96 to match line 99:
try { - const absolute = hrefObj - ? fullUrlFromObj(hrefObj) - : hrefString || (typeof href === 'string' ? href : '') + const absolute = hrefObj ? fullUrlFromObj(hrefObj) : hrefString window.open(absolute, '_blank', 'noopener,noreferrer') } catch { const absolute = hrefObj ? fullUrlFromObj(hrefObj) : hrefString
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
app/[lang]/_components/LocalizedLink.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: thesmithdao
PR: shapeshift/website-frontend#66
File: app/[lang]/page.tsx:262-296
Timestamp: 2025-09-02T02:04:59.408Z
Learning: User thesmithdao prefers to avoid refactoring to LocalizedLink components for landing info cards in app/[lang]/page.tsx, preferring to keep the implementation clean with plain anchor tags.
📚 Learning: 2025-09-02T02:04:59.408Z
Learnt from: thesmithdao
PR: shapeshift/website-frontend#66
File: app/[lang]/page.tsx:262-296
Timestamp: 2025-09-02T02:04:59.408Z
Learning: User thesmithdao prefers to avoid refactoring to LocalizedLink components for landing info cards in app/[lang]/page.tsx, preferring to keep the implementation clean with plain anchor tags.
Applied to files:
app/[lang]/_components/LocalizedLink.tsx
🧬 Code graph analysis (1)
app/[lang]/_components/LocalizedLink.tsx (1)
app/[lang]/_utils/i18nconfig.ts (2)
getLanguageFromPath(59-64)DEFAULT_LANGUAGE(52-52)
🔇 Additional comments (4)
app/[lang]/_components/LocalizedLink.tsx (4)
70-80: LGTM! App link detection is comprehensive.The detection logic correctly handles both string hrefs and
UrlObjectwith host information. The regex pattern appropriately matchesapp.shapeshift.comlinks with case-insensitive matching.
105-107: LGTM! onClick propagation is handled correctly.The user-provided
onClickhandler is properly forwarded after the analytics and navigation logic, ensuring compatibility with existing click handlers.
110-131: LGTM! External link handling is well-structured.The logic correctly identifies external links (including anchors, mailto, tel, and UrlObject with host/protocol) and bypasses localization for them. The conditional
onClickon line 127 ensures app links get the analytics + new-tab behavior while other external links retain their original click handlers.
133-146: LGTM! Localization logic correctly preserves UrlObject structure.The implementation properly:
- Detects existing language prefixes to avoid double-prefixing
- Only adds language prefix when not using the default language
- Preserves the original type (string or UrlObject) which maintains query and hash parameters
Based on coding guidelines (relevant_code_snippets show DEFAULT_LANGUAGE and getLanguageFromPath usage).
c3a80ae to
bfed48e
Compare
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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
app/[lang]/_components/LocalizedLink.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: thesmithdao
PR: shapeshift/website-frontend#66
File: app/[lang]/page.tsx:262-296
Timestamp: 2025-09-02T02:04:59.408Z
Learning: User thesmithdao prefers to avoid refactoring to LocalizedLink components for landing info cards in app/[lang]/page.tsx, preferring to keep the implementation clean with plain anchor tags.
📚 Learning: 2025-09-02T02:04:59.408Z
Learnt from: thesmithdao
PR: shapeshift/website-frontend#66
File: app/[lang]/page.tsx:262-296
Timestamp: 2025-09-02T02:04:59.408Z
Learning: User thesmithdao prefers to avoid refactoring to LocalizedLink components for landing info cards in app/[lang]/page.tsx, preferring to keep the implementation clean with plain anchor tags.
Applied to files:
app/[lang]/_components/LocalizedLink.tsx
🧬 Code graph analysis (1)
app/[lang]/_components/LocalizedLink.tsx (1)
app/[lang]/_utils/i18nconfig.ts (2)
getLanguageFromPath(59-64)DEFAULT_LANGUAGE(52-52)
🔇 Additional comments (8)
app/[lang]/_components/LocalizedLink.tsx (8)
13-14: LGTM!The ESLint disable and global declaration are appropriate for integrating with the Addressable pixel library.
16-19: LGTM!The type definition properly combines Next.js Link props with standard anchor attributes.
24-33: LGTM!The component properly supports both string and UrlObject hrefs, extracting the pathname for processing while preserving the original object structure.
75-85: LGTM!The app link detection correctly handles both string and UrlObject hrefs with appropriate pattern matching.
110-112: Verify onClick propagation behavior is intentional.When
isAppLinkis true, the handler callspreventDefault()and opens the link in a new tab, but still invokes the originalonClickafterward. Confirm this is the intended behavior, as users might expect theironClickto control navigation. If theonClickis meant only for side effects (e.g., analytics), this is fine; otherwise, consider callingonClickbeforepreventDefault()to allow it to cancel the action.
115-136: LGTM!The external link detection correctly handles both string patterns (http, #, mailto, tel, non-root paths) and UrlObject indicators (host, hostname, protocol), ensuring only internal root paths are localized.
138-151: LGTM!The language prefix logic correctly handles both string and UrlObject hrefs, preserving query and hash parameters when returning a UrlObject for localized internal links.
153-165: LGTM!The final return properly renders the localized link with all props forwarded, and the displayName is set for debugging.
bfed48e to
2faf556
Compare
2faf556 to
20a5b98
Compare
…n app.shapeshift.com clicks
20a5b98 to
fadd75f
Compare
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: 0
♻️ Duplicate comments (1)
app/[lang]/_components/LocalizedLink.tsx (1)
96-100: Add guard to prevent opening blank tab for empty hrefs.If
hrefObj,hrefString, andhrefare all empty or falsy, the computedabsolutewill be an empty string, andwindow.open('', '_blank', 'noopener,noreferrer')will openabout:blank. Consider adding an early return or validation.Apply this diff:
const absolute = hrefObj ? fullUrlFromObj(hrefObj) : hrefString || (typeof href === 'string' ? href : '') + if (!absolute) return try { window.open(absolute, '_blank', 'noopener,noreferrer')
🧹 Nitpick comments (2)
app/[lang]/_components/LocalizedLink.tsx (2)
49-49: Remove redundant type assertion.The type assertion
as stringis unnecessary here since thetypeof obj.query === 'string'check on line 47 already narrows the type tostring.Apply this diff:
- const raw = obj.query as string + const raw = obj.query
136-136: Consider usinggetLanguageFromPathfor more accurate language detection.The current regex
/^\/([a-z]{2})(\/|$)/matches any two-letter prefix, which means paths like/ab/test(whereabisn't a supported language) will be treated as already localized and won't get the language prepended. Using the existinggetLanguageFromPathutility would validate againstSUPPORTED_LANGUAGESand be more robust.Apply this diff:
- const hasLanguagePrefix = hrefString.match(/^\/([a-z]{2})(\/|$)/) + const hasLanguagePrefix = !!getLanguageFromPath(hrefString)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
app/[lang]/_components/LocalizedLink.tsx(1 hunks)tsconfig.json(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- tsconfig.json
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: thesmithdao
PR: shapeshift/website-frontend#66
File: app/[lang]/page.tsx:262-296
Timestamp: 2025-09-02T02:04:59.408Z
Learning: User thesmithdao prefers to avoid refactoring to LocalizedLink components for landing info cards in app/[lang]/page.tsx, preferring to keep the implementation clean with plain anchor tags.
📚 Learning: 2025-09-02T02:04:59.408Z
Learnt from: thesmithdao
PR: shapeshift/website-frontend#66
File: app/[lang]/page.tsx:262-296
Timestamp: 2025-09-02T02:04:59.408Z
Learning: User thesmithdao prefers to avoid refactoring to LocalizedLink components for landing info cards in app/[lang]/page.tsx, preferring to keep the implementation clean with plain anchor tags.
Applied to files:
app/[lang]/_components/LocalizedLink.tsx
🧬 Code graph analysis (1)
app/[lang]/_components/LocalizedLink.tsx (1)
app/[lang]/_utils/i18nconfig.ts (2)
getLanguageFromPath(59-64)DEFAULT_LANGUAGE(52-52)
🔇 Additional comments (3)
app/[lang]/_components/LocalizedLink.tsx (3)
19-20: Verify if content is missing near these lines.Past review comments indicate that line 19 had a "useful comment" that was removed and then "restored," but no comment is visible on line 19 in the current code. Additionally, line 20 has an unresolved question asking if it "is still removed." Please verify whether any content is missing here due to line number shifts or incomplete restoration.
85-110: Good implementation of analytics integration and new-tab behavior.The
handleClickfunction properly triggers the Addressable pixel, opens app links in a new tab with fallback handling, and correctly forwards customonClickhandlers. The defensive try-catch around the third-party__adrsblcall is appropriate.
145-148: Well done preserving UrlObject structure.Returning a UrlObject with the updated
pathnamewhen the originalhrefwas a UrlObject ensures that query parameters and hash fragments are preserved correctly. This maintains type consistency and proper URL semantics.
fadd75f to
4d1dc0e
Compare
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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
app/[lang]/_components/LocalizedLink.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T02:04:59.408Z
Learnt from: thesmithdao
PR: shapeshift/website-frontend#66
File: app/[lang]/page.tsx:262-296
Timestamp: 2025-09-02T02:04:59.408Z
Learning: User thesmithdao prefers to avoid refactoring to LocalizedLink components for landing info cards in app/[lang]/page.tsx, preferring to keep the implementation clean with plain anchor tags.
Applied to files:
app/[lang]/_components/LocalizedLink.tsx
🧬 Code graph analysis (1)
app/[lang]/_components/LocalizedLink.tsx (1)
app/[lang]/_utils/i18nconfig.ts (2)
getLanguageFromPath(59-64)DEFAULT_LANGUAGE(52-52)
🔇 Additional comments (4)
app/[lang]/_components/LocalizedLink.tsx (4)
40-76: Well-structured URL reconstruction helper.The
fullUrlFromObjfunction correctly handles both string and object-form queries (as addressed in previous review), properly serializes query parameters, and gracefully handles missing values. The logic is comprehensive and defensive.
78-88: App link detection works correctly for both string and UrlObject hrefs.The
isAppLinklogic correctly identifiesapp.shapeshift.comlinks regardless of whetherhrefis a string or UrlObject, ensuring the pixel fires consistently.
141-154: Localization logic preserves UrlObject structure correctly.The code correctly checks for existing language prefixes, only adds the language when appropriate, and importantly preserves the original
UrlObjectstructure (query, hash) when the input was a UrlObject. This ensures no data loss during localization.
118-129: Relative path skipping in LocalizedLink is intentional behavior—no action needed.Line 126's check (
!hrefString.startsWith('/')) correctly treats relative paths as non-localized. This is by design: the component is built for absolute paths and external URLs. Your codebase usage across 100+ instances confirms this—all hrefs are absolute paths like/blog,/chains/bitcoin, or external URLs. The defensive check prevents accidental misuse. The JSDoc explicitly states the component "automatically prepends the current language to internal links"—implying only absolute paths are intended inputs.
4d1dc0e to
9f0f42e
Compare
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
🧹 Nitpick comments (1)
app/[lang]/_components/LocalizedLink.tsx (1)
148-156: Progressive enhancement: add target/rel on app links.Set
target="_blank"andrel="noopener noreferrer"so links still open in a new tab without JS; security attributes are explicit.Apply:
return ( <Link href={href} ref={ref} {...props} + target={isAppLink ? '_blank' : props.target} + rel={isAppLink ? 'noopener noreferrer' : props.rel} onClick={isAppLink ? handleClick : onClick}> {children} </Link> )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
app/[lang]/_components/LocalizedLink.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T02:04:59.408Z
Learnt from: thesmithdao
PR: shapeshift/website-frontend#66
File: app/[lang]/page.tsx:262-296
Timestamp: 2025-09-02T02:04:59.408Z
Learning: User thesmithdao prefers to avoid refactoring to LocalizedLink components for landing info cards in app/[lang]/page.tsx, preferring to keep the implementation clean with plain anchor tags.
Applied to files:
app/[lang]/_components/LocalizedLink.tsx
🧬 Code graph analysis (1)
app/[lang]/_components/LocalizedLink.tsx (1)
app/[lang]/_utils/i18nconfig.ts (2)
getLanguageFromPath(59-64)DEFAULT_LANGUAGE(52-52)
9f0f42e to
fbd41eb
Compare
0xApotheosis
left a 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.
This breaks some external links: https://jam.dev/c/f74d605d-5df2-4853-a3fa-451dcf782acb
E.g. clicking "Get Started" or "Launch App" now opens a new tab and redirects the current tab to the new URL.
Summary
onClick, open app links in a new tabAcceptance
Output:
Summary by CodeRabbit
Enhancements
Chores