您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
remove tracking parameters
当前为
// ==UserScript== // @name TrackingParameterRemover // @namespace https://htsign.hateblo.jp // @version 20240915-rev0 // @description remove tracking parameters // @author htsign // @match *://*/* // @run-at document-start // @grant GM_registerMenuCommand // ==/UserScript== const createStyle = params => { const toKebab = s => s.replace(/(?<=[a-z])[A-Z]/g, m => `-${m.toLowerCase()}`); return Object.entries(params) .reduce((acc, [key, val]) => ({ ...acc, [toKebab(key)]: val }), {}); }; GM_registerMenuCommand('open settings', ev => { const PADDING = 20; const wrapper = Object.assign( document.createElement('div'), { style: createStyle({ position: 'absolute', left: PADDING, top: PADDING, }), }, ); const shadowRoot = wrapper.shadowRoot ?? wrapper.attachShadow({ mode: 'open' }); document.body.append(wrapper); }); (function() { 'use strict'; const TRACKING_TAGS = [ '#?utm_campaign', '#?utm_content', '#?utm_int', '#?utm_medium', '#?utm_source', '_hsmi', '_openstat', 'action_object_map', 'action_ref_map', 'action_type_map', 'fb_action_ids', 'fb_action_types', 'fb_ref', 'fb_source', 'ga_campaign', 'ga_content', 'ga_medium', 'ga_place', 'ga_source', 'ga_term', 'gs_l', 'guccounter', 'guce_referrer', 'guce_referrer_sig', 'gws_rd', 'hmb_campaign', 'hmb_medium', 'hmb_source', 'ref_src', 'ref_url', 'utm_campaign', 'utm_cid', 'utm_content', 'utm_int', 'utm_language', 'utm_medium', 'utm_name', 'utm_place', 'utm_pubreferrer', 'utm_reader', 'utm_source', 'utm_swu', 'utm_term', 'utm_userid', 'utm_viz_id', 'yclid', '[email protected]', '_encoding@amazon.*', 'linkCode@amazon.*', 'linkId@amazon.*', 'pd_rd_*@amazon.*', 'psc@amazon.*', 'qid@amazon.*', 'sbo@amazon.*', 'sprefix@amazon.*', 'sr@amazon.*', 'tag@amazon.*', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', 'bi?@google.*', 'client@google.*', 'dpr@google.*', 'ei@google.*', 'gws_rd@google.*', 'oq@google.*', 'sa@google.*', 'sei@google.*', 'source@google.*', 'ved@google.*', '[email protected]', '[email protected]', '[email protected]', 'ref@*.nicovideo.jp', 'ss_id@*.nicovideo.jp', 'ss_pos@*.nicovideo.jp', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]/watch', ]; /** * @param {Location} loc * @returns {{ url: string, locationChanged: boolean }} */ const removeTracking = loc => { let locationChanged = false; const escapables = Object.freeze({ '.': '\.', }); const wildcardCharacters = Object.freeze({ '*': '.*', '?': '.', }); const wildcardKeys = Object.keys(wildcardCharacters); /** * @param {string} pattern * @returns {RegExp} */ const toRegExp = pattern => { /** * * @param {Record<string, string>} table * @param {string} s * @returns {string} */ const replace = (table, s) => Object.entries(table).reduce((acc, [f, t]) => acc.split(f).join(t), s); const sanitized = replace(escapables, pattern); const inner = replace(wildcardCharacters, sanitized); return new RegExp('^' + inner + '$', 'i'); }; /** * * @param {string} pattern * @param {string} s * @returns {boolean} */ const match = (pattern, s) => { if (wildcardKeys.some(c => pattern.includes(c))) { return toRegExp(pattern).test(s); } return pattern === s; }; /** * @param {string} domain * @param {URLSearchParams} params * @param {string} pattern * @returns {string} */ const deleteKeys = (domain, params, pattern) => { if (!domain || loc.hostname.split('.').some((_, i, arr) => match(domain, arr.slice(i).join('.')))) { for (const [key] of params) { if (match(pattern, key)) { params.delete(key); locationChanged = true; } } } return params.toString().split('%25').join('%'); }; /** * @param {string} search * @param {() => boolean} condition * @param {(arg: URLSearchParams) => any} callback * @returns {void} */ const proc = (search, condition, callback) => { const params = new URLSearchParams(search); if (params.size === 0) return; if (!condition()) return; callback(params); }; const url = new URL(loc); url.search = url.search.split('%25').join('\0'); // avoid to escape of original '%25' TRACKING_TAGS.forEach(tag => { const [t, domain, pathname] = tag.split(/[@\/]/); if (t.startsWith('#?')) { proc( url.hash.slice(1), () => pathname == null || url.pathname === `/${pathname}`, params => { url.hash = deleteKeys(domain, params, t.slice(2)); }, ); } else { if (!url.search) return; proc( url.search.slice(1).replace(/%(?!25)/g, '%25'), () => pathname == null || url.pathname === `/${pathname}`, params => { url.search = deleteKeys(domain, params, t); }, ); } }); url.search = url.search.split('%00').join('%25'); // restore original '%25' return { url: url.href, locationChanged }; }; const { url, locationChanged } = removeTracking(location); if (locationChanged) { console.info(`TrackingParameterRemover: {${location.href}} => {${url}}`); location.replace(url); } }());
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址