Privacy Tools Guide

Third-party trackers have become ubiquitous across the web, collecting user data through scripts that load silently in the background. For developers building privacy-conscious applications and power users who want control over their digital footprint, understanding how these trackers operate and learning to block them is essential. This guide covers practical methods to detect hidden trackers and implement effective blocking strategies.

Understanding Third-Party Trackers

Third-party trackers are scripts embedded by external domains that collect browsing behavior, device information, and user interactions. Common tracker categories include:

These trackers often load via third-party domains, making them harder to spot than first-party analytics. The challenge lies in identifying requests to known tracker domains and detecting novel tracking techniques.

Detecting Trackers with Network Analysis

The most reliable method for detecting trackers involves analyzing network requests using browser developer tools or dedicated analysis tools.

Using Browser DevTools

Open Chrome DevTools (F12 or Cmd+Option+I) and navigate to the Network tab. Filter requests by domain to identify third-party connections:

// In DevTools Network tab, filter by common tracker domains
domain:google-analytics.com OR domain:facebook.com OR domain:doubleclick.net

Look for requests to known tracker domains. Pay attention to requests with:

Programmatic Detection with JavaScript

For automated analysis, you can intercept fetch and XMLHttpRequest calls:

const trackedDomains = new Set([
  'google-analytics.com',
  'facebook.com',
  'doubleclick.net',
  'hotjar.com',
  'segment.io',
  'newrelic.com'
]);

// Monitor fetch requests
const originalFetch = window.fetch;
window.fetch = function(...args) {
  const url = args[0];
  if (typeof url === 'string') {
    try {
      const hostname = new URL(url).hostname;
      trackedDomains.forEach(tracker => {
        if (hostname.includes(tracker)) {
          console.log(`[Tracker Detected] ${hostname} - ${url}`);
        }
      });
    } catch (e) {}
  }
  return originalFetch.apply(this, args);
};

// Monitor XMLHttpRequest
const originalXHROpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
  if (typeof url === 'string') {
    try {
      const hostname = new URL(url, location.origin).hostname;
      trackedDomains.forEach(tracker => {
        if (hostname.includes(tracker)) {
          console.log(`[Tracker Detected] ${hostname} - ${url}`);
        }
      });
    } catch (e) {}
  }
  return originalXHROpen.call(this, method, url, ...rest);
};

Building a Tracker Blocklist

Instead of blocking everything, you can create a targeted blocklist based on your threat model. Popular blocklists include EasyList and uBlock Origin’s filter lists, but you can create custom rules:

! Block specific tracker domains
||google-analytics.com^
||facebook.net^
||hotjar.com^

! Block tracker subdomains
||*.doubleclick.net^
||*.googlesyndication.com^

Blocking Trackers at Different Levels

Browser-Level Blocking

For end users, browser extensions provide the easiest way to block trackers. uBlock Origin is widely regarded as the most effective:

For Firefox users, Enhanced Tracking Protection automatically blocks known trackers in standard mode.

Application-Level Blocking

If you’re building a web application, you can implement tracker blocking at the edge using a Content Security Policy:

Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  connect-src 'self' https://api.yourapp.com;
  frame-src 'none';
  object-src 'none';

This CSP prevents loading scripts from third-party sources, though it requires careful configuration to avoid breaking legitimate functionality.

Network-Level Blocking

For protection, consider network-level blocking using Pi-hole or similar solutions:

# Add tracker domains to Pi-hole blocklist
pihole -w google-analytics.com
pihole -w facebook.com
pihole -w doubleclick.net

Network-level blocking protects all devices on your network without requiring browser extensions.

Detecting Fingerprinting Scripts

Beyond traditional trackers, fingerprinting scripts collect device characteristics to create unique identifiers without cookies. Detection requires analyzing script behavior:

// Detect API abuse for fingerprinting
const fingerprintingAPIs = [
  'CanvasRenderingContext2D',
  'WebGLRenderingContext',
  'AudioContext',
  'Navigator.userAgent',
  'Screen.width',
  'Screen.height'
];

// Monitor access to fingerprinting-susceptible APIs
fingerprintingAPIs.forEach(api => {
  const originalValue = window[api];
  if (originalValue) {
    Object.defineProperty(window, api, {
      get: function() {
        console.log(`[Fingerprinting Risk] Access to ${api}`);
        return originalValue;
      }
    });
  }
});

Tools like CanvasBlocker and Tor Browser provide built-in fingerprinting protection by adding noise to API responses or blocking suspicious access patterns.

Practical Implementation: Building a Tracker Detector

Here’s a complete example of a detection module you can integrate into your projects:

class TrackerDetector {
  constructor(options = {}) {
    this.blockedDomains = options.blockedDomains || [];
    this.onDetect = options.onDetect || (() => {});
    this.init();
  }

  init() {
    this.interceptFetch();
    this.interceptXHR();
    this.interceptScriptLoading();
  }

  isTracker(hostname) {
    return this.blockedDomains.some(domain =>
      hostname === domain || hostname.endsWith(`.${domain}`)
    );
  }

  interceptFetch() {
    const original = window.fetch;
    window.fetch = async (...args) => {
      const url = args[0]?.url || args[0];
      if (url && this.isTracker(new URL(url, location.origin).hostname)) {
        this.onDetect(url);
        if (this.options?.block) {
          return new Response('', { status: 204 });
        }
      }
      return original.apply(this, args);
    };
  }

  interceptXHR() {
    const original = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = (...args) => {
      const url = args[1];
      if (url && this.isTracker(new URL(url, location.origin).hostname)) {
        this.onDetect(url);
      }
      return original.apply(this, args);
    };
  }

  interceptScriptLoading() {
    const originalCreateElement = document.createElement;
    document.createElement = function(tag, ...args) {
      const element = originalCreateElement.call(this, tag, ...args);
      if (tag === 'script') {
        const originalSrc = Object.getOwnPropertyDescriptor(
          HTMLScriptElement.prototype, 'src'
        );
        Object.defineProperty(element, 'src', {
          set: function(value) {
            if (this.ownerDocument &&
                this.ownerDocument.location &&
                this.isTracker(new URL(value, this.ownerDocument.location.origin).hostname)) {
              this.onDetect(value);
            }
            originalSrc.set.call(this, value);
          },
          get: function() {
            return originalSrc.get.call(this);
          }
        });
      }
      return element;
    };
  }
}

// Usage
const detector = new TrackerDetector({
  blockedDomains: ['google-analytics.com', 'facebook.net'],
  onDetect: (url) => console.log('Blocked tracker:', url)
});

Built by theluckystrike — More at zovo.one