Advanced

Ad-Blocker Resistance

How the FanID Widget resists ad-blocker removal and best practices for self-hosting.

The gated content overlay is designed to resist removal by ad blockers like uBlock Origin and AdBlock Plus. Here's how it works and what you can do to strengthen it.

How ad blockers work

Ad blockers operate at three levels:

  1. CSS filter rules — Inject CSS to hide elements matching known selectors (e.g., .paywall-overlay { display: none })
  2. Element hiding — Hide entire elements by tag name or attribute
  3. Script blocking — Block JavaScript files by URL pattern

Built-in defenses

Randomized class names

Every page load generates a unique random prefix for all gated content CSS classes (e.g., _f3x9a_overlay, _k7m2p_panel). Since the class names are different on every page load, ad blockers cannot add them to static filter lists.

The styles are injected as a <style> tag in <head> with these randomized selectors. The SDK monitors the tag and re-injects it if removed.

Non-identifiable naming

  • No words like paywall, gate, wall, overlay, modal, popup, banner, ad, subscribe, or premium appear in the generated class names
  • CSS custom properties use the --fanid-gate-* namespace which is not in any ad-blocker filter list

Integrity verification

The SDK monitors gated elements with a MutationObserver and periodic checks. If the overlay is removed by a browser extension, it is re-applied within 3 seconds. The injected <style> tag is also monitored and re-injected if removed.

Best practices

Self-host the script

When loaded from a third-party CDN, ad blockers can identify and block the script by URL pattern. Self-hosting eliminates this:

  1. Download fan-id-widget.iife.js and widget.css
  2. Rename them if desired (e.g., auth.js, auth.css)
  3. Serve from your own domain alongside your other assets
<script src="/assets/js/auth.js"></script>
<link rel="stylesheet" href="/assets/css/auth.css" />

Bundle via npm

Even stronger — install via npm and bundle the widget into your application's JavaScript:

npm install @wmt-fanid/widget
import FanIDWidget from '@wmt-fanid/widget'

The widget code becomes part of your application bundle. Ad blockers cannot distinguish it from your first-party code without blocking your entire application.

Use a custom element name

If the default wmt-fanid-protected tag is ever added to a filter list:

FanIDWidget.init({
  baseUrl: 'https://your-org.fanid.co',
  gatedContent: {
    customElementName: 'my-premium-section'
  }
})

Each site can use a unique tag name that will never appear in any shared filter list.

Limitations

Gated content is a visual deterrent, not a security boundary. A determined user with browser DevTools can always inspect the DOM and read the source content. This is acceptable — the same model is used by Medium, LinkedIn, and major news paywalls.

Copyright © 2026