fix: only attribute referrer to landing page and strip Meta ad params
This commit is contained in:
@@ -15,6 +15,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|||||||
- **Preloaded pages no longer count as visits.** Modern browsers sometimes preload pages in the background before you actually visit them. These ghost visits no longer inflate your pageview counts — only pages the visitor actually sees are tracked.
|
- **Preloaded pages no longer count as visits.** Modern browsers sometimes preload pages in the background before you actually visit them. These ghost visits no longer inflate your pageview counts — only pages the visitor actually sees are tracked.
|
||||||
- **Marketing parameters no longer fragment your pages.** Pages like `/about?utm_source=google` and `/about?utm_campaign=spring` now correctly show as just `/about` in your Top Pages. UTM tags, Facebook click IDs, Google click IDs, and other tracking parameters are stripped from the page path so all visits to the same page are grouped together.
|
- **Marketing parameters no longer fragment your pages.** Pages like `/about?utm_source=google` and `/about?utm_campaign=spring` now correctly show as just `/about` in your Top Pages. UTM tags, Facebook click IDs, Google click IDs, and other tracking parameters are stripped from the page path so all visits to the same page are grouped together.
|
||||||
- **Trailing slashes no longer split pages.** `/about/` and `/about` now count as the same page instead of appearing as separate entries in your analytics.
|
- **Trailing slashes no longer split pages.** `/about/` and `/about` now count as the same page instead of appearing as separate entries in your analytics.
|
||||||
|
- **Traffic sources are no longer over-counted.** When a visitor arrived from Facebook (or any external source) and browsed multiple pages, every page was credited to Facebook instead of just the first. Now only the landing page shows the referrer, giving you accurate traffic source numbers.
|
||||||
|
- **More ad parameters are cleaned from page paths.** Facebook and Meta ad parameters like `ad_id` and `campaign_id` are now stripped, so pages shared across different ad campaigns all show as one entry in your Top Pages.
|
||||||
|
|
||||||
## [0.15.0-alpha] - 2026-03-13
|
## [0.15.0-alpha] - 2026-03-13
|
||||||
|
|
||||||
|
|||||||
@@ -226,7 +226,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// * Normalize path: strip trailing slash and UTM/marketing query parameters
|
// * Normalize path: strip trailing slash and UTM/marketing query parameters
|
||||||
var UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'utm_id', 'fbclid', 'gclid', 'gad_source', 'msclkid', 'twclid', 'dclid', 'mc_cid', 'mc_eid', 'ref'];
|
var UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'utm_id', 'fbclid', 'gclid', 'gad_source', 'msclkid', 'twclid', 'dclid', 'mc_cid', 'mc_eid', 'ref', 'ad_id', 'adset_id', 'campaign_id', 'ad_name', 'adset_name', 'campaign_name', 'placement', 'site_source_name'];
|
||||||
function cleanPath() {
|
function cleanPath() {
|
||||||
var pathname = window.location.pathname;
|
var pathname = window.location.pathname;
|
||||||
// * Strip trailing slash (but keep root /)
|
// * Strip trailing slash (but keep root /)
|
||||||
@@ -250,6 +250,9 @@
|
|||||||
return pathname;
|
return pathname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// * SPA referrer: only attribute external referrer to the landing page
|
||||||
|
var firstPageviewSent = false;
|
||||||
|
|
||||||
// * Refresh dedup: skip pageview if the same path was tracked within 5 seconds
|
// * Refresh dedup: skip pageview if the same path was tracked within 5 seconds
|
||||||
// * Prevents inflated pageview counts from F5/refresh while allowing genuine revisits
|
// * Prevents inflated pageview counts from F5/refresh while allowing genuine revisits
|
||||||
var REFRESH_DEDUP_WINDOW = 5000;
|
var REFRESH_DEDUP_WINDOW = 5000;
|
||||||
@@ -295,16 +298,20 @@
|
|||||||
lcpObserved = false;
|
lcpObserved = false;
|
||||||
clsObserved = false;
|
clsObserved = false;
|
||||||
currentEventId = null;
|
currentEventId = null;
|
||||||
// * Strip self-referrals: don't send referrer if it matches the current site domain
|
// * Only send external referrer on the first pageview (landing page).
|
||||||
var rawReferrer = document.referrer || '';
|
// * SPA navigations keep document.referrer stale, so clear it after first hit
|
||||||
|
// * to avoid inflating traffic source attribution.
|
||||||
var referrer = '';
|
var referrer = '';
|
||||||
if (rawReferrer) {
|
if (!firstPageviewSent) {
|
||||||
try {
|
var rawReferrer = document.referrer || '';
|
||||||
var refHost = new URL(rawReferrer).hostname.replace(/^www\./, '');
|
if (rawReferrer) {
|
||||||
var siteHost = domain.replace(/^www\./, '');
|
try {
|
||||||
if (refHost !== siteHost) referrer = rawReferrer;
|
var refHost = new URL(rawReferrer).hostname.replace(/^www\./, '');
|
||||||
} catch (e) {
|
var siteHost = domain.replace(/^www\./, '');
|
||||||
referrer = rawReferrer;
|
if (refHost !== siteHost) referrer = rawReferrer;
|
||||||
|
} catch (e) {
|
||||||
|
referrer = rawReferrer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const screenSize = {
|
const screenSize = {
|
||||||
@@ -331,6 +338,7 @@
|
|||||||
}).then(res => res.json())
|
}).then(res => res.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
recordPageview(path);
|
recordPageview(path);
|
||||||
|
firstPageviewSent = true;
|
||||||
if (data && data.id) {
|
if (data && data.id) {
|
||||||
currentEventId = data.id;
|
currentEventId = data.id;
|
||||||
// * For SPA navigations the browser never emits a new largest-contentful-paint
|
// * For SPA navigations the browser never emits a new largest-contentful-paint
|
||||||
@@ -407,14 +415,17 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var path = cleanPath();
|
var path = cleanPath();
|
||||||
var rawRef = document.referrer || '';
|
// * Custom events use same referrer logic: only on first pageview, empty after
|
||||||
var referrer = '';
|
var referrer = '';
|
||||||
if (rawRef) {
|
if (!firstPageviewSent) {
|
||||||
try {
|
var rawRef = document.referrer || '';
|
||||||
var rh = new URL(rawRef).hostname.replace(/^www\./, '');
|
if (rawRef) {
|
||||||
var sh = domain.replace(/^www\./, '');
|
try {
|
||||||
if (rh !== sh) referrer = rawRef;
|
var rh = new URL(rawRef).hostname.replace(/^www\./, '');
|
||||||
} catch (e) { referrer = rawRef; }
|
var sh = domain.replace(/^www\./, '');
|
||||||
|
if (rh !== sh) referrer = rawRef;
|
||||||
|
} catch (e) { referrer = rawRef; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var screenSize = { width: window.innerWidth || 0, height: window.innerHeight || 0 };
|
var screenSize = { width: window.innerWidth || 0, height: window.innerHeight || 0 };
|
||||||
var payload = {
|
var payload = {
|
||||||
|
|||||||
Reference in New Issue
Block a user