Blocks all ads, banners, and sponsored content on Rotter.net including Taboola widgets, ad containers, and sponsored links
Size
9.8 KB
Version
1.0.1
Created
Mar 11, 2026
Updated
about 1 month ago
1// ==UserScript==
2// @name Rotter.net Ad Blocker
3// @description Blocks all ads, banners, and sponsored content on Rotter.net including Taboola widgets, ad containers, and sponsored links
4// @version 1.0.1
5// @match https://*.rotter.net/*
6// @icon https://rotter.net/favicon.ico
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 console.log('Rotter.net Ad Blocker extension loaded');
12
13 // Main initialization function
14 async function init() {
15 console.log('Initializing ad blocker...');
16
17 // Block ads immediately when page loads
18 blockAds();
19
20 // Set up MutationObserver to block ads that load dynamically
21 setupMutationObserver();
22
23 // Add CSS to hide ads
24 addAdBlockingCSS();
25
26 // Show blocked ads count
27 showBlockedCount();
28 }
29
30 // Function to block all ads on the page
31 function blockAds() {
32 console.log('Blocking ads...');
33
34 // Common ad selectors based on analysis
35 const adSelectors = [
36 // Taboola ads
37 '[id*="taboola"]',
38 '[class*="taboola"]',
39 '.trc_related_container',
40 '.trc_rbox_container',
41 '.trc-content-sponsored',
42
43 // Ad containers with data-adpath
44 '[data-adpath]',
45 '[data-onpage="true"]',
46
47 // General ad selectors
48 '[id*="ad"]',
49 '[class*="ad"]',
50 '[id*="banner"]',
51 '[class*="banner"]',
52 '[id*="sponsor"]',
53 '[class*="sponsor"]',
54 '[id*="promo"]',
55 '[class*="promo"]',
56
57 // Specific elements found on rotter.net
58 '#adn_player',
59 'iframe[src*="ads"]',
60 'iframe[src*="ad"]',
61
62 // Social media widgets that might contain ads
63 '.social-widget',
64 '.share-widget'
65 ];
66
67 let blockedCount = 0;
68
69 // Try each selector and hide matching elements
70 adSelectors.forEach(selector => {
71 try {
72 const elements = document.querySelectorAll(selector);
73 elements.forEach(element => {
74 // Check if element is already hidden
75 if (element.style.display !== 'none' && element.style.visibility !== 'hidden') {
76 element.style.display = 'none';
77 element.style.visibility = 'hidden';
78 element.style.height = '0';
79 element.style.width = '0';
80 element.style.overflow = 'hidden';
81 element.style.opacity = '0';
82 blockedCount++;
83
84 console.log(`Blocked ad element: ${selector}`, element);
85 }
86 });
87 } catch (error) {
88 console.error(`Error blocking ads with selector ${selector}:`, error);
89 }
90 });
91
92 // Also block iframes that might contain ads
93 const iframes = document.querySelectorAll('iframe');
94 iframes.forEach(iframe => {
95 const src = iframe.src || '';
96 if (src.includes('ad') || src.includes('ads') || src.includes('banner') ||
97 src.includes('sponsor') || src.includes('promo')) {
98 iframe.style.display = 'none';
99 iframe.style.visibility = 'hidden';
100 blockedCount++;
101 console.log('Blocked ad iframe:', iframe);
102 }
103 });
104
105 console.log(`Blocked ${blockedCount} ad elements`);
106 return blockedCount;
107 }
108
109 // Set up MutationObserver to catch dynamically loaded ads
110 function setupMutationObserver() {
111 console.log('Setting up MutationObserver for dynamic ads...');
112
113 // Debounce function to prevent excessive calls
114 function debounce(func, wait) {
115 let timeout;
116 return function executedFunction(...args) {
117 const later = () => {
118 clearTimeout(timeout);
119 func(...args);
120 };
121 clearTimeout(timeout);
122 timeout = setTimeout(later, wait);
123 };
124 }
125
126 const debouncedBlockAds = debounce(() => {
127 console.log('Mutation detected, checking for new ads...');
128 blockAds();
129 showBlockedCount();
130 }, 500);
131
132 // Create MutationObserver
133 const observer = new MutationObserver((mutations) => {
134 let shouldBlock = false;
135
136 mutations.forEach(mutation => {
137 // Check if new nodes were added
138 if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
139 shouldBlock = true;
140 }
141
142 // Check if attributes changed (ads might load with different attributes)
143 if (mutation.type === 'attributes') {
144 const attrName = mutation.attributeName;
145 if (attrName && (attrName.includes('src') || attrName.includes('data-ad') ||
146 attrName.includes('class') || attrName.includes('id'))) {
147 shouldBlock = true;
148 }
149 }
150 });
151
152 if (shouldBlock) {
153 debouncedBlockAds();
154 }
155 });
156
157 // Start observing the document
158 observer.observe(document.documentElement, {
159 childList: true,
160 subtree: true,
161 attributes: true,
162 attributeFilter: ['src', 'data-ad', 'class', 'id', 'style']
163 });
164
165 console.log('MutationObserver started');
166 }
167
168 // Add CSS styles to hide ads
169 function addAdBlockingCSS() {
170 console.log('Adding ad blocking CSS...');
171
172 const css = `
173 /* Hide ad elements */
174 [id*="taboola"],
175 [class*="taboola"],
176 .trc_related_container,
177 .trc_rbox_container,
178 .trc-content-sponsored,
179 [data-adpath],
180 [data-onpage="true"],
181 #adn_player,
182 [id*="ad"],
183 [class*="ad"],
184 [id*="banner"],
185 [class*="banner"],
186 [id*="sponsor"],
187 [class*="sponsor"],
188 [id*="promo"],
189 [class*="promo"] {
190 display: none !important;
191 visibility: hidden !important;
192 height: 0 !important;
193 width: 0 !important;
194 overflow: hidden !important;
195 opacity: 0 !important;
196 position: absolute !important;
197 left: -9999px !important;
198 top: -9999px !important;
199 }
200
201 /* Hide ad iframes */
202 iframe[src*="ad"],
203 iframe[src*="ads"],
204 iframe[src*="banner"],
205 iframe[src*="sponsor"],
206 iframe[src*="promo"] {
207 display: none !important;
208 visibility: hidden !important;
209 }
210
211 /* Improve page layout after removing ads */
212 body {
213 overflow-x: hidden;
214 }
215
216 /* Optional: Add some visual feedback when ads are blocked */
217 .ad-blocked-notice {
218 display: none;
219 }
220 `;
221
222 const style = document.createElement('style');
223 style.textContent = css;
224 style.id = 'rotter-ad-blocker-styles';
225 document.head.appendChild(style);
226
227 console.log('Ad blocking CSS added');
228 }
229
230 // Show blocked ads count (optional visual feedback)
231 function showBlockedCount() {
232 // Remove any existing counter
233 const existingCounter = document.getElementById('ad-blocker-counter');
234 if (existingCounter) {
235 existingCounter.remove();
236 }
237
238 // Count ad elements that are hidden
239 const adElements = document.querySelectorAll(`
240 [id*="taboola"],
241 [class*="taboola"],
242 .trc_related_container,
243 [data-adpath],
244 #adn_player,
245 [id*="ad"],
246 [class*="ad"]
247 `);
248
249 let hiddenCount = 0;
250 adElements.forEach(el => {
251 const style = window.getComputedStyle(el);
252 if (style.display === 'none' || style.visibility === 'hidden') {
253 hiddenCount++;
254 }
255 });
256
257 // Create counter element
258 const counter = document.createElement('div');
259 counter.id = 'ad-blocker-counter';
260 counter.innerHTML = `🚫 ${hiddenCount} ads blocked`;
261 counter.style.cssText = `
262 position: fixed;
263 bottom: 20px;
264 right: 20px;
265 background: #4CAF50;
266 color: white;
267 padding: 8px 16px;
268 border-radius: 20px;
269 font-size: 14px;
270 font-family: Arial, sans-serif;
271 z-index: 999999;
272 box-shadow: 0 2px 10px rgba(0,0,0,0.2);
273 cursor: pointer;
274 transition: opacity 0.3s;
275 `;
276
277 // Add click to hide functionality
278 counter.addEventListener('click', () => {
279 counter.style.opacity = '0';
280 setTimeout(() => counter.remove(), 300);
281 });
282
283 document.body.appendChild(counter);
284
285 // Auto-hide after 5 seconds
286 setTimeout(() => {
287 if (counter.parentNode) {
288 counter.style.opacity = '0';
289 setTimeout(() => counter.remove(), 300);
290 }
291 }, 5000);
292
293 console.log(`Showing blocked count: ${hiddenCount} ads`);
294 }
295
296 // Initialize when DOM is ready
297 if (document.readyState === 'loading') {
298 document.addEventListener('DOMContentLoaded', init);
299 } else {
300 init();
301 }
302
303})();