From e1027cf5f811c73b78ca1bbb0e4d537b612c88e4 Mon Sep 17 00:00:00 2001 From: tecc Date: Tue, 27 Sep 2022 01:12:27 +0200 Subject: [PATCH 1/3] fix(tracking): Controlled tracking auto-pageviews: The `enableAutoPageviews` option (enabled by default) was also tracking specific profile views. plugin-track: The new track plugin (`plugins/track.js`) effectively replaces the autoPageview system, with a lot more customisability. Now, profile views are tracked as events rather than their specific pages. --- nuxt.config.js | 8 +++++++- plugins/track.js | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 plugins/track.js diff --git a/nuxt.config.js b/nuxt.config.js index 28c038a34..816a9cdea 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -139,6 +139,7 @@ export default { { src: '~/plugins/globals.js' }, { src: '~/plugins/auth.js' }, { src: '~/plugins/datepicker.js', ssr: false }, + { src: '~/plugins/track.js', ssr: false } ], components: true, buildModules: [], @@ -163,11 +164,16 @@ export default { }, plausible: { domain: process.env.PLAUSIBLE_DOMAIN || translations.domain, + // NOTE(privacy): Disables automatic tracking of page views, meaning we have to do it manually + // If it's not done manually, a privacy issue occurs, which we *do not want* + // - tecc + enableAutoPageviews: false }, publicRuntimeConfig: { plausible: { domain: process.env.PLAUSIBLE_DOMAIN || translations.domain, - apiHost: process.env.PLAUSIBLE_API_HOST + apiHost: process.env.PLAUSIBLE_API_HOST, + enableAutoPageviews: false // see previous comment } }, build: { diff --git a/plugins/track.js b/plugins/track.js new file mode 100644 index 000000000..b423d2b0f --- /dev/null +++ b/plugins/track.js @@ -0,0 +1,49 @@ +function defaultHandler({plausible, to, from}) { + // console.debug("[analytics] Tracking default handler"); + plausible.trackPageview() +} +function eventHandler(eventName) { + return function ({plausible, to, from}) { + plausible.trackEvent(eventName, {}, {}); + } +} + +const TRACKER_OVERRIDES = [ + { + test(v) { + return /^\/@.+/.test(v); + }, + handling: eventHandler('Profile view') + } +] + +export const plugin = function ({app}) { + const plausible = app.$plausible; + + app.router.afterEach((to, from) => { + let handler = defaultHandler; + for (const trackerOverride of TRACKER_OVERRIDES) { + if (!trackerOverride.test(to.fullPath)) { + continue; + } + + if (trackerOverride.handling === false) { + console.debug("[analytics] Page is blocked from tracking"); + } else if (typeof trackerOverride.handling === "function") { + handler = trackerOverride.handling; + } else { + throw new Error("Tracking override handling is invalid"); + } + break; + } + + // console.log("[analytics] Tracking pageview") + try { + handler({plausible, to, from}); + } catch (e) { + console.error("Error whilst trying to handle navigation: %O", e); + } + }) +} + +export default plugin; \ No newline at end of file From 866f3f4db6607e2a4ff7c5572f8ca79a42edd35c Mon Sep 17 00:00:00 2001 From: tecc Date: Tue, 27 Sep 2022 01:19:55 +0200 Subject: [PATCH 2/3] fix(tracking): Respecting no-tracking from handling --- plugins/track.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/track.js b/plugins/track.js index b423d2b0f..4fe430cf7 100644 --- a/plugins/track.js +++ b/plugins/track.js @@ -29,6 +29,7 @@ export const plugin = function ({app}) { if (trackerOverride.handling === false) { console.debug("[analytics] Page is blocked from tracking"); + return; } else if (typeof trackerOverride.handling === "function") { handler = trackerOverride.handling; } else { From 53dd20c17f4c865d797251fc7cbe6e9e1b29fdc8 Mon Sep 17 00:00:00 2001 From: tecc Date: Tue, 27 Sep 2022 19:10:44 +0200 Subject: [PATCH 3/3] change: Redacting profile views instead of creating event --- plugins/track.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/plugins/track.js b/plugins/track.js index 4fe430cf7..67b8c9616 100644 --- a/plugins/track.js +++ b/plugins/track.js @@ -7,13 +7,33 @@ function eventHandler(eventName) { plausible.trackEvent(eventName, {}, {}); } } +/** + * @param {(value: string) => string} redactor + * @param {(ctx) => void} base + * @return {(ctx) => void} + */ +function redact(redactor, base = defaultHandler) { + return (ctx) => base({ + ...ctx, + to: redactor(ctx) + }) +} const TRACKER_OVERRIDES = [ { test(v) { return /^\/@.+/.test(v); }, - handling: eventHandler('Profile view') + handling: redact((v) => { + const parts = v.split('/').filter((v) => v.length > 0); + for (const i in parts) { // NOTE(tecc): This might be overengineering but that's fine + const part = parts[i]; + if (/^@.+$/.test(part)) { + parts[i] = '@--redacted--'; + } + } + return '/' + parts.join('/'); + }) } ]