ReTarget.gg
Integrate

Widget integration reference

The complete map of embeds, attributes, and API URLs: everything the ReTarget.gg widgets do, cross-linked.

5 min readReviewed Apr 27, 2026

One script per surface, two required attributes, one API. This page is the single source of truth for every attribute, URL, and behavior across the widget family.

Public key + website key required

Scripts at a glance

ScriptDocUse case
widget.jsGeo-blocking widgetFull-page overlay when the visitor falls on the blocked side of your geo rule.
widget-section.jsSection widgetSponsored offers inside a container (mode=section on the decision API).
widget-decline.jsTrigger WidgetYour server triggers the overlay after a decline path (KYC, deposit, etc.).
iframeIframe fallbackThird-party popup/tag builders that only support iframes.

All three scripts are served from https://cdn.retarget.gg/ (static CDN). The overlay modes mount into #retarget-root: the script creates it on first render.

Required attributes

Every script tag needs exactly these:

  • data-pub: the website's public key (pk_…).
  • data-website: the website's website key (web_…).

Each website has its own pair. If you run multiple sites, each gets its own pk_ / web_ on its own dashboard page.

Optional attributes

AttributeScopePurpose
data-apiallOverride the API base URL. Defaults to https://api.retarget.gg. Use for staging.
data-comments="false"allMute the script's console.log diagnostics. Purely a logging toggle: does not hide any visible label.
data-debugallForce verbose debug logging (same effect as running on localhost).
data-dev-countryallForce a country (e.g. DE). Only honored on localhost or with data-allow-localhost.
data-dev-regionallForce a region (e.g. BY). Same localhost-only constraint.
data-allow-localhostallTreat the current host as "localhost" for dev-override purposes (useful for tunnels).
data-containersectionDefault retarget-ads. Accepts a single id: not a list.
data-max-adssectionCap the number of cards rendered. Default 6, hard cap 24.

Section mode also needs a container on the page: <div id="retarget-ads"></div>.

The "guarded loader" pattern below works everywhere: plain HTML, GTM, Cloudflare Zaraz, any tag manager. The querySelector guard prevents a double load when the tag fires twice on an SPA or GTM refire:

<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>

Geo-blocking flow (widget.js)

  1. Script loads

    Reads its data-* attributes and issues GET /v1/decision?pub=…&website=….

  2. Decision returns

    The API returns { allowed, requestId, country, region }. allowed=true → the script emits a POST /v1/events/snippet-ping and exits. allowed=false → the widget fetches offers.

  3. Offers render

    GET /v1/offers?website=…&requestId=…&country=… returns a ranked list. The widget creates #retarget-root and renders the full-screen overlay.

  4. Impressions and clicks

    The widget posts POST /v1/events/impression for each rendered card and POST /v1/events/click before navigating through GET /v1/r?t=… for attribution.

The page's Origin must match the domain registered on the website. Unknown origins get a 403 from /v1/decision with reason: "invalid_origin".

Section flow (widget-section.js)

Identical to geo-blocking with three differences:

  1. GET /v1/decision?mode=section so analytics differentiate inline from overlay.
  2. allowed=false renders cards into your container instead of creating an overlay.
  3. Card density is tuned for inline layouts (up to data-max-ads cards, default 6).

Same keys, same origin rules, same events.

Trigger Widget flow (widget-decline.js)

For "we're not proceeding" flows where you still want alternative offers, with you deciding when the overlay opens.

One-time setup in the dashboard: Websites → [Your site] → toggle Trigger Widget to reveal the integration secret.

  1. Browser: load widget-decline.js

    POST /v1/widget-decline/session?pub=…&website=… returns a sessionId and expiresAt (~15 min). The script sets window.__RETARGET_DECLINE_SESSION_ID and dispatches retarget:decline-session with detail: { sessionId }.

  2. Browser → your server

    Send the sessionId to your backend via whatever transport fits your app (cookie-auth'd fetch, signed JWT, etc.).

  3. Your server → trigger

    When ready, POST /v1/widget-decline/trigger with Authorization: Bearer <integration_secret> and { "sessionId": "..." }. Returns 200 with { "ok": true } (or { "ok": true, "alreadyTriggered": true } on a second call).

  4. Next poll sees status: ready → overlay renders

    The embed is polling GET /v1/widget-decline/session/{sessionId} every 2 seconds. On ready it fetches offers and renders.

Integration secret: server only

The integration secret is the only credential that can arm a Trigger Widget session. Keep it in server env vars or a secrets manager. Never in NEXT_PUBLIC_*, in git, or in client bundles.

API endpoints used by the widgets

The widgets call these on your behalf. You don't need to call them directly unless you're building custom integrations: but knowing what they do helps debug.

GET/v1/decisionauth: public
GET/v1/offersauth: public
POST/v1/events/impressionauth: public
POST/v1/events/clickauth: public
POST/v1/events/snippet-pingauth: public
GET/v1/rauth: public
POST/v1/widget-decline/sessionauth: public
GET/v1/widget-decline/session/:sessionIdauth: public
POST/v1/widget-decline/triggerauth: integration-secret

Full spec at /docs/api.

Browser events dispatched

Only the Trigger Widget currently dispatches a DOM event. The geo-blocking and section widgets do not emit custom events: if you want to forward widget activity to your own analytics stack, do it from your server via the events you receive in your dashboard, or subscribe to the API's webhook product (contact us).

EventWidgetdetail
retarget:decline-sessionwidget-decline.js{ sessionId: string }

Example:

window.addEventListener("retarget:decline-session", (ev) => {
  const { sessionId } = ev.detail;
  console.log("ReTarget.gg decline session", sessionId);
});

Origin and CORS

The widget's page Origin must match the domain registered on the website. The API enforces this on /v1/decision, /v1/offers, and /v1/widget-decline/*. Unknown origins get 403 Forbidden with reason: "invalid_origin".

Event endpoints (/v1/events/*) accept any origin: they're designed to be sendBeacon-friendly and CORS-safelisted (text/plain content type, no preflight).

Publisher app proxy (optional)

Instead of loading the script from https://retarget.gg/, you can proxy it through your own host (e.g. /widget.js mapped to https://cdn.retarget.gg/widget.js). When proxied, set the API base either via data-api on the script tag or by assigning window.RETARGET_API before the script loads (window.AFFILFINDER_API is still accepted as an alias).

Performance

  • Single async script per surface.
  • Allowed visitors: one /v1/decision call, one snippet-ping, nothing rendered.
  • Blocked visitors: decision + offers + events.
  • API responses set Cache-Control: no-store: decisions are per-request. Don't cache them in a CDN in front of api.retarget.gg.
  • widget.js respects standard async loading: it never blocks first paint.

Need help with setup?

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

Widget integration reference | Docs | ReTarget.gg