Hide Twitter Ads

Hide ads on Twitter

  1. // ==UserScript==
  2. // @name Hide Twitter Ads
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description Hide ads on Twitter
  6. // @author Yeky
  7. // @match https://x.com/*
  8. // @grant none
  9. // @name:en Hide Twitter Ads
  10. // @name:zh 隐藏推特广告
  11. // @description 这个油猴脚本隐藏Twitter上的广告、趋势和用户推荐,提供更干净的浏览体验。
  12. // @description:en This Tampermonkey script hides ads, trends, and user recommendations on Twitter for a cleaner browsing experience.
  13. // @icon https://lh3.googleusercontent.com/RhFY2tkBB9MSrgCTDW0JdYnB51bJ_QmEPZRHVISanz34PWFA4CSCwW75m34sR7Oynl38odzKabuCIrWHB44akhHU=s60
  14. // @license All Rights Reserved
  15. // ==/UserScript==
  16.  
  17. (function() {
  18. 'use strict';
  19.  
  20. var adsHidden = 0;
  21. var adSelector = "div[data-testid=placementTracking]";
  22. var trendSelector = "div[data-testid=trend]";
  23. var userSelector = "div[data-testid=UserCell]";
  24. var articleSelector = "article[data-testid=tweet]";
  25.  
  26. var sponsoredSvgPath = 'M20.75 2H3.25C2.007 2 1 3.007 1 4.25v15.5C1 20.993 2.007 22 3.25 22h17.5c1.243 0 2.25-1.007 2.25-2.25V4.25C23 3.007 21.993 2 20.75 2zM17.5 13.504c0 .483-.392.875-.875.875s-.875-.393-.875-.876V9.967l-7.547 7.546c-.17.17-.395.256-.62.256s-.447-.086-.618-.257c-.342-.342-.342-.896 0-1.237l7.547-7.547h-3.54c-.482 0-.874-.393-.874-.876s.392-.875.875-.875h5.65c.483 0 .875.39.875.874v5.65z';
  27. var sponsoredBySvgPath = 'M19.498 3h-15c-1.381 0-2.5 1.12-2.5 2.5v13c0 1.38 1.119 2.5 2.5 2.5h15c1.381 0 2.5-1.12 2.5-2.5v-13c0-1.38-1.119-2.5-2.5-2.5zm-3.502 12h-2v-3.59l-5.293 5.3-1.414-1.42L12.581 10H8.996V8h7v7z';
  28. var youMightLikeSvgPath = 'M12 1.75c-5.11 0-9.25 4.14-9.25 9.25 0 4.77 3.61 8.7 8.25 9.2v2.96l1.15-.17c1.88-.29 4.11-1.56 5.87-3.5 1.79-1.96 3.17-4.69 3.23-7.97.09-5.54-4.14-9.77-9.25-9.77zM13 14H9v-2h4v2zm2-4H9V8h6v2z';
  29. var adsSvgPath = 'M19.498 3h-15c-1.381 0-2.5 1.12-2.5 2.5v13c0 1.38 1.119 2.5 2.5 2.5h15c1.381 0 2.5-1.12 2.5-2.5v-13c0-1.38-1.119-2.5-2.5-2.5zm-3.502 12h-2v-3.59l-5.293 5.3-1.414-1.42L12.581 10H8.996V8h7v7z';
  30. var peopleFollowSvgPath = 'M17.863 13.44c1.477 1.58 2.366 3.8 2.632 6.46l.11 1.1H3.395l.11-1.1c.266-2.66 1.155-4.88 2.632-6.46C7.627 11.85 9.648 11 12 11s4.373.85 5.863 2.44zM12 2C9.791 2 8 3.79 8 6s1.791 4 4 4 4-1.79 4-4-1.791-4-4-4z';
  31. var xAd = '>Ad<'; // TODO: add more languages; appears to only be used for English accounts as of 2023-08-03
  32. var removePeopleToFollow = false; // set to 'true' if you want these suggestions removed, however note this also deletes some tweet replies
  33. const promotedTweetTextSet = new Set(['Promoted Tweet', 'プロモツイート']);
  34.  
  35. function getAds() {
  36. return Array.from(document.querySelectorAll('div')).filter(function(el) {
  37. var filteredAd;
  38.  
  39. if (el.innerHTML.includes(sponsoredSvgPath)) {
  40. filteredAd = el;
  41. } else if (el.innerHTML.includes(sponsoredBySvgPath)) {
  42. filteredAd = el;
  43. } else if (el.innerHTML.includes(youMightLikeSvgPath)) {
  44. filteredAd = el;
  45. } else if (el.innerHTML.includes(adsSvgPath)) {
  46. filteredAd = el;
  47. } else if (removePeopleToFollow && el.innerHTML.includes(peopleFollowSvgPath)) {
  48. filteredAd = el;
  49. } else if (el.innerHTML.includes(xAd)) {
  50. filteredAd = el;
  51. } else if (promotedTweetTextSet.has(el.innerText)) { // TODO: bring back multi-lingual support from git history
  52. filteredAd = el;
  53. }
  54.  
  55. return filteredAd;
  56. })
  57. }
  58.  
  59. function hideAd(ad) {
  60. if (ad.closest(adSelector) !== null) { // Promoted tweets
  61. ad.closest(adSelector).remove();
  62. adsHidden += 1;
  63. } else if (ad.closest(trendSelector) !== null) {
  64. ad.closest(trendSelector).remove();
  65. adsHidden += 1;
  66. } else if (ad.closest(userSelector) !== null) {
  67. ad.closest(userSelector).remove();
  68. adsHidden += 1;
  69. } else if (ad.closest(articleSelector) !== null) {
  70. ad.closest(articleSelector).remove();
  71. adsHidden += 1;
  72. } else if (promotedTweetTextSet.has(ad.innerText)) {
  73. ad.remove();
  74. adsHidden += 1;
  75. }
  76.  
  77. console.log('X ads hidden: ', adsHidden.toString());
  78. }
  79.  
  80. function getAndHideAds() {
  81. getAds().forEach(hideAd)
  82. }
  83.  
  84. // hide ads on page load
  85. window.addEventListener('load', () => getAndHideAds());
  86.  
  87. // oftentimes, tweets render after onload. LCP should catch them.
  88. new PerformanceObserver((entryList) => {
  89. getAndHideAds();
  90. }).observe({type: 'largest-contentful-paint', buffered: true});
  91.  
  92. // re-check as user scrolls
  93. window.addEventListener('scroll', () => getAndHideAds());
  94.  
  95. // re-check as user scrolls tweet sidebar (exists when image is opened)
  96. var sidebarExists = setInterval(function() {
  97. let timelines = document.querySelectorAll("[aria-label='Timeline: Conversation']");
  98.  
  99. if (timelines.length == 2) {
  100. let tweetSidebar = document.querySelectorAll("[aria-label='Timeline: Conversation']")[0].parentElement.parentElement;
  101. tweetSidebar.addEventListener('scroll', () => getAndHideAds());
  102. }
  103. }, 500);
  104. })();

QingJ © 2025

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