All essays
Engineering

Cloudflare Workers + an affiliate widget: the cleanest way to monetize geo-blocked traffic in 2026

If your stack already runs on Cloudflare, monetizing blocked traffic can be a five-line Worker — inject the ReTarget widget at the edge for out-of-region visitors only, save origin bandwidth, and stay eligibility-safe at auction time.

5 min readUpdated Jun 22, 2026
  • cloudflare workers affiliate
  • cloudflare geo block monetize
  • edge worker geo overlay
  • monetize cloudflare blocked traffic
  • workers affiliate monetization
  • HTMLRewriter widget
  • edge injection pattern
  • request.cf.country
On this page (13 sections)

Executive summary: Cloudflare's edge gives you request.cf.country before your origin renders. Pair it with an eligibility-aware overlay and you can monetize blocked traffic without origin round-trips for those visitors. Pattern: Worker checks region → injects ReTarget script via HTMLRewriter → auction API enforces license eligibility server-side. Sites at seven-figure blocked pageviews save measurable origin bandwidth.

Cloudflare's edge gives you everything needed to detect and act on geo-blocked traffic before the page fully renders. Combined with an eligibility-aware overlay like ReTarget.gg, you flip a per-region revenue line on without touching your origin application code.

This is the pattern we recommend for high-traffic iGaming and regulated publishers already on Cloudflare.


The 30-second mental model

Visitor
   │
   ▼
Cloudflare Edge (Worker)
   │
   ├─ In licensed region? ──YES──► Pass through to origin (unchanged)
   │
   └─ NO (blocked)
         │
         ├─ Pattern A: Pass to origin + client-side widget detects
         │
         └─ Pattern B: HTMLRewriter injects script at edge
                              │
                              ▼
                    ReTarget auction API
                    (eligibility check)
                              │
                              ▼
                    Overlay renders (or no-op)

Pattern A is the default install — simplest, works everywhere.

Pattern B saves origin bandwidth on every blocked impression. For sites doing seven-figure blocked pageviews monthly, that is measurable money and latency.


Why edge-side detection matters

You can ship the ReTarget script on every page and let the client-side widget detect blocked visitors. That works fine for most publishers.

Edge-side detection wins when:

ConcernClient-side onlyEdge injection
Script load on in-region visitors~14 KB every session0 KB — script only for blocked
Adblocker resistanceThird-party script fetchInline injection in origin HTML
Origin bandwidth for blocked geosFull page renderOptional: static shell only
Auction contextClient-detectedWorker can pass data-region, data-vertical
Implementation complexityLowMedium — test caching interactions

Rule of thumb: Under 50k blocked monthly pageviews, client-side is fine. Above 500k, edge injection pays for the engineering time in weeks.


The minimal Worker (Pattern B)

// worker.ts — deploy via Wrangler or Cloudflare dashboard
const RETARGET_SCRIPT = `
<script>
  (function () {
    var s = document.createElement("script");
    s.src = "https://cdn.retarget.gg/widget.js";
    s.async = true;
    s.setAttribute("data-pub", "YOUR_PUBLIC_KEY");
    s.setAttribute("data-website", "YOUR_WEBSITE_KEY");
    (document.head || document.documentElement).appendChild(s);
  })();
</script>`;
 
// Your licensed regions — align with Geo rules in dashboard
const ALLOWED = new Set(["GB", "DE", "CA", "IE", "NL", "MT"]);
 
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const country = request.cf?.country ?? "XX";
 
    // In-region: pass through untouched
    if (ALLOWED.has(country)) {
      return fetch(request);
    }
 
    // Blocked: fetch origin and inject widget
    const upstream = await fetch(request);
 
    // Only transform HTML responses
    const contentType = upstream.headers.get("content-type") ?? "";
    if (!contentType.includes("text/html")) {
      return upstream;
    }
 
    return new HTMLRewriter()
      .on("head", {
        element(element) {
          element.append(RETARGET_SCRIPT, { html: true });
        },
      })
      .transform(upstream);
  },
} satisfies ExportedHandler<Env>;

That is the core. Cloudflare gives you request.cf.country for free on every request. You check it against your licensed-region set. Only blocked visitors get the script injected. In-region visitors receive the unmodified origin response.

Keys: Get YOUR_PUBLIC_KEY and YOUR_WEBSITE_KEY from the dashboard. See Quickstart.


Enhanced Worker: pass auction context

Give the auction engine richer signals from the edge:

const RETARGET_SCRIPT = (country: string, colo: string) => `
<script>
  (function () {
    var s = document.createElement("script");
    s.src = "https://cdn.retarget.gg/widget.js";
    s.async = true;
    s.setAttribute("data-pub", "YOUR_PUBLIC_KEY");
    s.setAttribute("data-website", "YOUR_WEBSITE_KEY");
    s.setAttribute("data-region", "${country}");
    s.setAttribute("data-edge-colo", "${colo}");
    s.setAttribute("data-source", "cf-worker");
    (document.head || document.documentElement).appendChild(s);
  })();
</script>`;
 
export default {
  async fetch(request: Request): Promise<Response> {
    const country = request.cf?.country ?? "XX";
    const colo = request.cf?.colo ?? "unknown";
 
    if (ALLOWED.has(country)) {
      return fetch(request);
    }
 
    const upstream = await fetch(request);
    const script = RETARGET_SCRIPT(country, colo);
 
    return new HTMLRewriter()
      .on("head", {
        element(el) {
          el.append(script, { html: true });
        },
      })
      .transform(upstream);
  },
};

