Export format

Programmatic HTML5, ready for any DSP or ad server.

Every exchange rewrites the click its own way, so the creative has to accept a click macro, keep clickTag as a fallback, and stay safe inside a cross-origin iframe. Do that once and the same file runs across Display & Video 360, The Trade Desk and a plain ad server.

This is the IAB shell we wrap programmatic builds in: inline assets only, no document.write, no top-level navigation, and a fixed stage that scales into whatever slot the exchange serves it into.

The spec

Programmatic HTML5 (IAB)

Delivery
ZIP with index.html at the root, uploaded to the DSP or ad server as an HTML5 creative.
Size
Any IAB slot; the stage is fixed and scaled by transform to fit.
Weight
Keep the compressed bundle under 200 KB where the exchange enforces IAB LEAN.
Click through
The exchange click macro is prepended to the landing URL, with clickTag kept as a fallback.
SSL
Everything is inline, so the creative is https-safe by construction.
Sandbox
No document.write, no top-level navigation, no cookies — safe inside a cross-origin iframe.
Sizing
The 320x480 stage scales into whatever slot the exchange serves.
Destination
Any website, tracked by the DSP's own click macro.

The template

playable_programmatic_320x480.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- IAB HTML5 display creative. Declare the slot size for the ad server. -->
<meta name="ad.size" content="width=320,height=480">
<title>Playable — 320x480</title>
<style>
  html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: #0f0f12; }
  * { -webkit-tap-highlight-color: transparent; box-sizing: border-box; }
  #stage { position: relative; width: 320px; height: 480px; margin: 0 auto; transform-origin: top center; }
  #exit { position: absolute; inset: 0; z-index: 9999; background: transparent; border: 0; padding: 0; cursor: pointer; }
</style>
</head>
<body>
  <script type="text/javascript">
    // Click macro. Most DSPs rewrite %%CLICK_URL_UNESC%% at serve time;
    // clickTag / clickTAG are read as a fallback by legacy ad servers.
    var CLICK_MACRO = "%%CLICK_URL_UNESC%%";
    var clickTag = "";
    var clickTAG = clickTag;
    var LANDING_URL = "https://example.com";
  </script>

  <div id="stage">
    <!-- PLAYABLE BODY: generated markup, CSS and JS are inlined here. -->
    <button id="exit" type="button" aria-label="Visit site" hidden></button>
  </div>

  <script type="text/javascript">
    function resolveClickUrl() {
      var macro = CLICK_MACRO.indexOf("%%") === 0 ? "" : CLICK_MACRO;
      var target = clickTag || clickTAG || LANDING_URL;
      return macro ? macro + encodeURIComponent(target) : target;
    }

    function fireCTA() {
      var url = resolveClickUrl();
      if (url) { window.open(url, "_blank"); }
    }

    document.getElementById("exit").addEventListener("click", fireCTA, false);

    window.showEndCard = function () {
      document.getElementById("exit").hidden = false;
    };

    // Fit a fixed 320x480 stage inside any slot the exchange serves it into.
    function scaleStage() {
      var stage = document.getElementById("stage");
      var scale = Math.min(window.innerWidth / 320, window.innerHeight / 480);
      stage.style.transform = "scale(" + scale + ")";
    }
    window.addEventListener("resize", scaleStage, false);
    window.addEventListener("orientationchange", scaleStage, false);
    scaleStage();
  </script>
</body>
</html>

How this fits the build

The studio generates one self-contained playable, then wraps it in the shell above: the click plumbing, the size declaration and the end-card exit surface are the parts a validator actually checks, and they are identical on every build.

Because this is display inventory rather than app-install inventory, the click can land on your website. No App Store or Google Play listing is required.

Compare this with the four ad networks →