Ad Blocker Impact on Tracking | Blue Frog Docs

Ad Blocker Impact on Tracking

Understanding and mitigating the impact of ad blockers on analytics and conversion tracking

Ad Blocker Impact on Tracking

What This Means

Ad blockers and privacy-focused browsers can block analytics and marketing scripts, causing significant data loss. Studies suggest 25-40% of users have some form of ad blocking enabled, though rates vary by audience.

Impact on Tracking:

  • Analytics pageviews undercounted by 10-40%
  • Conversion events missing entirely
  • User journeys appear fragmented
  • Marketing attribution becomes unreliable
  • A/B testing sample sizes skewed

What Gets Blocked:

How to Diagnose

Measure Ad Blocker Rate

// Detect ad blocker presence
function detectAdBlocker() {
  return new Promise((resolve) => {
    // Method 1: Check for blocked elements
    const testAd = document.createElement('div');
    testAd.innerHTML = ' ';
    testAd.className = 'adsbox ad-banner textads';
    document.body.appendChild(testAd);

    setTimeout(() => {
      const isBlocked = testAd.offsetHeight === 0;
      testAd.remove();
      resolve(isBlocked);
    }, 100);
  });
}

// Method 2: Check if GA loaded
function isGABlocked() {
  return typeof window.gtag === 'undefined';
}

// Track ad blocker rate (via fallback endpoint)
detectAdBlocker().then(isBlocked => {
  navigator.sendBeacon('/api/analytics/adblock-detect', JSON.stringify({
    blocked: isBlocked,
    timestamp: Date.now()
  }));
});

Compare Data Sources

Check discrepancies between:

Source Method Affected by Ad Blockers
GA4 Client-side Yes (10-40% loss)
Server logs Server-side No
CRM data Backend No
Payment processor Backend No

Calculate your ad blocker rate:

Ad Blocker Rate = 1 - (GA4 Users / Server Log Unique Visitors)

Check Network Requests

  1. Open DevTools → Network tab
  2. Filter by "blocked" status (if available)
  3. Look for failed requests to:
    • google-analytics.com
    • googletagmanager.com
    • connect.facebook.net
    • px.ads.linkedin.com

General Fixes

Fix 1: Implement Server-Side Tracking

Server-side tracking is the most effective solution:

// Server-Side GTM Configuration
// Requests go to your first-party domain

// Client-side configuration
gtag('config', 'G-XXXXXXXXXX', {
  transport_url: 'https://sgtm.yourdomain.com',
  first_party_collection: true
});

// Server-side GTM forwards to GA4
// Ad blockers don't block first-party requests

Server-Side GTM Benefits:

  • First-party domain not blocked
  • Full control over data
  • Enhanced privacy
  • Better data quality

Fix 2: Use Custom Domain for GTM

Configure a custom domain (CNAME) for GTM:

# Nginx configuration
server {
    server_name gtm.yourdomain.com;

    location /gtm/ {
        proxy_pass https://www.googletagmanager.com/;
        proxy_set_header Host www.googletagmanager.com;
        proxy_ssl_server_name on;
    }

    location /ga/ {
        proxy_pass https://www.google-analytics.com/;
        proxy_set_header Host www.google-analytics.com;
        proxy_ssl_server_name on;
    }
}

Then update your GTM configuration:

// Load GTM from your domain
(function(w,d,s,l,i){
  w[l]=w[l]||[];
  w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});
  var f=d.getElementsByTagName(s)[0],
      j=d.createElement(s);
  j.async=true;
  j.src='https://gtm.yourdomain.com/gtm/gtm.js?id='+i;
  f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');

Fix 3: Hybrid Tracking Implementation

Track critical events both client and server-side:

// Hybrid approach for purchase tracking
async function trackPurchase(order) {
  // Client-side (might be blocked)
  if (window.gtag) {
    gtag('event', 'purchase', {
      transaction_id: order.id,
      value: order.total,
      currency: 'USD'
    });
  }

  // Server-side fallback (always works)
  await fetch('/api/track/purchase', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      event: 'purchase',
      transaction_id: order.id,
      value: order.total,
      client_id: getClientId()
    })
  });
}

Server endpoint:

// /api/track/purchase
export async function POST(request) {
  const data = await request.json();

  // Send to GA4 via Measurement Protocol
  await fetch(`https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXXXXX&api_secret=SECRET`, {
    method: 'POST',
    body: JSON.stringify({
      client_id: data.client_id,
      events: [{
        name: 'purchase',
        params: {
          transaction_id: data.transaction_id,
          value: data.value,
          currency: 'USD'
        }
      }]
    })
  });

  return Response.json({ success: true });
}

Fix 4: Beacon API for Critical Events

Use Beacon API which is harder to block:

// Beacon-based tracking
function trackWithBeacon(event, params) {
  const payload = JSON.stringify({
    event,
    params,
    timestamp: Date.now(),
    page: window.location.href
  });

  // Beacon to your first-party endpoint
  navigator.sendBeacon('/api/collect', payload);
}

// Use for important events
document.querySelector('form').addEventListener('submit', () => {
  trackWithBeacon('form_submit', { form_id: 'contact' });
});

Fix 5: Statistical Adjustment

Apply correction factors to your analytics:

// Calculate adjustment factor
const serverLogUsers = getServerLogUniqueVisitors();
const gaUsers = getGA4Users();
const adjustmentFactor = serverLogUsers / gaUsers;

// Apply to metrics
const adjustedConversions = gaConversions * adjustmentFactor;
const adjustedRevenue = gaRevenue * adjustmentFactor;

console.log(`Ad blocker adjustment: ${((adjustmentFactor - 1) * 100).toFixed(1)}%`);

Fix 6: Use Lightweight Analytics Alternatives

Consider analytics that are less frequently blocked:

Solution Blocking Rate Self-Hosted
Google Analytics High No
Plausible Low Yes
Fathom Low Yes
Umami Low Yes
Matomo Medium Yes
PostHog Medium Yes

Testing Ad Blocker Scenarios

  1. uBlock Origin (most popular)
  2. Adblock Plus
  3. Privacy Badger
  4. Brave Browser

Browser DevTools Testing

// Test in console with blocked scripts
// Check if tracking functions exist
console.log('gtag:', typeof window.gtag);
console.log('dataLayer:', window.dataLayer?.length);
console.log('fbq:', typeof window.fbq);

// Simulate blocked tracking
window.gtag = undefined;
// Then test your fallback mechanisms

Conversion Tracking Priority

For ad blockers, prioritize server-side for:

  1. Purchases - Critical for ROAS
  2. Form submissions - Lead generation
  3. Sign-ups - User acquisition
  4. Add to cart - Funnel tracking

Less critical (client-side OK):

Platform-Specific Guides

Platform Guide
Shopify Shopify Server-Side Tracking
WordPress WordPress Tracking Alternatives
Webflow Webflow Analytics Setup

Verification

After implementing fixes:

  1. Compare data sources

    • Server logs vs GA4
    • Payment data vs tracked purchases
  2. Test with ad blockers enabled

    • Verify events still reach backend
    • Check Measurement Protocol hits
  3. Monitor data quality

    • Check GA4 data quality reports
    • Compare week-over-week variances

Further Reading

// SYS.FOOTER