This helps reporting distinguish edge-injected impressions from client-side installs in Analytics.


Pattern C: skip origin entirely for blocked visitors

For maximum origin savings, serve a static blocked shell from the Worker without calling origin:

const BLOCKED_HTML = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>Service unavailable in your region</title>
  <!-- ReTarget script inline here -->
</head>
<body>
  <p>This service is not available in your region.</p>
</body>
</html>`;
 
export default {
  async fetch(request: Request): Promise<Response> {
    const country = request.cf?.country ?? "XX";
 
    if (ALLOWED.has(country)) {
      return fetch(request);
    }
 
    return new Response(BLOCKED_HTML, {
      headers: { "content-type": "text/html;charset=UTF-8" },
    });
  },
};

Tradeoff: You lose origin personalization for blocked visitors entirely. Good for hard geo-walls; bad if blocked visitors still need account-specific content.


Eligibility still happens at auction time

A common worry: if the Worker injects the script for any blocked visitor, won't unlicensed-region visitors see ineligible offers?

No. The eligibility engine runs server-side at auction time:

  1. Worker injects the script (dumb, fast).
  2. Script calls api.retarget.gg with visitor geo.
  3. API filters to advertisers licensed in that region.
  4. Auction runs among eligible offers only.
  5. If no eligible offer exists → overlay does not render.

Worst case: the API returns no offer and the visitor sees your blocked page without monetization. There is no scenario where an unlicensed advertiser wins in a regulated geo.


Caching gotchas (read before shipping)

HTMLRewriter and Cloudflare cache interact in non-obvious ways:

ScenarioRiskMitigation
Cache keyed only by URLIn-region visitor gets blocked-injected HTML from cacheVary cache on CF-IPCountry header
Cache-Control: public on originBlocked response cached for in-region usersSeparate cache keys or bypass cache for HTML
Workers Cache APIStale injection stateInclude country in cache key
CDN purgingOld script version servedVersion your Worker deployment

Test matrix before production:

  1. VPN to DE (in-region) → no script in HTML source
  2. VPN to BR (blocked) → script present in HTML source
  3. Switch VPN DE → BR on same browser → correct behavior after cache TTL
  4. Verify in-region conversion funnel unchanged

Deeper walkthrough: Cloudflare integration recipe.


Wrangler deployment checklist

# wrangler.toml
name = "retarget-geo-inject"
main = "src/worker.ts"
compatibility_date = "2024-01-01"
 
[vars]
# Do NOT put API secrets here — public keys only
RETARGET_PUB_KEY = "pk_live_..."
RETARGET_WEBSITE_KEY = "wk_live_..."
npx wrangler deploy
npx wrangler tail  # watch first 1,000 blocked requests
  • Route pattern covers all public HTML paths
  • ALLOWED set matches Geo rules in dashboard
  • Cache variation configured
  • Staging Worker tested with 3+ VPN geos
  • Analytics shows data-source=cf-worker impressions

When NOT to use this pattern

  • You do not already use Cloudflare. Do not migrate CDN for this alone. Client-side install is fine.
  • Aggressive edge caching without cache-key discipline. You will serve wrong HTML to wrong geos.
  • Heavy per-user dynamic origin content for blocked visitors. Pattern C will not work; Pattern A or B still calls origin.
  • Decline Popup triggers. KYC failures happen post-origin. Edge injection handles geo-block only; wire Decline Popup in your application layer.

Combining with Geotargetly or other routers

If Geotargetly runs redirect rules on the same page:

  1. Geotargetly evaluates redirects first (client-side or their own Worker).
  2. Cloudflare Worker injects ReTarget only for non-redirected, blocked visitors.
  3. No double-overlay if sequenced correctly.

See Geotargetly integration recipe.


Performance benchmarks (indicative)

From publishers who shipped Pattern B:

MetricBefore (client-side everywhere)After (edge injection)
Script bytes on in-region sessions~14 KB0 KB
Origin requests from blocked geos100%0–100% (depends on pattern)
Time to first overlay paint~800ms~400–600ms
Blocked session revenuebaseline±5% (auction identical)

Revenue should be neutral — the auction is the same. Savings are bandwidth, latency, and in-region page weight.


FAQ

Does this work with Cloudflare Zero Trust? Yes. Worker runs before access policies in most configurations. Test your specific Access rules.

What about EU visitors and GDPR? ReTarget's script loads only for blocked visitors. Pass no PII from Worker to script. Standard affiliate disclosure applies.

Can I use Workers KV for dynamic allowlists? Yes — store licensed regions in KV and update without redeploying Worker code.

Does HTMLRewriter work with Next.js / React SSR? Yes, on the HTML output. Test hydration — injected script in <head> should not break React.

What if request.cf.country is wrong? Rare but possible (VPN, corporate proxies). Auction API uses additional geo signals. Monitor no-offer rate per geo.


Want help wiring this for your stack? Contact the team with your Cloudflare zone and license map.

Ready to monetize blocked traffic?

Two-minute install, free for publishers. The network handles eligibility, advertiser demand, and payouts.