Keep licence keys and emails out of your analytics
Payment providers put the buyer's email and licence key in the return URL, and analytics records full URLs by default. Where it leaks, and the fix.
After a payment, our provider sends the buyer back to /order/complete with the payment id, the status, the buyer's email and their licence key in the URL. That is useful: it is how the page can show the key. It is also exactly the URL that analytics records on every page view.
Where it leaks
- Google Analytics records
page_locationas the full URL, query string included. - A hand-rolled Mixpanel call often sends
$current_urlaslocation.href. - The browser keeps it in history, and it appears in any screenshot of the address bar.
The fix, in three places
// 1. GA: set page_location before config on sensitive paths
var loc = location.pathname.indexOf("/order/") === 0
? location.origin + location.pathname : location.href;
gtag("config", id, { page_location: loc });
// 2. Your own events: same rule for $current_url
// 3. The page: read the params, then wipe them
history.replaceState(null, "", location.pathname);Scope it to the paths that carry private data rather than stripping every query string, or you lose UTM parameters that tell you which campaign brought someone.
Test it the boring way
Load the return page with a fake key, then open your analytics real-time view and the browser history, and search for the fake key. It should be in neither. The broader tracking setup this sits inside is in an event plan for a landing page.
Questions
Does GA4 record query strings?
Yes, page_location includes the full URL by default, query string and all. Set page_location yourself on pages whose query carries anything private.
Is an email address in a URL a privacy problem?
Yes. It ends up in analytics, in browser history and in any screenshot. Google Analytics' own policy prohibits sending personally identifiable information.
Should the page also remove the parameters?
Yes. Read them, then replace the URL in the address bar with the bare path using history.replaceState, so they do not sit in history or get bookmarked.