Export format
Google Display HTML5, built for a website destination.
Google Display buys website traffic by default, which makes it the natural home for a playable from a brand with no app. The bundle rules are strict but small: a declared slot size, a clickTag exit, everything inlined, and a static backup image alongside.
Below is the exact shell we wrap every Google Display build in. The generated playable drops into the stage, and the click plumbing stays untouched so the validator has nothing to argue with.
The spec
Google Display HTML5
- Delivery
- ZIP containing index.html plus any assets, uploaded in Google Ads or DV360.
- Size
- Fixed slot size, declared in a meta ad.size tag.
- Weight
- 150 KB initial load, 2.2 MB polite load, no more than 10 files.
- Click through
- A global clickTag variable, declared before use and opened only inside a user gesture.
- External requests
- None at load. Everything is inlined; Google's validator flags remote assets.
- Backup image
- A static JPG or PNG at the same size is required alongside the bundle.
- Animation
- Loops must stop within 30 seconds; the end card stays on screen.
- Destination
- Any website. This is standard display inventory, so no app listing is needed.
The template
playable_google_display_300x250.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">
<!-- Required by Google Ads / Display & Video 360 HTML5 validation. -->
<meta name="ad.size" content="width=300,height=250">
<title>Playable — 300x250</title>
<style>
html, body { margin: 0; padding: 0; width: 300px; height: 250px; overflow: hidden; background: #0f0f12; }
* { -webkit-tap-highlight-color: transparent; box-sizing: border-box; }
#stage { position: relative; width: 300px; height: 250px; }
#exit { position: absolute; inset: 0; z-index: 9999; cursor: pointer; background: transparent; border: 0; padding: 0; }
</style>
</head>
<body>
<!-- Google requires a global clickTag variable, assigned before any use. -->
<script type="text/javascript">
var clickTag = "";
</script>
<div id="stage">
<!-- PLAYABLE BODY: generated markup, CSS and JS are inlined here. -->
<!-- No external requests: images are data URIs, fonts are system stacks. -->
<!-- Full-unit exit surface. Keep it above the playable only on the end card. -->
<button id="exit" type="button" aria-label="Visit site" hidden></button>
</div>
<script type="text/javascript">
// Reveal the exit surface when the playable reaches its end card.
window.showEndCard = function () {
document.getElementById("exit").hidden = false;
};
// Single exit path. Google rewrites clickTag at serve time; window.open
// must run inside the user gesture or the pop-up is blocked.
function fireCTA() {
if (clickTag) {
window.open(clickTag, "_blank");
}
}
document.getElementById("exit").addEventListener("click", fireCTA, false);
// Polite load: signal readiness only once everything is parsed.
if (document.readyState === "complete") {
window.adReady = true;
} else {
window.addEventListener("load", function () { window.adReady = true; }, false);
}
</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.