-
Notifications
You must be signed in to change notification settings - Fork 0
fix: keep campaign parameters in browser page context #37
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
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| --- | ||
| "trakoo": minor | ||
| --- | ||
|
|
||
| Report the full page URL from the browser adapter so campaign parameters survive. `BrowserAnalytics` built its page context from `window.location.pathname` alone, so the query string never left the browser and every `utm_source`/`utm_medium`/`utm_campaign` value was dropped before delivery — campaign traffic arrived in the dashboard as direct. The adapter now also populates the `url`, `search`, `host` and `protocol` fields that `EventContext["page"]` already declared, from a single `getPageContext()` snapshot shared by `initialize()` and `pageView()`. | ||
|
|
||
| `updateContext()` also merges the page snapshot instead of rebuilding it from `path`, `title` and `referrer`, which had silently discarded every other declared field. Without that, only the immediate `pageView()` call carried a URL — `track()` and `pageLeave()` read the stored context and still saw none. Partial page updates now merge rather than erase, and an empty `search` is kept as a real value so a URL with no query string cannot inherit the previous page's parameters. | ||
|
|
||
| This reaches any provider that reports a URL. OpenPanel, Bento, EmitKit, Pirsch and the proxy all read `context.page.url` and fall back to `context.page.path`; until now that fallback was always taken. OpenPanel's `screenView()` consequently receives the full URL, which is what its own SDK sends when it tracks screen views itself, so its `__path` changes from a bare pathname to an absolute URL and its dashboard resolves the path and domain server-side. OpenPanel's `screenView()` also dedupes on the value it is handed, so two visits to one pathname under different query strings are now distinct: an app that calls `pageView()` when query parameters change — filters, pagination, tabs — emits one `screen_view` per change where it previously emitted one in total. Expect page-view counts on those routes to rise. | ||
|
|
||
| Nothing new is collected — the query string was always present in the browser — but a site that puts sensitive values in query parameters now sends them to its analytics provider, so exclude those before they reach the URL. |
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
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
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
Oops, something went wrong.
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.
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.
When initialization passes this snapshot to
updateContext, that method reconstructspageusing onlypath,title, andreferrer, silently discardingurl,search,host, andprotocol. Consequently, subsequenttrack()andpageLeave()calls still receive no campaign-bearing URL; only the immediatepageView()provider call works because it separately substitutes the localpagesnapshot. Merge every declared page field into the stored context instead.Useful? React with 👍 / 👎.
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.
Confirmed and fixed in d153f99 — thanks, this was a real gap.
updateContextrebuiltpagefrompath,titleandreferreronly, so the four new fields were discarded the moment they were stored.pageView()masked it by substituting its own local snapshot into the provider call, which is exactly why the adapter test passed while the bug was live;track()andpageLeave()readthis.contextand still saw no URL.It now merges the supplied fields over the stored ones. Two details worth noting:
updateContext({ page: { path } })no longer erases a storedurl. A plain spread would have let anundefinedwipe it.searchis kept as a real value when empty. A truthy fallback would have made a URL with no query string inherit the previous page's parameters.Two regression tests cover it:
track()afterpageView()carriespage.url, and partial updates neither erase nor go stale. Both fail against the previousupdateContext— verified by reverting just that hunk.