Why local testing passes but Google's preview doesn't
When you open an export directly in a browser or serve it from a local static server, the browser is forgiving. It'll patch up a slightly malformed <!doctype>, tolerate a missing <body> tag, and generally do its best to render something. Google's ad preview renderer, running your creative inside its own sandboxed iframe as part of the review pipeline, is stricter — it expects the document to be well-formed before it treats it as a valid HTML5 asset at all. A structural issue that a normal browser silently fixes can be exactly the thing that makes Google's preview render nothing.
Real causes, grounded in Google's actual spec
1. Malformed doctype or missing html/body structure
Google's HTML5 spec for playables requires a proper <!doctype html> declaration and a complete <html>/<body> structure — not just a chunk of markup that happens to render. If a build tool strips the doctype during minification, or an inlining step accidentally duplicates or drops the opening <html> or <body> tag, the file can still be readable by a browser's error-correcting parser while failing Google's stricter check. This is one of the most common causes of a preview that shows nothing with zero console output, because there's no runtime error to see — the file just never gets treated as valid.
2. Entry file not at the expected root location
Google expects index.html at the root of the ZIP — not nested inside a subfolder, and not under a different name. If your Playworks/Luna export ends up zipped with an extra wrapper folder around it (a common side effect of how some archive tools compress a directory), the ZIP looks fine when you unzip and open the file manually, because you naturally navigate into the subfolder first. Google's preview tool doesn't do that navigation for you — it looks for index.html at the top level, doesn't find it, and shows a blank preview instead of a "file not found" message.
3. A JS error thrown before anything renders
If an inline <script> block throws early — a syntax error, a reference to something not yet defined, a cache lookup that fails silently — the rest of the page's rendering logic never runs, and you get a blank canvas. This is easy to miss locally if your browser's console happened to be closed, or if the error only surfaces under Google's iframe sandboxing (which is more restrictive about certain APIs and cross-frame calls than an unsandboxed local test). The fix is always the same regardless of where the error came from: find and fix the actual exception, since a preview tool showing "blank" is really just "JavaScript never got to the point of drawing anything."
4. Orientation meta mismatch causing a sizing issue
Google's spec requires an orientation meta tag so its preview frame knows whether to render your creative in a portrait or landscape container. If that tag is missing, contradicts the actual layout the creative was built for, or wasn't updated after you changed the target orientation late in development, Google's preview can size the iframe incorrectly — which often looks like a blank or clipped screen rather than an obvious layout bug, because the canvas is being asked to draw into a viewport it wasn't expecting.
How to actually diagnose it
- Open the ZIP's
index.htmldirectly first, before touching Google's tools. Unzip it and confirmindex.htmlis sitting at the top level, not one folder down — and confirm it opens and plays with no console errors of its own. - Run the free Playable Ad Validator and check the inline-script-syntax result specifically. It parses every inline
<script>block in the export and reports a syntax error with detail if one exists — the same class of early failure that produces a blank Google preview with no visible error. - Check the doctype and html/body structure by eye if the validator comes back clean but the preview still fails. Confirm the file starts with
<!doctype html>on its own, followed by a single well-formed<html>element wrapping one<body>— not two, and not missing. - Confirm the orientation meta tag matches what the creative was actually built for. If the build supports only portrait but the meta tag (or Google's dropdown at upload) says otherwise, fix the mismatch rather than assuming the asset itself is broken.
How PlayableKit avoids this category of problem
This whole class of failure — technically uploadable, but silently blank in Google's own preview — is exactly what PlayableKit's structural checks target before a build ever ships. Its Google output pass enforces the doctype and html/body structure the spec requires (requiresDoctype, requiresHtmlBody), verifies the orientation meta tag is present and correct (requiresOrientationMeta), and confirms index.html lands at the ZIP's true root rather than inside a wrapper folder, per Google's entryFile expectation. The same inline-script-syntax check available in the free validator also runs as part of a full conversion, so a JS error that would otherwise only surface as a blank Google preview gets caught and reported before you upload at all. You can read the full breakdown of what a compliant Google build needs on the Google Ads playable ads page.