ReTarget.gg
Integrate

Geo-blocking widget

Full-page overlay that shows sponsored offers only to visitors outside your service area. Install in two minutes, CMS-agnostic.

4 min readReviewed Apr 27, 2026

The geo-blocking widget renders a full-screen overlay of sponsored offers only to visitors whose country or region falls outside the rule you set on your website. It's the right fit when your core product is regulated or region-locked (iGaming, finance, streaming catalogues) and you want to turn otherwise-declined traffic into revenue.

Public key + website key required

Before you start

You'll need a public key (pk_…) and a website key (web_…) from the dashboard: Websites → [Your site]. Both are per-website and safe to expose in client-side HTML: the widget validates the page's origin against the domain you registered.

How it works

  1. Script loads, decision runs

    The <script> tag is async: it never blocks rendering. On load it calls GET /v1/decision with your public key, website key, and the visitor's country (resolved server-side from the client IP).

  2. Allowed → pass through

    If the visitor falls on the allowed side of your geo rule, nothing renders. The script fires one POST /v1/events/snippet-ping and exits. No visible DOM.

  3. Blocked → overlay appears

    If the visitor is on the blocked side, the widget creates #retarget-root, fetches eligible offers for their country, and renders a full-screen card layout.

  4. Clicks attribute via redirect

    Every click routes through api.retarget.gg/v1/r?… so attribution, fraud signals, and publisher revenue land in your dashboard.

Install

The simplest, universal form is a single guarded <script> block that works on any host: static sites, SPAs, GTM, Cloudflare Zaraz, anywhere.

HTML
<script>
(function () {
  if (document.querySelector('script[data-website="YOUR_WEBSITE_KEY"]')) return;
  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-api', 'https://api.retarget.gg');
  (document.head || document.documentElement).appendChild(s);
})();
</script>
Next.js
// app/layout.tsx
import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
  <html lang="en">
    <body>
      {children}
      <Script
        src="https://cdn.retarget.gg/widget.js"
        data-pub="YOUR_PUBLIC_KEY"
        data-website="YOUR_WEBSITE_KEY"
        strategy="afterInteractive"
      />
    </body>
  </html>
);
}
GTM / Zaraz
<!-- Custom HTML tag, trigger: All Pages -->
<script>
(function () {
  if (document.querySelector('script[data-website="YOUR_WEBSITE_KEY"]')) return;
  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-api', 'https://api.retarget.gg');
  (document.head || document.documentElement).appendChild(s);
})();
</script>

Origin must match your registered domain

The widget refuses to render if the page's Origin doesn't match the domain you registered on the website. If you serve the same site on staging or a preview host, either add the staging hostname as a second website (with its own keys) or use data-api to point at a staging API.

Attributes

AttributeRequiredPurpose
data-pubThe website's public key. Starts with pk_.
data-websiteThe website key. Starts with web_.
data-api:Override the API base URL. Defaults to https://api.retarget.gg. Use for staging.
data-dev-country:Force a country (e.g. DE) regardless of IP. Only honored on localhost or when data-allow-localhost is set; ignored on arbitrary production hosts.
data-dev-region:Force a region (e.g. BY for Bavaria). Same localhost-only constraint.
data-allow-localhost:Treat the current host as "localhost" for dev-override purposes (useful when testing on a tunnelled hostname like *.ngrok.io).
data-comments="false":Mute the script's console.log diagnostics. Purely a logging toggle.
data-debug:Force the widget into verbose debug mode (same effect as localhost).

Iframe / geo-gate setups

If you already use a third-party geo gate (Cloudflare Access, custom middleware, iframe sandboxing) that embeds your page inside an iframe for blocked traffic, point the blocked URL to a page on your domain that loads this widget: typically your homepage or a dedicated /blocked route. The script behaves identically inside the iframe.

Same keys, any surface

widget.js and widget-section.js share the same public key and website key. Embed them on the same page or swap between them without changes in the dashboard.

Verify the install

  1. Reload your page from an allowed location

    Nothing should appear. Open DevTools → Network and confirm the GET /v1/decision call returns { "allowed": true }. A POST /v1/events/snippet-ping will follow it with a 204 No Content.

  2. Simulate a blocked visit (local dev)

    While developing on localhost, add data-dev-country="DE" (or any country on your blocked side) to the script tag and reload. The overlay should appear.

  3. Check analytics

    The website's Analytics tab shows the decision, impression, and click events after they flush. If nothing appears, jump to the Debugging guide.

Performance

  • Single async script. Never blocks first paint.
  • The decision request is tiny (GET /v1/decision) and doesn't need any payload beyond the query string.
  • Allowed visitors: one request out, nothing rendered. Blocked visitors: one decision call, one offers call, then render.
  • The server responds with Cache-Control: no-store: decisions are per-request. Don't put a CDN cache in front of api.retarget.gg.

Need help with setup?

Send us your website stack, target regions, and whether you are installing Geo Popup or Decline Popup.

Geo-blocking widget | Docs | ReTarget.gg