1. Exceeding 512 files in the ZIP

Google caps a playable ZIP at 512 files, on top of a separate 5 MB size limit — and the two are unrelated, which is exactly why this one catches people off guard. A ZIP can sit comfortably under 5 MB and still fail on file count alone. It happens routinely with Unity exports, since a build that bundles its own runtime, individual texture files, and per-clip audio assets can rack up file count fast without the total byte size looking anywhere near the ceiling.

Fix: count the files in the archive before you upload, not after rejection. Atlas textures where you can, bundle audio into fewer clips, and strip anything the build doesn't actually need at runtime. See the 512-file limit explained for where the count usually comes from and how to get under it reliably.

2. Missing or broken clickTag

Google's click-through model is a clickTag variable exited through Google's own hosted ExitApi.exit() script — not interchangeable with the MRAID mraid.open() other networks use, or Meta's FbPlayableAd.onCTAClick(). A playable with no clickTag defined, or one whose CTA never actually calls ExitApi.exit(), has no functioning click-through from Google's point of view — even if the button renders and looks clickable.

Fix: confirm clickTag is defined and every CTA path — including any end-card or replay-then-install flow — actually invokes ExitApi.exit() with it. A broken exit call doesn't throw an error, it just never converts, and a casual local test where you're not clicking through won't catch it.

3. Referencing assets outside Google's allow-list

Google is more permissive here than most networks — local relative paths inside the ZIP are fine, no base64 required. But anything hosted externally has to be on Google's specific short list: its own exit API script, Google Fonts, or Google-hosted jQuery/CreateJS/GreenSock. A CDN font, a third-party analytics snippet, or any other externally pulled library is not on that list, and referencing it puts the whole upload at risk even though it renders fine for you locally.

Fix: audit every external URL in the build, including anything a pipeline injects automatically. If it's not on Google's three-item list, pull it into the ZIP as a local asset or drop it — one stray external reference is enough to fail intake.

4. Missing orientation meta tag

Google requires an explicit orientation declaration in the document head. Generic HTML5 exports — including a raw Unity Playworks/Luna export — aren't built with Google's spec in mind by default and commonly leave this out, because a browser renders the creative fine either way and nothing about local testing surfaces the gap.

Fix: add the orientation meta tag declaring the creative's intended device orientation before packaging. It's easy to forget precisely because skipping it produces no visible symptom until Google's upload check runs.

5. Missing DOCTYPE or malformed HTML structure

Google checks that the entry file — index.html at the root of the archive — has a valid <!DOCTYPE> declaration and properly opens <html> and <body>. This is a purely structural check, independent of what the creative does once it loads. A missing DOCTYPE, or malformed HTML/body tags, fails here regardless of how correct the game logic and asset packaging are.

Fix: validate the entry file's markup directly rather than trusting that "it renders in Chrome" means it's structurally sound — browsers are forgiving about malformed HTML in ways Google's upload check isn't.

6. Unmuted autoplay audio

Google requires creatives to stay muted until the user has interacted with them. Standalone-app behavior — a sound sting the moment the game loads — is normal in an app context, and violates this the instant it's dropped into a Google Ads placement unmodified, since the creative starts playing sound in front of a user who never opted in.

Fix: gate all audio playback behind the first user interaction rather than firing it on load. It's a one-line change in most builds, but easy to miss if the export was built and tested as a standalone game rather than as an ad creative.

Worth knowing: none of the six reasons above are about whether your game is fun or your art looks good — they're mechanical packaging checks, and Google's automation enforces every one the same way regardless of how strong the creative is otherwise. For the complete reference, see Google Playable Ads: requirements, formats & common errors.

Catching these before you submit

All six categories above are checkable before a ZIP reaches Google's upload flow — file count, clickTag wiring, external references, orientation meta, and DOCTYPE/html/body structure are all verifiable properties of the package itself. Running your build through PlayableKit's free Playable Ad Validator checks exactly these things against Google's spec — entry file, HTML structure, orientation meta, clickTag/ExitApi wiring, and external references outside the allow-list — for free, no signup, before you spend a review cycle finding out the hard way.

If you're adapting a Unity Playworks/Luna export by hand for Google specifically, PlayableKit automates the clickTag/ExitApi wiring, orientation meta tag, muted-audio gating, and DOCTYPE/html/body structure directly from your source build, then checks the result against the 5 MB and 512-file limits before zipping it. See pricing for what's included on each plan.