Block reddit click tracking

Stops reddit from tracking your inbound and outbound clicks

  1. // ==UserScript==
  2. // @name Block reddit click tracking
  3. // @namespace mjhcfwlmjfzg778evppa995xavvt2nmb
  4. // @description Stops reddit from tracking your inbound and outbound clicks
  5. // @license MIT
  6. // @match *://*.reddit.com/*
  7. // @version 1.2
  8. // @grant unsafeWindow
  9. // @run-at document-start
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. "use strict";
  14.  
  15. const expiredDate = Date.now().toString();
  16. const targetLink = Symbol();
  17.  
  18.  
  19. // Capturing event listener on the outermost element.
  20. // Runs FIRST, before any others.
  21. const beforeClick = function (event) {
  22. let target = event.target;
  23.  
  24. // Did we click on an element?
  25. if (target.nodeType === 1) {
  26. // Is that element inside a link?
  27. target = target.closest("a");
  28.  
  29. if (target) {
  30. // Stash link in the event object so that
  31. // the second handler doesn't have to dig
  32. // through the DOM with .closest() again
  33. event[targetLink] = target;
  34.  
  35. if (target.dataset.hrefUrl) {
  36. // Remove link tracking attributes
  37. delete target.dataset.inboundUrl;
  38. delete target.dataset.outboundUrl;
  39.  
  40. // Mark outbound link as expired so reddit code
  41. // does not try to use it
  42. if (target.dataset.outboundExpiration) {
  43. target.dataset.outboundExpiration = expiredDate;
  44. }
  45. }
  46. }
  47. }
  48. };
  49.  
  50.  
  51. // Bubbling event listener on the outermost element.
  52. // Runs LAST, just before the click goes through
  53. // (unless reddit code adds any others afterwards)
  54. const justBeforeClick = function (event) {
  55. const target = event[targetLink];
  56.  
  57. // If reddit event handlers modified the link, change it back
  58. if (target && target.dataset.hrefUrl) {
  59. target.href = target.dataset.hrefUrl;
  60. }
  61. };
  62.  
  63.  
  64. // Mark both event listeners as passive so they
  65. // won't impact scroll performance
  66. const doCapture = { capture: true, passive: true };
  67. const doBubble = { capture: false, passive: true };
  68.  
  69. window.addEventListener("mousedown", beforeClick, doCapture);
  70. window.addEventListener("keydown", beforeClick, doCapture);
  71. window.addEventListener("touchstart", beforeClick, doCapture);
  72.  
  73. window.addEventListener("mousedown", justBeforeClick, doBubble);
  74. window.addEventListener("keydown", justBeforeClick, doBubble);
  75. window.addEventListener("touchstart", justBeforeClick, doBubble);
  76.  
  77.  
  78. // Patch navigator.sendBeacon() if it is available
  79. if (typeof unsafeWindow.Navigator.prototype.sendBeacon === "function") {
  80. // Firefox/Greasemonkey defines exportFunction to make
  81. // sandboxed functions callable by the page script.
  82. const exportFunction = (window.exportFunction) ? window.exportFunction : (f) => f;
  83.  
  84. // Fake sendBeacon() function that does nothing
  85. Reflect.defineProperty(unsafeWindow.Navigator.prototype, "sendBeacon", {
  86. value: exportFunction(function sendBeacon(url) { return true; }, unsafeWindow)
  87. });
  88. }
  89. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址