-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsimple_url_tracker_cleaner.user.js
More file actions
115 lines (108 loc) · 4.78 KB
/
simple_url_tracker_cleaner.user.js
File metadata and controls
115 lines (108 loc) · 4.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// ==UserScript==
// @name Simple URL Tracker Cleaner
// @namespace https://github.com/StaticPH
// @match *://*/*
// @version 1.6.4
// @createdAt 8/10/2021
// @author StaticPH
// @description Scrub various common tracker parameters from URLs.
// @license MIT
// @updateURL https://raw.githubusercontent.com/StaticPH/Userscripts/master/simple_url_tracker_cleaner.user.js
// @downloadURL https://raw.githubusercontent.com/StaticPH/Userscripts/master/simple_url_tracker_cleaner.user.js
// @homepageURL https://github.com/StaticPH/UserScripts
// @supportURL https://github.com/StaticPH/UserScripts/issues
// @icon https://cdn-icons-png.flaticon.com/32/185/185441.png
// @grant none
// @run-at document-end
// ==/UserScript==
// Icon from https://www.flaticon.com/free-icon/fly-swatter_185441; All rights belong to their original owner(s).
(function(){
'use strict';
function queryParamFirst(href){
// Put the damn query parameter first so it's predictable
const args = href.split('&');
const queryIndex = args.findIndex(s => s.startsWith('q='));
if (queryIndex === -1){
return href;
}
const argStart = href.indexOf('?');
const pathTail = href.slice(href.lastIndexOf('/', argStart), argStart);
args[0] = args[0].replace(`${pathTail}?`, `${pathTail}?${args[queryIndex]}&`);
delete args[queryIndex];
return args.filter(Boolean).join('&');
}
function fixDanglingQuery(href){
return href.replace(/[?&]*#/, '#').replace(/[?&]*$/, '');
}
const commonRegex = {
stripAll: /[&?].+$/,
stripSearch: /[&?][^#]+/,
findUniversal: /(?:[?&])(amp;)?(utm_(source|medium|campaign|term|content)|(fb|g)clid)=[^&?#]*[&?#]?/,
stripUniversal: /(?:[?&])(amp;)?(utm_(source|medium|campaign|term|content)|(fb|g)clid)=[^&?#]*/g,
findGoogleUrlRedir: /google\.[^/]+\/url\?.*/,
findGSearchClutter: /google\.[^/]+\/search.*?[&?](ei|sa|ved|bi[wh]|spell|oq|gs_lcp|sclient|uact)=[^&?#]*/,
stripGSearchClutter: /&(ei|sa|ved|bi[wh]|spell|oq|gs_lcp|sclient|uact)=[^&?#]*/g,
findAmazonProduct: /amazon\.[^/]+\/[^/]+\/dp\/[^/]+\/[^?&]+[?&]/,
};
function cleanURLs(){
for (const link of document.links){
let fixed = null;
if (commonRegex.findGoogleUrlRedir.test(link.href)){
const url = new URL(link.href);
if (url.searchParams.has('url')){
fixed = url.searchParams.get('url');
if (!fixed || fixed.length === 0){ console.warn('Found empty "url" parameter in link: ' + link.href); }
else{
console.log(`${link.href} --> ${fixed}`);
link.href = fixed;
}
}
else if (url.searchParams.has('q')){
fixed = url.searchParams.get('q');
if (!fixed || fixed.length === 0){ console.warn('Found empty "q" parameter in link: ' + link.href); }
else if (fixed.startsWith('https://')){
if (url.searchParams.has('tbs')){ // This is one of the parameters actually worth keeping, as it controls some of the "advanced" filtering
fixed = fixed + '&' + url.searchParams.get('tbs');
}
console.log(`${link.href} --> ${fixed}`);
link.href = fixed;
}
else{
console.info('Expected query parameter starting with "https://", but found q=' + fixed);
}
}
else{
console.warn('Could not find expected "url" or "q" parameter for link: ' + link.href);
}
}
if (commonRegex.findUniversal.test(link.href)){
fixed = fixDanglingQuery(link.href.replace(commonRegex.stripUniversal, ''));
console.log(`${link.href} --> ${fixed}`);
link.href = fixed;
}
if (commonRegex.findGSearchClutter.test(link.href)){
// fixed = link.href.replace(/&(ei|sa|ved|bi[wh]|spell|oq|gs_lcp|sclient|uact)=[^&?#]*/g, '');
// fixed = link.href.replace(/\?([^&#=]+=[^&#]*((&[^&#=]+=[^&#]*)+)?&)(q=[^&?#]*)(.*)/, '?$4&$1$5').replace('&&','&'); // This *CAN'T* be the optimal way to handle scenarios where 'q' isn't the first search parameter...
fixed = queryParamFirst(link.href);
fixed = fixed.replace(commonRegex.stripGSearchClutter, '');
/* Compare performance against:
const oldUrl = new URL(link.href);
['ei','sa','ved','biw','bih','spell','oq','gs_lcp','sclient','uact'].forEach(oldUrl.searchParams.delete);
fixed = oldUrl.href;
*/
console.log(`${link.href} --> ${fixed}`);
link.href = fixed;
}
// TODO: More AMAZON URLS
// On Amazon product pages in particular, you can remove keywords, ref, dchild, pd*, pf*, qid, and sr
if (commonRegex.findAmazonProduct.test(link.href)){
fixed = link.href.replace(commonRegex.stripAll, '');
console.log(`${link.href} --> ${fixed}`);
link.href = fixed;
}
}
}
cleanURLs();
setInterval(cleanURLs, 5000);
// Apparently calling `cleanURLs()` in the setInterval call violates CSP on google pages, because something decides to try interpreting a simple string as javascript.
})();