fix(language-selector): keep the query string and hash through redirects - #2154
Merged
Conversation
The canonical guard compared the full `window.location.href` against the canonical link and hard-navigated on any difference. A query string or a hash is enough to make those strings differ, so every visit carrying campaign parameters -- utm_*, gclid, fbclid, msclkid -- was bounced to the bare canonical URL before an analytics tag could read them, and anchor deep links were dropped the same way. Sites that enable the language selector were affected on every page, since this script replaces static/js/alias.js and runs site-wide rather than only on alias pages. Decide on the location alone: compare origin and pathname, so a page that is already canonical never redirects. When a redirect is warranted, carry `location.search + location.hash` to the target, matching what static/js/alias.js already does. Apply the same treatment to the language switch, which dropped parameters when moving between translations, and fix its bare-folder branch to compare pathnames rather than a full href against a path -- a comparison that could never match.
✅ Deploy Preview for gethinode-demo ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Collaborator
Author
|
🎉 This PR is included in version 3.23.11 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The canonical guard in
assets/js/critical/languageSelector.jscompares the fullwindow.location.hrefagainst the<link rel="canonical">href and hard-navigates on any difference:The canonical never carries a query string, so any URL that does looks like a mismatch. The visitor is bounced to the bare canonical URL and the parameters are gone —
utm_source,utm_medium,utm_campaign, plusgclid,fbclid,msclkid,hsCtaTracking. Anchor deep links (#section) are dropped the same way.This is not limited to alias pages. When
main.enableLanguageSelectionStorageis true this script replacesstatic/js/alias.jsand ships in the critical bundle on every page, so the redirect fires site-wide. The only URL that escapes is?force=true, via the early return above.static/js/alias.js— the redirect this script stands in for — already gets it right:Reported by a marketing team whose campaign links lost their UTM parameters before GA4 could record the attribution.
Fix
origin+pathname, so a page that is already canonical never redirects. This strictly reduces redirects, so it cannot introduce a new one.location.search + location.hashto the target, matchingalias.js.applyLanguage, which dropped parameters when switching translations.applyLanguage's bare-folder branch, which compared a full href against a path (window.location.href !== '/nl/') — a comparison that can never be equal, so the guard never suppressed anything.Behaviour
gclid/ ad click id#anchordeep linkAlias redirection is preserved — it just no longer discards the payload.
Testing
npm testpasses (eslint, stylelint, markdownlint, template tests).