Every technical playable ad spec you will read — Unity's, Vungle's, Chartboost's, ironSource's — assumes you already know what MRAID is. Almost none of them explain it. If you have been handed a rejection notice citing "MRAID compliance" and had to guess what that meant, this guide is the missing context. MRAID is the reason a single HTML file can behave correctly inside a dozen different apps, and understanding the three or four calls that matter will save you more review cycles than any design change.
MRAID in one paragraph
MRAID stands for Mobile Rich Media Ad Interface Definitions. It is a standard published by the IAB that defines a common JavaScript API between a rich-media ad and the app showing it. Your creative runs inside a webview owned by someone else's app. It cannot open a browser, resize itself, or know whether it is even on screen — the host app controls all of that. MRAID is the agreed vocabulary for asking. The ad calls a method, the host SDK implements it, and the same file works in every app that speaks the standard.
This is why playable ads are single self-contained HTML files rather than websites. A website assumes it owns the tab. A playable ad assumes nothing, and negotiates for everything through MRAID.
The four things that actually matter
The full spec is large. In practice, playable ads use a small corner of it, and getting these four right is most of what compliance means.
- mraid.open(url) — opens the store listing. This is the click. Never use window.open or window.location on an MRAID network; the host has to know a click happened, and a raw browser call bypasses it entirely.
- The ready event — the host tells you the MRAID bridge is available. Calling mraid.open before this fires is one of the most common silent failures, because the object exists but is not yet wired up.
- viewableChange and isViewable() — whether the ad is actually on screen. Start gameplay and audio when the ad becomes viewable, not when the file loads, or a chunk of your users will burn their first three seconds while the ad is still off screen.
- mraid.getState() — 'loading', 'default', 'expanded' or 'hidden'. Worth checking before assuming you can interact with anything.
The single most common rejection
A CTA wired to window.open instead of mraid.open. It works perfectly when you test the file in a desktop browser, and does nothing — or opens a dead webview — inside the network's SDK. Always test the exported file on a real device through the network's own preview tool, not just locally.
MRAID 2.0 vs 3.0 — which do you need?
Most network specs still ask for MRAID 2.0 compliance, and that is what playable ads realistically target. Version 2.0 introduced the pieces rich media needed: viewability events, storePicture, and a defined resize behaviour. Version 3.0 added measurement and viewability refinements aimed largely at brand advertising and third-party verification. For a playable ad whose job is to run a mini-game and then open a store listing, 2.0 covers everything you use. If a network asks for 3.0 it is generally asking for backwards-compatible behaviour rather than a different creative.
The networks that ignore MRAID entirely
This is the part the specs bury, and it matters more than the version number. Not every network uses mraid.open — three of the largest own the click destination themselves and take no URL at all.
- Google Ads uses ExitApi.exit() from its own exitapi.js, loaded from Google's domain — the one permitted external script.
- Meta (Facebook) uses FbPlayableAd.onCTAClick(), which takes no arguments. Meta decides the destination from the campaign, not from your creative.
- Mintegral uses window.install(), again with no URL.
- Unity, ironSource, AppLovin, Chartboost, Vungle, InMobi, Liftoff, Moloco and Pangle are MRAID-based and honour mraid.open with a URL you supply.
The practical consequence: on the three owned-exit networks, a per-button destination link or a dynamic click parameter cannot travel, because there is no URL for it to travel on. That is not a bug to route around, it is the network's contract. Any tool that claims dynamic click destinations work identically everywhere has not read these three SDKs.
Why the single-file rule exists
MRAID creatives are usually delivered as one inlined HTML document with every image, font and sound embedded, and no outward requests at runtime. Reviewers enforce this strictly. The reasoning is straightforward: the ad may be shown in an offline or poor-connectivity session, a remote fetch adds latency to a format measured in seconds, and an external URL is a security surface the host app cannot audit. Some networks want that single file; others want a ZIP laid out their way, occasionally down to which file must sit at the root. Both shapes still forbid runtime fetching.
Testing MRAID without an SDK
Open your exported file locally and MRAID will be undefined — that is expected, not a fault. A well-built playable falls back to window.open for local preview and uses mraid.open when the bridge exists. If your creative does nothing at all in a plain browser, you cannot QA it before upload, which is its own problem.
What this means for how you build
If you are hand-coding playables, budget real time for the per-network wiring: each SDK's click call, its ready and viewability handling, its packaging shape, and its size ceiling. It is not difficult work, but it is repetitive, easy to get subtly wrong, and only fails at review — after the creative is finished. If you are using a builder, this is the layer it should be absorbing for you. Playable Ads Maker writes the correct exit call, packaging and size handling per network at export, so the same creative goes to thirteen networks without thirteen sets of edits.
Common MRAID mistakes, and what they look like
These are the ones that reach review rather than being caught in development, because each of them behaves perfectly in a desktop browser.
- Assuming mraid exists on page load. The object may be injected slightly after your script runs, so a guarded check plus the ready event is the reliable pattern, not a bare reference.
- Starting gameplay, timers and audio on load rather than on viewability. The user's opening seconds are consumed before the ad is even on screen, and your engagement rate quietly suffers with no visible fault.
- Firing the click on pointerdown rather than on a completed tap. Scroll gestures then register as clicks, which inflates click counts and irritates users into a negative impression of the product.
- Calling mraid.open more than once from a rapid double tap. Some hosts open two store sessions; a simple guard flag after the first call avoids it.
- Not signalling that the playable has ended, where the network expects it. The ad appears to work and the integration reports as incomplete.
Where MRAID ends and the network begins
One last distinction worth holding onto, because it explains most of the confusion in this area. MRAID is a standard for talking to the host app. It is not a standard for packaging, file size, review policy or creative content — those are entirely per network, and they vary more than the API does. Two networks can be equally MRAID-compliant while disagreeing on whether you submit a single HTML file or a ZIP, what the ceiling is, and whether your creative sufficiently represents the app.
So "MRAID compliant" is necessary and never sufficient. Treat it as the shared foundation, and treat each network's own requirements as a separate checklist on top of it.
Create playable end cards in minutes—no code required.
Open Playable Ads MakerCheck a build against these specs
The free Playable Ad Spec Checker grades an HTML or ZIP against all 13 networks’ size caps, packaging, MRAID rules and store-exit calls. It runs entirely in your browser — no upload, no sign-up.