Complete Guide to Optimizing Google Ads Revenue with Cloudflare Workers: Solving the CDN Proxy Revenue Drop Issue

Why Does Google Ads Revenue Drop Significantly After Implementing Cloudflare?

Many website owners encounter a puzzling problem after integrating Cloudflare CDN into their websites: Google AdSense impressions and cost per thousand impressions (CPM) suddenly plummet. This isn’t a random occurrence but rather an inevitable consequence of how Cloudflare’s infrastructure operates.

The Root Cause of the Problem

When your website uses Cloudflare as a CDN and reverse proxy, all visitor requests first pass through Cloudflare’s servers before being forwarded to your origin server. During this process, several critical issues emerge:

「IP Address Replacement」: The visitor’s real IP address gets replaced with Cloudflare’s IP address. For instance, a visitor from Beijing, China, after passing through Cloudflare’s Amsterdam node, appears to your server as having a Netherlands IP address.

「Geographic Targeting Failure」: Google Ads relies on accurate geographic location data to serve advertisements. When advertisers configure their campaigns to display ads only to users in China, the system incorrectly identifies the visitor as being from the Netherlands, preventing proper ad delivery.

「User Profiling Disruption」: Cloudflare’s caching and proxy mechanisms interfere with Google Ads’ user tracking capabilities, causing personalized ad targeting to fail and resulting in only low-value generic ads being displayed.

「Real-World Impact Data」: Comparative data from a website before and after Cloudflare implementation shows that with 1,245 page views, only 285 ad impressions occurred—a mere 23% impression rate. CPM dropped from a normal range of 2.00 to just $0.05, and click-through rate (CTR) decreased from the normal 0.5-2% range to only 0.08%.

What is Cloudflare Workers and How Does It Solve This Problem?

Cloudflare Workers is a serverless computing platform that runs on Cloudflare’s edge network. It allows you to execute JavaScript code at Cloudflare’s edge nodes before requests reach your server, enabling you to modify both requests and responses.

The core functionality of Workers involves intercepting every HTTP request passing through Cloudflare, allowing you to:

  • Read and modify request headers
  • Add custom HTTP headers
  • Control caching strategies
  • Forward genuine visitor IP addresses
  • Execute different logic based on various conditions

Through Workers, we can add the visitor’s real IP address and geographic location information to HTTP headers before the request is forwarded to the origin server, enabling your website and Google Ads to obtain accurate visitor information.

Complete Solution: Deploying Cloudflare Workers

