From 44ef4ea2584b5c2976d6217994282d9068c5a2e2 Mon Sep 17 00:00:00 2001 From: Adriaan <1079135+adriaandotcom@users.noreply.github.com> Date: Tue, 3 Jun 2025 15:09:31 +0200 Subject: [PATCH] fix utm parsing for manual pageview --- dist/latest/latest.dev.js | 26 +++++++++++++++++++------- src/default.js | 24 ++++++++++++++++++------ test/unit/manual-utm.test.js | 22 ++++++++++++++++++++++ 3 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 test/unit/manual-utm.test.js diff --git a/dist/latest/latest.dev.js b/dist/latest/latest.dev.js index 06bf05c..33aadcc 100644 --- a/dist/latest/latest.dev.js +++ b/dist/latest/latest.dev.js @@ -1,4 +1,4 @@ -/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2025-05-29; 36a5; v12) */ +/* Simple Analytics - Privacy-first analytics (docs.simpleanalytics.com/script; 2025-05-30; 8e6f; v12) */ /* eslint-env browser */ (function ( @@ -216,9 +216,11 @@ overwriteOptions.strictUtm || attr(scriptElement, "strict-utm") == trueText; - var getQueryParams = function (ignoreSource) { + var getQueryParams = function (ignoreSource, overrideQuery) { + var search = + overrideQuery !== undefinedVar ? "?" + overrideQuery : loc.search; return ( - loc.search + search .slice(1) .split("&") .filter(function (keyValue) { @@ -511,6 +513,7 @@ var page = {}; var lastSendPath; + var queryOverwrite; var getReferrer = function () { // Customers can overwrite their referrer, here we check for that @@ -619,6 +622,7 @@ var getPath = function (overwrite) { var path = ""; + queryOverwrite = undefinedVar; // decodeURIComponent can fail when having invalid characters // https://github.com/simpleanalytics/roadmap/issues/462 @@ -628,6 +632,12 @@ warn(error); } + if (overwrite && overwrite.indexOf("?") > -1) { + var overwriteParts = overwrite.split("?"); + path = overwriteParts[0]; + queryOverwrite = overwriteParts.slice(1).join("?").split("#")[0]; + } + var pathOverwriterFunction = window[pathOverwriter]; if (isFunction(pathOverwriterFunction)) { try { @@ -656,18 +666,19 @@ isPushState, deleteSourceInfo, sameSite, - metadata + metadata, + queryOverwrite ) { if (isPushState) sendOnLeave("" + payload.page_id, trueVar); if (collectDataOnLeave) payload.page_id = uuid(); - var currentPage = definedHostname + getPath(); + var currentPage = definedHostname + page.path; sendData({ id: payload.page_id, type: pageviewText, referrer: !deleteSourceInfo || sameSite ? referrer : null, - query: getQueryParams(deleteSourceInfo), + query: getQueryParams(deleteSourceInfo, queryOverwrite), metadata: stringify(metadata), }); @@ -759,7 +770,8 @@ isPushState, isPushState || userNavigated || !collectMetricByString("r"), // r = referrers sameSite, - metadata + metadata, + queryOverwrite ); }; diff --git a/src/default.js b/src/default.js index 816815a..305f956 100644 --- a/src/default.js +++ b/src/default.js @@ -232,9 +232,11 @@ overwriteOptions.strictUtm || attr(scriptElement, "strict-utm") == trueText; - var getQueryParams = function (ignoreSource) { + var getQueryParams = function (ignoreSource, overrideQuery) { + var search = + overrideQuery !== undefinedVar ? "?" + overrideQuery : loc.search; return ( - loc.search + search .slice(1) .split("&") .filter(function (keyValue) { @@ -586,6 +588,7 @@ var page = {}; var lastSendPath; + var queryOverwrite; var getReferrer = function () { // Customers can overwrite their referrer, here we check for that @@ -702,6 +705,7 @@ var getPath = function (overwrite) { var path = ""; + queryOverwrite = undefinedVar; // decodeURIComponent can fail when having invalid characters // https://github.com/simpleanalytics/roadmap/issues/462 @@ -711,6 +715,12 @@ warn(error); } + if (overwrite && overwrite.indexOf("?") > -1) { + var overwriteParts = overwrite.split("?"); + path = overwriteParts[0]; + queryOverwrite = overwriteParts.slice(1).join("?").split("#")[0]; + } + /** if pathoverwriter **/ var pathOverwriterFunction = window[pathOverwriter]; if (isFunction(pathOverwriterFunction)) { @@ -745,18 +755,19 @@ isPushState, deleteSourceInfo, sameSite, - metadata + metadata, + queryOverwrite ) { if (isPushState) sendOnLeave("" + payload.page_id, trueVar); if (collectDataOnLeave) payload.page_id = uuid(); - var currentPage = definedHostname + getPath(); + var currentPage = definedHostname + page.path; sendData({ id: payload.page_id, type: pageviewText, referrer: !deleteSourceInfo || sameSite ? referrer : null, - query: getQueryParams(deleteSourceInfo), + query: getQueryParams(deleteSourceInfo, queryOverwrite), /** if metadata **/ metadata: stringify(metadata), @@ -864,7 +875,8 @@ isPushState, isPushState || userNavigated || !collectMetricByString("r"), // r = referrers sameSite, - metadata + metadata, + queryOverwrite ); }; diff --git a/test/unit/manual-utm.test.js b/test/unit/manual-utm.test.js new file mode 100644 index 0000000..843bb43 --- /dev/null +++ b/test/unit/manual-utm.test.js @@ -0,0 +1,22 @@ +const { expect } = require("chai"); +const { createDOM } = require("./helpers/dom"); + +describe("manual pageview utm", function () { + it("parses utm params from manual path", function (done) { + const dom = createDOM({ settings: { autoCollect: false } }); + + dom.window.sa_pageview("/sa/1/1/1/1?utm_source=test&utm_medium=email"); + + setTimeout(() => { + const req = dom.sent.find( + (r) => r.type === "image" && /path=%2Fsa%2F1%2F1%2F1%2F1/.test(r.url) + ); + expect(req, "pageview request").to.exist; + const url = new URL(req.url); + expect(url.searchParams.get("query")).to.equal( + "utm_source=test&utm_medium=email" + ); + done(); + }, 10); + }); +});