NNicheStackTutorials
← All tutorials
Static Hosting

Ad Blockers Broke My Vercel Static Site Layout — Script Paths That Trigger Filters

AdSense on Hugo/Vercel — uBlock hid more than ads. Filenames, third-party domains, and lazy-load patterns that look like malware.

·11 min read·Static Hosting
Ad Blockers Broke My Vercel Static Site Layout — Script Paths That Trigger Filters cover

Problem: 30% of visitors (per Plausible + manual testing) saw broken nav. Console:

GET https://mysite.com/js/ads.js net::ERR_BLOCKED_BY_CLIENT

Followed by JS error — my nav code was in the same file as ad loader.

Mistake: ads.js bundled with app logic

<script src="/js/ads.js"></script>  <!-- blocked -->
<script src="/js/site.js"></script>   <!-- fine -->

EasyList blocks paths matching ads.js, /ads/, ad-slot.

Fix: separate concerns

<script src="/js/site.js" defer></script>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" crossorigin="anonymous"></script>

Site works when ad script blocked. Ad slot collapses gracefully:

.ad-slot:empty { display: none; min-height: 0; }
.ad-slot { min-height: 90px; } /* reserve space only when ad loads */

Don't name folders /ads/

Static path /ads/banner.html — blocked even if it's your analytics dashboard.

Rename to /sponsors/ or /monetization/.

class names

class="ad-banner" — cosmetic filters hide it. Use neutral names:

<aside class="content-promo" data-ad-slot="sidebar"></aside>

Test with blockers on

# Chrome: install uBlock Origin
# Or curl won't help — must test in browser

Checklist:

  1. Disable JS in ads file — site navigable?
  2. No layout shift when slot empty?
  3. No combined bundles with "ad" in filename

Vercel note

Hosting doesn't cause blocking — path naming on your static export does. Same issue on any host.

Result

Bounce rate from ad-block users dropped 18% → 9% after splitting scripts.

Detect blocked ads in analytics

// Optional: don't gate features on ad load
window.addEventListener('load', () => {
  const slot = document.querySelector('[data-ad-slot]');
  if (slot && slot.offsetHeight === 0) {
    document.documentElement.dataset.adblock = 'likely';
  }
});

Use for layout tweaks only — never nag users to disable blockers.

Third-party script order

Load site.js first with defer. Ad scripts async at end of <body>. Parser never blocks on blocked ad URL.

Tags: Ad BlockAdSenseVercelStatic Site