Hide OLX Promoted Ads

It hides all promoted ads on OLX

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==

// @name         Hide OLX Promoted Ads
// @name:ro      Ascunde Anunțuri De Tip PROMOVAT Pe OLX
// @name:bg      Скриване На Реклами Тип ПРОМОТИРАНА ОБЯВА На OLX
// @name:ua      Приховати Оголошення Типу ТОП На OLX
// @name:pt      Ocultar Anúncios Do Tipo TOP No OLX
// @name:pl      Ukryj Ogłoszenia Typu WYRÓŻNIONE Na OLX

// @description  It hides all promoted ads on OLX
// @description:ro Ascunde toate anunțurile de tip PROMOVAT de pe OLX
// @description:bg Скрива всички реклами тип ПРОМОТИРАНА ОБЯВА на OLX
// @description:ua Сховує всі оголошення типу ТОП на OLX
// @description:pt Oculta todos os anúncios do tipo TOP no OLX
// @description:pl Ukrywa wszystkie ogłoszenia typu WYRÓŻNIONE na OLX

// @author       NWP
// @namespace    https://greasyfork.org/users/877912
// @version      1.0.0
// @license      MIT
// @match        *://www.olx.ro/*
// @match        *://www.olx.bg/*
// @match        *://www.olx.ua/*
// @match        *://www.olx.pt/*
// @match        *://www.olx.pl/*
// @grant        none
// @run-at       document-idle

// ==/UserScript==

(function () {
  "use strict";

  const DEBUG = false;

  const CARD_SELECTOR = '[data-cy="l-card"][data-testid="l-card"]';
  const HIDE_CLASS = "nwp-hide-promoted";

  // Patterns that indicate a promoted listing
  const PROMOTED_PATTERNS = [
    "promoted",   // search_reason=search|promoted
    "featured",   // possible alternative wording
  ];

  const processed = new WeakSet();

  function log(...args) {
    if (DEBUG) console.log("[OLX hide promoted]", ...args);
  }

  function injectCSS() {
    if (document.getElementById("nwp-promoted-hide-style")) return;
    const style = document.createElement("style");
    style.id = "nwp-promoted-hide-style";
    style.textContent = `
      .${HIDE_CLASS} { display: none !important; }
      .olx-rating-rowwrap:has(.${HIDE_CLASS}) { display: none !important; }
    `;
    document.documentElement.appendChild(style);
  }

  function isPromoted(card) {
    // Method 1: Check links for "promoted" in search_reason parameter
    const links = card.querySelectorAll("a[href]");
    for (const link of links) {
      const href = link.getAttribute("href") || "";
      for (const pattern of PROMOTED_PATTERNS) {
        if (href.includes(pattern)) {
          log("Promoted link found:", href);
          return true;
        }
      }
    }

    // Method 2 (fallback): Check if canvas has painted pixels (old method)
    const canvas = card.querySelector("canvas");
    if (canvas) {
      try {
        const ctx = canvas.getContext("2d");
        if (ctx) {
          const { data } = ctx.getImageData(0, 0, canvas.width, canvas.height);
          for (let i = 3; i < data.length; i += 4) {
            if (data[i] !== 0) {
              log("Painted canvas found");
              return true;
            }
          }
        }
      } catch (e) {
        // Tainted canvas — skip this check
      }
    }

    return false;
  }

  function processCard(card) {
    if (processed.has(card)) return;
    processed.add(card);

    if (isPromoted(card)) {
      card.classList.add(HIDE_CLASS);
      // Also add the class the rating script's CSS looks for
      card.classList.add("nwp-hide-painted-canvas");
      log("Hidden:", card.id || "(no-id)");

      // Hide the rating wrapper if it already exists
      const wrapper = card.closest(".olx-rating-rowwrap");
      if (wrapper) {
        wrapper.classList.add(HIDE_CLASS);
      }
    }
  }

  function processAll() {
    document.querySelectorAll(CARD_SELECTOR).forEach(processCard);
  }

  function setupObserver() {
    const mo = new MutationObserver((mutations) => {
      for (const m of mutations) {
        for (const node of m.addedNodes) {
          if (!(node instanceof Element)) continue;

          // New card added directly
          if (node.matches?.(CARD_SELECTOR)) {
            processCard(node);
          } else {
            // Card nested inside added subtree (e.g. rating script wrapping)
            node.querySelectorAll?.(CARD_SELECTOR).forEach((card) => {
              // If the card was already marked promoted but got reparented
              // by the rating script, ensure the new wrapper is also hidden.
              if (card.classList.contains(HIDE_CLASS)) {
                const wrapper = card.closest(".olx-rating-rowwrap");
                if (wrapper && !wrapper.classList.contains(HIDE_CLASS)) {
                  wrapper.classList.add(HIDE_CLASS);
                }
              } else {
                processCard(card);
              }
            });
          }
        }
      }
    });
    mo.observe(document.body, { childList: true, subtree: true });
  }

  function start() {
    injectCSS();
    processAll();
    setupObserver();
    log("Started");
  }

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", start, { once: true });
  } else {
    start();
  }
})();