Step One: Create a Worker

  1. Log into Cloudflare Dashboard (https://dash.cloudflare.com)
  2. Locate “Workers & Pages” in the left sidebar menu
  3. Click the “Create application” or “Create Worker” button
  4. Name your Worker, for example “google-ads-optimizer”
  5. Click “Deploy” to deploy the default code

Step Two: Write the Worker Code

Click “Edit Code” to enter the code editor, delete all default code, and paste the following complete code:

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  const url = new URL(request.url)
  const realIP = request.headers.get('CF-Connecting-IP') || 'unknown'
  const country = request.headers.get('CF-IPCountry') || 'unknown'
  
  // Ad-related keywords
  const adKeywords = [
    'adsbygoogle',
    'googlesyndication',
    'doubleclick',
    'pagead',
    'googletagservices',
    'googletagmanager',
    'google-analytics'
  ]
  
  // WordPress admin and dynamic path list
  const wpAdminPaths = [
    '/wp-admin',
    '/wp-login.php',
    '/wp-json/',
    '/xmlrpc.php',
    '/wp-cron.php',
    '/wp-comments-post.php',
    '?preview=',
    '/checkout/',
    '/cart/',
    '/my-account/'
  ]
  
  // Check various request types
  const isAd = adKeywords.some(keyword => 
    url.href.toLowerCase().includes(keyword)
  )
  
  const isTxt = url.pathname.toLowerCase().endsWith('.txt')
  
  const isWpAdmin = wpAdminPaths.some(path => 
    url.pathname.includes(path) || url.search.includes(path)
  )
  
  const isPostRequest = request.method === 'POST'
  
  const cookies = request.headers.get('Cookie') || ''
  const isLoggedIn = cookies.includes('wordpress_logged_in') || 
                     cookies.includes('wp-settings-')
  
  // Requests that need to bypass cache
  const noCache = isAd || isTxt || isWpAdmin || isPostRequest || isLoggedIn
  
  // Add real IP to request headers
  const headers = new Headers(request.headers)
  headers.set('X-Real-IP', realIP)
  headers.set('X-Forwarded-For', realIP)
  headers.set('X-Country', country)
  headers.set('X-Forwarded-Proto', 'https')
  headers.set('X-Original-IP', realIP)
  
  // Add request type markers
  if (isAd) headers.set('X-Ad-Request', 'true')
  if (isTxt) headers.set('X-Txt-File', 'true')
  if (isWpAdmin) headers.set('X-WP-Admin', 'true')
  if (isPostRequest) headers.set('X-Post-Request', 'true')
  if (isLoggedIn) headers.set('X-Logged-In', 'true')
  
  const modifiedRequest = new Request(request, { headers })
  
  // Get response
  const response = await fetch(modifiedRequest, {
    cf: noCache ? { 
      cacheTtl: 0, 
      cacheEverything: false 
    } : { 
      cacheTtl: 3600,
      cacheEverything: true 
    }
  })
  
  // Create new response and add markers
  const newResponse = new Response(response.body, response)
  newResponse.headers.set('X-Worker-Status', 'active')
  newResponse.headers.set('X-Worker-Version', '1.3')
  newResponse.headers.set('X-Visitor-IP', realIP)
  newResponse.headers.set('X-Visitor-Country', country)
  newResponse.headers.set('X-Ad-Optimized', isAd ? 'yes' : 'no')
  
  // Force no-cache
  if (noCache) {
    newResponse.headers.set('Cache-Control', 'no-cache, no-store, must-revalidate, private')
    newResponse.headers.set('Pragma', 'no-cache')
    newResponse.headers.set('Expires', '0')
    newResponse.headers.set('X-Cache-Bypass', 'true')
    
    if (isWpAdmin) newResponse.headers.set('X-No-Cache-Reason', 'wp-admin')
    else if (isPostRequest) newResponse.headers.set('X-No-Cache-Reason', 'post-request')
    else if (isLoggedIn) newResponse.headers.set('X-No-Cache-Reason', 'logged-in')
    else if (isTxt) newResponse.headers.set('X-No-Cache-Reason', 'txt-file')
    else if (isAd) newResponse.headers.set('X-No-Cache-Reason', 'ad-request')
  }
  
  return newResponse
}

Click “Save and Deploy” in the upper right corner to save and deploy.

Step Three: Configure Routes

