AppLovin's actual requirements

These are AppLovin's packaging rules as PlayableKit implements them — not a paraphrase, the literal spec its build pipeline validates against before it will call a creative done:

  • Single file, one entry point. The whole ad is one .html file — no ZIP, no companion assets sitting next to it. AppLovin's spec calls for exactly one file.
  • 5 MB maximum. The entire file, including every embedded image, sound, and script, has to fit under 5 MB. There's no separate "assets" allowance — it's all one file, one limit.
  • MRAID 2.0 required. AppLovin's rendering surface talks to the creative through the MRAID (Mobile Rich Media Ad Interface Definitions) 2.0 API. The ad has to implement it, not some other network's click/SDK convention.
  • Both orientations supported. The creative needs to render correctly whether the device is held in portrait or landscape.
  • Zero external requests. External JS, external CSS, externally-hosted images or fonts, and any runtime network call are all prohibited outright. Every resource has to already be inside the HTML file when it's submitted.
  • The CTA calls mraid.open(url). That's the click-through mechanism AppLovin's SDK expects — not a bare window.open, not a clickTag variable, not another network's install callback.
  • No auto-click, no auto-play audio. The creative can't simulate a click on its own, and can't start playing sound before the user has actually interacted with the ad.
  • Wait for MRAID ready. The ad must not call any MRAID API, and shouldn't make layout decisions that depend on viewport info, until MRAID itself has signaled it's ready.
RequirementWhat AppLovin checks
File formatSingle self-contained .html file (no ZIP)
Size cap5 MB, all resources included
Ad interfaceMRAID 2.0
OrientationMust render in both portrait and landscape
External requestsProhibited — JS, CSS, images, fonts, network calls all inline
Click-throughmraid.open(url)
Audio / interactionNo auto-play audio or auto-click before user interaction
MRAID timingMust wait for MRAID ready before API calls or layout decisions

Why a raw Playworks/Luna export usually fails this

Playworks/Luna builds a genuinely working playable and exports it as a ZIP (typically under ProjectRoot\LunaTemp\stage4\create-hub). That export runs fine in a browser — it just wasn't built with AppLovin's specific rules in mind, and the two most common rejection causes both trace back to the same root cause: the export assumes it's allowed to load things after the page opens.

1. Assets referenced by relative path instead of embedded

A typical Luna export references its images, audio, and sometimes fonts with ordinary relative paths — src="assets/hero.png", an @font-face pointing at a local .woff2, a background sprite pulled in via CSS. That's completely normal for a multi-file export, and it's exactly what AppLovin's "single self-contained file, no external requests" rule prohibits. The moment AppLovin's renderer opens the HTML in isolation with no sibling files present, every one of those relative-path assets returns nothing, and the creative either fails validation outright or renders broken. It doesn't matter that the ZIP looked complete on your machine — AppLovin never sees the ZIP, it sees one HTML file.

2. MRAID called before it's ready

The other common failure is timing, not encoding. It's natural to write mraid.open(url) straight into a button's click handler, or to size the canvas off mraid.getMaxSize() as soon as the script loads — both work fine in a quick browser test, because the browser doesn't care whether an MRAID container actually exists yet. Inside AppLovin's real rendering surface, though, the MRAID bridge isn't guaranteed to be ready the instant the page's scripts run. A raw export that calls the API immediately, instead of waiting for the mraidviewable/ready state, works in local testing and then fails or misbehaves in the actual ad placement — which is a frustrating class of bug to chase down after the fact, because it doesn't reproduce outside AppLovin's own environment.

Worth knowing: both of these are exactly the kind of structural problem that's invisible until you actually submit to AppLovin. PlayableKit's free Playable Ad Validator checks a raw export for missing entry files, unembedded assets, and broken inline scripts before you spend a review cycle finding out the hard way.

How PlayableKit handles both

Upload the same Playworks/Luna export ZIP you already have, select AppLovin as a target, and PlayableKit produces the applovin.html file AppLovin's spec expects — with both problems above resolved automatically rather than left for you to hand-fix.

  • Full asset embedding. Every image, audio clip, and font the export references gets walked, read, and re-encoded as base64 or base122 directly into the HTML — not linked, not left as a relative path. Nothing in the finished file points outside itself, which is what actually satisfies "no external requests" rather than just avoiding an obvious <script src="http...">".
  • Proper MRAID-ready gating. PlayableKit injects an adapter script that wires the CTA to mraid.open(url), but wraps every MRAID call and every layout decision behind a listener for the MRAID ready state — so the same logic that looked fine in a browser test behaves correctly once it's actually running inside AppLovin's container.
  • Size and orientation handled together. Because embedding happens automatically, PlayableKit can tell you immediately if the resulting single file is over the 5 MB cap — instead of you discovering it after packaging by hand — and the build is checked against both orientations rather than just the one you happened to test in.
  • No auto-play, no auto-click, by construction. The injected adapter never fires the CTA on its own and never starts audio before an actual user interaction, so that rule isn't something you have to separately remember to enforce in your own build.
StepDoing it by hand for AppLovinWith PlayableKit
Asset embeddingManually convert every image/audio/font reference to base64 and rewire the pathsAutomatic base64/base122 embedding, whole export
MRAID wiringHand-write mraid.open(url) and guess at ready timingAdapter script gated on MRAID ready, applied automatically
Size checkZip it up, submit, wait for AppLovin's review to flag itFree size checker before you ever submit
Structural sanity checkDebug a rejection with no detail on what failedFree validator flags missing files/broken scripts up front

Pricing

AppLovin is included on every paid PlayableKit plan. Starter is $400/mo for 50 builds a month across Google Ads, Meta, AppLovin, and Unity Ads. Studio is $560/mo for 100 builds across all supported networks. Scale is $800/mo for 300 builds and 2 seats across all networks. Enterprise pricing is custom for teams that need volume beyond that. Full detail is on the pricing page.

If you're also shipping to other networks

If AppLovin isn't your only target, the same source Playworks/Luna export needs different handling for each network — Google Ads wants a ZIP with a clickTag and its own ExitApi script, Meta wants a single file with FbPlayableAd.onCTAClick() and no MRAID at all. See exporting to Google Ads and exporting to Meta for the specifics on each, or the broader Unity Playworks/Luna alternative overview for how PlayableKit handles every network from one build.