Back to Home

URL Tracker Cleanup in Manifest V3 Without Crashes

Article breaks down URL cleanup from trackers implementation in Chrome extensions Manifest V3. Described solutions for search engines whitelist, transitionType filtering, Clipboard API via content script. Provided working code with examples.

Manifest V3: Link Cleanup Without Breaking the Browser
Advertisement 728x90

Cleaning Tracker Parameters from URLs in Manifest V3: Avoiding Common Pitfalls

Browser extension developers often face the task of removing UTM tags, fbclid, gclid, and other tracking parameters from URLs. A simple implementation using regular expressions works for basic cases, but in Manifest V3, it leads to failures: breaking search engines, causing infinite redirects, and disrupting XHR requests. Let's explore key issues and their solutions with a real-world architecture example.

A whitelist for search engines prevents the removal of necessary parameters. Google, Yandex, and others use source and medium for filters (e.g., images, videos). Without exceptions, cleaning renders search non-functional.

const WHITELIST = [
  'google.com', 'bing.com', 'yandex.ru', 'duckduckgo.com' 
];

async function cleanUrl(url) {
  const urlObj = new URL(url);
  if (WHITELIST.some(site => urlObj.hostname.includes(site))) {
    return url; // Leave search engines untouched
  }
  // ... cleaning logic
}

Navigation in Manifest V3: Filtering Transitions

Manifest V3 restricts request interception. declarativeNetRequest doesn't parse parameters dynamically, so webNavigation.onBeforeNavigate is used. A simple redirect via chrome.tabs.update causes problems:

Google AdInline article slot
  • POST requests from forms break.
  • XHR/Fetch requests for JSON fail.
  • The redirect triggers the event repeatedly, creating a loop.

The solution is strict transitionType checking. Only handle 'link' (link clicks), ignoring typing, auto_subframe, and form_submit.

chrome.webNavigation.onBeforeNavigate.addListener(async (details) => {
  const result = await chrome.storage.sync.get(['autoClean']);
  if (!result.autoClean) return;

  if (details.transitionType !== 'link') return;

  const cleanedUrl = await cleanUrl(details.url);

  if (details.url !== cleanedUrl) {
    chrome.tabs.update(details.tabId, { url: cleanedUrl });
  }
}, {
  url: [
    {hostContains: '.'},
    {schemes: ['http', 'https']}
  ]
});

The hostContains: '.' filter excludes chrome-extension:// schemes, where new URL() behaves unpredictably.

Context Menu and Clipboard API

For manual link cleaning, add a context menu. In Manifest V3 Service Workers, clipboard access is blocked—delegate to a content script.

Google AdInline article slot

In background.js:

chrome.contextMenus.onClicked.addListener((info, tab) => {
  if (info.menuItemId === "cleanCopy" && info.linkUrl) {
    chrome.tabs.sendMessage(tab.id, {
      action: "cleanAndCopy",
      url: info.linkUrl
    });
  }
});

Content script uses the Async Clipboard API with a toast notification:

function cleanAndCopyLink(url) {
  chrome.runtime.sendMessage({ action: "cleanLink", url: url }, (response) => {
    if (response && response.cleanedUrl) {
      navigator.clipboard.writeText(response.cleanedUrl).then(() => {
        showNotification(`Link cleaned and copied!\nTrackers removed: ${response.trackerCount}`);
      });
    }
  });
}

function showNotification(message) {
  let toast = document.getElementById('zerotail-toast');
  if (!toast) {
    toast = document.createElement('div');
    toast.id = 'zerotail-toast';
    toast.style.cssText = `
      position: fixed; bottom: 20px; right: 20px;
      background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
      color: white; padding: 12px 20px; border-radius: 8px;
      box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 999999;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      max-width: 320px; transition: opacity 0.3s ease;
    `;
    document.body.appendChild(toast);
  }
  toast.textContent = message;
  toast.style.opacity = '1';
  setTimeout(() => { toast.style.opacity = '0'; }, 3000);
}

Styling mimics Material Design: gradient background, shadow, smooth fade.

Google AdInline article slot

Key Takeaways

  • Domain whitelist: Excludes search engines (google.com, yandex.ru) where parameters are critical for functionality.
  • transitionType === 'link': Prevents interference with forms, XHR, and URL input.
  • Scheme filter: hostContains: '.' + http/https avoids errors with extension://.
  • Clipboard delegation: Service Worker → Content Script for Manifest V3.
  • Toast UI: Minimalist notifications without alerts, with a count of removed trackers.

— Editorial Team

Advertisement 728x90

Read Next