After deploying the Worker, you need to bind it to your domain for it to take effect:

  1. On the Worker page, click the “Triggers” tab
  2. Find the “Routes” section and click “Add route”
  3. Add the first route:

    • Route: yourdomain.com/* (replace with your domain)
    • Zone: Select your domain
  4. Add the second route:

    • Route: www.yourdomain.com/*
    • Zone: Select your domain
  5. Ensure both routes show “Active” status

Step Four: Configure WordPress to Receive Real IP

In your WordPress website’s wp-config.php file, add the following code before the line require_once(ABSPATH . 'wp-settings.php');:

/**
 * Cloudflare Real IP Restoration
 */
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
    $_SERVER['HTTP_X_FORWARDED_FOR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
} elseif (isset($_SERVER['HTTP_X_REAL_IP'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_REAL_IP'];
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $forwardedIPs = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
    $_SERVER['REMOTE_ADDR'] = trim($forwardedIPs[0]);
}

if (isset($_SERVER['HTTP_CF_IPCOUNTRY'])) {
    define('VISITOR_COUNTRY', $_SERVER['HTTP_CF_IPCOUNTRY']);
}
if (isset($_SERVER['HTTP_X_COUNTRY'])) {
    define('VISITOR_COUNTRY_WORKER', $_SERVER['HTTP_X_COUNTRY']);
}

Step Five: Clear Cache

  1. Return to Cloudflare Dashboard
  2. Select your domain
  3. Choose “Caching” → “Configuration” from the left menu
  4. Click the “Purge Everything” button
  5. Confirm to clear all cache
  6. Wait 2-3 minutes for the Worker to propagate across global nodes

How to Verify the Worker is Functioning Correctly?

Method One: Command Line Testing

Run the following command in your terminal or command prompt:

curl -sI https://www.yourdomain.com/ | grep -i "x-"

Under normal circumstances, you should see the following response headers:

x-worker-status: active
x-visitor-ip: Your real IP address
x-visitor-country: CN
x-real-ip: Your real IP address
x-forwarded-for: Your real IP address
x-ad-optimized: no

Method Two: Create a Test Page

Create a file named worker-test.php in your website’s root directory with the following content:

<?php
header('Content-Type: text/plain; charset=utf-8');

echo "=== Cloudflare Worker Status Detection ===\n\n";

$checks = [
    'CF-Ray' => $_SERVER['HTTP_CF_RAY'] ?? null,
    'CF-Connecting-IP' => $_SERVER['HTTP_CF_CONNECTING_IP'] ?? null,
    'CF-IPCountry' => $_SERVER['HTTP_CF_IPCOUNTRY'] ?? null,
    'X-Real-IP' => $_SERVER['HTTP_X_REAL_IP'] ?? null,
    'X-Forwarded-For' => $_SERVER['HTTP_X_FORWARDED_FOR'] ?? null,
    'X-Country' => $_SERVER['HTTP_X_COUNTRY'] ?? null,
    'REMOTE_ADDR' => $_SERVER['REMOTE_ADDR'] ?? null,
];

foreach ($checks as $key => $value) {
    $status = $value ? '✅' : '❌';
    echo "$status $key: " . ($value ?: 'Not detected') . "\n";
}

echo "\n=== Result ===\n";
if ($checks['CF-Ray'] && $checks['X-Real-IP']) {
    echo "🎉 Worker is running perfectly! Real IP has been passed!\n";
} elseif ($checks['CF-Ray']) {
    echo "⚠️ Traffic passes through Cloudflare, but Worker hasn't added custom headers\n";
} else {
    echo "❌ Traffic is not passing through Cloudflare\n";
}
?>

Visit https://www.yourdomain.com/worker-test.php. If it displays “Worker is running perfectly,” the configuration is successful.

Method Three: Check Browser Developer Tools

  1. Open your website
  2. Press F12 to open developer tools
  3. Switch to the “Network” tab
  4. Refresh the page (Ctrl+F5)
  5. Click on the first request (usually the website homepage)
  6. Check the “Response Headers” section

You should see custom response headers like x-worker-status: active and x-visitor-ip.

Core Functionality Analysis of Worker Code

Real IP Transmission Mechanism

The Worker reads the visitor’s real IP address from the CF-Connecting-IP header provided by Cloudflare, then adds this information to multiple standard HTTP headers:

  • X-Real-IP: Custom header directly containing the real IP
  • X-Forwarded-For: Standard proxy forwarding header
  • X-Original-IP: Backup real IP information
  • X-Country: Visitor’s country code

This multi-layered approach ensures WordPress, Google Ads, and other services can accurately obtain visitor information.

Intelligent Cache Control

The Worker automatically adjusts caching strategies based on request type:

「Content Not Cached」:

  • Google Ads related scripts and requests
  • WordPress admin pages (/wp-admin, /wp-login.php)
  • REST API endpoints (/wp-json/)
  • POST requests (form submissions, AJAX)
  • Requests from logged-in users
  • Text files like .txt

「Normally Cached Content」:

  • Static resources (CSS, JavaScript, images)
  • Frontend pages accessed by non-logged-in users
  • HTML pages

This strategy ensures real-time performance for ads and admin areas while fully leveraging CDN acceleration advantages.

Request Type Identification

The Worker identifies different request types through the following methods:

「Ad Request Identification」: Checks if the URL contains keywords like adsbygoogle, googlesyndication, doubleclick.

「Admin Request Identification」: Checks if the path contains WordPress admin addresses like /wp-admin, /wp-login.php.

「User Login Status」: Checks if cookies contain the wordpress_logged_in identifier.

「Request Method」: Identifies different HTTP methods like GET, POST.

Expected Results and Improvement Timeline

Immediate Effects

  • Worker takes effect across global edge nodes 2-3 minutes after deployment
  • Real IP information immediately begins being passed to the origin server
  • WordPress admin and ad requests are no longer cached

Improvements After 24-48 Hours

Google Ads system requires time to re-identify and analyze your traffic quality. Typically, significant improvements are visible after 24-48 hours:

「Impressions」: Increase from the original 285 to 500-800 impressions, representing approximately 100-200% growth. This occurs because Google can now accurately identify visitor locations and serve more targeted ads.

「Cost Per Thousand Impressions (CPM)」: Increase from 0.50-$2.00, representing 10-40 times growth. Advertisers from high-value regions can now properly bid and compete.

「Click-Through Rate (CTR)」: Increase from 0.08% to 0.3-1.0%, representing 4-12 times growth. Ads become more relevant, making users more likely to click.

「Impression Rate」: Increase from 23% to 60-80%. More page views successfully trigger ad impressions.

Long-Term Stable Results

After one week, Google Ads fully adapts to the new traffic characteristics, and revenue should recover to pre-Cloudflare levels or even better. This is because you now enjoy both Cloudflare’s speed advantages and maintain precise ad targeting capabilities.

Common Troubleshooting Issues

Issue One: Worker Has No Effect After Deployment

「Check Routes Configuration」: Ensure you’ve added correct routing rules in Worker’s Triggers → Routes section, formatted as yourdomain.com/* and www.yourdomain.com/*, with status showing as Active.

「Check DNS Proxy Status」: In Cloudflare’s DNS → Records page, ensure the A record or CNAME record’s cloud icon is orange (Proxied), not gray (DNS only). A gray cloud indicates traffic doesn’t pass through Cloudflare, preventing Worker from functioning.

「Clear Cache」: After deploying the Worker, you must clear Cloudflare’s cache; otherwise, it will continue returning old cached content.

Issue Two: Cannot See X-Real-IP Response Header

「Confirm Worker Code is Complete」: Check if the code contains the line headers.set('X-Real-IP', realIP), ensuring there are no copy-paste errors.

「Wait for Propagation Time」: Global Worker deployment takes 2-3 minutes; don’t test immediately.

「Test Using Incognito Mode」: Browser cache may affect test results; use incognito mode or clear browser cache before testing.

Issue Three: Ads Still Display Abnormally

「Check WordPress Configuration」: Confirm the IP restoration code in wp-config.php has been correctly added, positioned before require_once.

「Review AdSense Dashboard」: Log into Google AdSense dashboard to check for “invalid traffic” or other warning messages.

「Check Traffic Sources」: Use Google Analytics or other tools to view traffic geographic distribution, confirming visitor country codes are correct.

「Allow Sufficient Time」: Google Ads needs 24-48 hours to reassess traffic quality; don’t expect immediate improvements.

Issue Four: Website Speed Decreases

「Check Cache Configuration」: Confirm the cacheTtl parameter in Worker code is set correctly; regular pages should use 3600 (1 hour) cache.

「Optimize Worker Code」: If Worker logic is too complex, it may affect response speed. Use a simplified version of Worker code, keeping only core functionality.

「Monitor Worker Performance」: Check execution time and success rate in Cloudflare Dashboard’s Workers & Pages → Your Worker → Metrics.

Additional Advantages of Workers

WordPress Admin Security Protection

The Worker code includes special handling for WordPress admin paths, ensuring these pages aren’t cached so administrators always see the latest content. Additionally, POST requests and logged-in user requests aren’t cached, preventing sensitive information leakage.

E-commerce Website Support

If your website uses e-commerce plugins like WooCommerce, the Worker has implemented no-cache strategies for shopping cart (/cart/), checkout pages (/checkout/), user accounts (/my-account/), and other dynamic pages, ensuring the shopping process functions properly.

Flexible Extensibility

The Worker code uses modular design, allowing you to easily add more features as needed:

  • Add more non-cacheable file types (.log, .xml, .json, etc.)
  • Add more paths requiring protection
  • Execute different logic based on visitor country or IP
  • Add custom security rules

Cost-Effectiveness

Cloudflare Workers’ free plan provides 100,000 requests per day, completely sufficient for small to medium-sized websites. Beyond that, the paid rate is $0.50 per million requests—extremely cost-effective.

In-Depth Understanding of Technical Principles

Cloudflare Edge Network Architecture

Cloudflare operates over 300 data centers globally, forming a massive edge network. When users access your website, requests are routed to the nearest Cloudflare node rather than directly connecting to your origin server.

Workers run on these edge nodes, completing processing before requests reach the origin server. This architecture’s advantages include:

「Low Latency」: Code executes at nodes closest to users, ensuring fast response times.

「High Availability」: Even if the origin server goes down, Workers can still return cached content or error pages.

「Reduced Server Load」: Many requests are processed at edge nodes, reducing pressure on the origin server.

The Role of HTTP Headers

HTTP headers are crucial components of the HTTP protocol, containing metadata about requests and responses. Common request headers include:

  • User-Agent: Client browser and operating system information
  • Cookie: Session information stored on the client
  • Referer: URL of the referring page
  • Accept-Language: Languages accepted by the client

Workers add custom HTTP headers to pass additional information. These headers are invisible to users but can be read and used by server-side applications.

How Google Ads Works

Google Ads relies on various signals to determine which ads to display:

「Geographic Location」: Advertisers can configure ads to display only to users in specific countries, regions, or even cities.

「User Interests」: By analyzing user browsing history and behavior, Google builds detailed interest profiles.

「Contextual Relevance」: Ad content automatically matches webpage content.

「Bidding System」: Multiple advertisers bid simultaneously; the ad with the highest bid and best quality score wins.

When Cloudflare replaces the real IP, geographic location information becomes incorrect, user profiles cannot be established, advertisers cannot properly target, bidding fails, and ultimately only low-value generic ads can be displayed.

Implementation Recommendations and Best Practices

Pre-Deployment Preparation

「Backup Existing Configuration」: Before modifying any configuration, back up wp-config.php and other critical files.

「Choose Appropriate Timing」: Consider deploying during low-traffic periods (such as early morning) to minimize user impact.

「Prepare Testing Tools」: Have test pages and command-line tools ready to quickly verify successful configuration.

Post-Deployment Monitoring

「Continuously Observe AdSense Data」: Check AdSense dashboard daily for key metrics like impressions, CPM, and CTR, recording trend changes.

「Monitor Website Performance」: Use tools like Google PageSpeed Insights and GTmetrix to monitor website loading speed, ensuring the Worker hasn’t affected performance.

「Review Error Logs」: Regularly check Cloudflare’s Worker logs and WordPress error logs to promptly identify issues.

Optimization Recommendations

「Set Appropriate Cache Times」: Adjust the cacheTtl parameter based on content update frequency. Frequently updated content should use shorter cache times (like 1800 seconds), while static content can use longer cache times (like 86400 seconds).

「Combine with Page Rules」: Cloudflare’s Page Rules can set more granular caching strategies for specific pages, working better in combination with Workers.

「Regularly Update Code」: As WordPress and plugins update, you may need to add new no-cache paths. Regularly review and update the path list in Worker code.

Conclusion

The drop in Google Ads revenue after implementing Cloudflare CDN is a common but perfectly solvable problem. By deploying Cloudflare Workers, we can enjoy CDN acceleration advantages while maintaining accurate visitor information identification by ad systems.

The core function of Workers is to pass real IP addresses and geographic location information while implementing differentiated caching strategies for special content like ad requests and WordPress admin areas. The entire deployment process takes only 15-20 minutes, requires no modifications to core website code, and carries minimal risk.

After deployment, significant improvement effects are typically visible within 24-48 hours. Impressions, CPM, and click-through rates all increase substantially, and website ad revenue can recover to pre-CDN levels or even better.

This solution applies not only to Google AdSense but also to other advertising networks, statistical analysis tools, and security protection systems that rely on accurate geographic location information. It represents a worthwhile optimization solution for all websites using Cloudflare to implement.