What a Meta playable ad is

A Meta playable is an interactive, self-contained mini-build of your app or game shown inline in a user's feed or story. Instead of a static image or a passive video, the user gets a short, hands-on preview — a few taps of real gameplay or a sample flow — before hitting an install CTA. Meta reports these units convert better than static creative for game and app install campaigns specifically because the user has already tried the thing before being asked to install it. That upside comes with a tradeoff: the format has to load fast on a feed scroll, run offline once loaded, and pass a review pipeline that inspects the file itself, not just its behavior in a browser.

Because the ad has to run entirely client-side with no network calls once it's live, Meta's spec is built around one governing idea: the entire experience — code, art, audio, everything — has to fit inside a single HTML file with nothing left to fetch.

Technical requirements

  • Single self-contained HTML file. Meta's uploader accepts exactly one file — no ZIP, no folder, no linked assets/ directory. Every image, sound, font, and script the playable needs has to live inside that one .html file.
  • 5 MB maximum, 2 MB recommended. The hard cap Meta enforces at upload is 5 MB. Meta's own guidance recommends staying closer to 2 MB — creatives that clear the cap but sit well above that recommendation load slowly on a feed scroll, which hurts delivery even on a technically passing file.
  • Zero external requests. No external JS, no external CSS, no image or font loaded from a CDN, no analytics ping, no network call of any kind once the ad is live. Everything has to be embedded — typically as base64 data URIs — inside the single HTML file.
  • FbPlayableAd.onCTAClick() for the click-through. This is Meta's own click API, and it's specific to Meta. The install/CTA button in the playable has to invoke this exact function so Meta's own SDK controls the store redirect. Nothing else — not window.open(), not an auto-redirect on load, not an MRAID call — satisfies this requirement.
  • No auto-playing audio. Sound is only allowed to start after the user has actually interacted with the ad. Audio that plays on load, before any tap, violates the spec regardless of volume or content.
  • MRAID format is prohibited. Meta doesn't use the MRAID standard that AppLovin and Unity Ads rely on. A creative built around mraid.open() or other MRAID lifecycle calls — even if otherwise functional — is the wrong shape for Meta and gets rejected.
RequirementMeta's rule
File countExactly 1 (no ZIP, no folder)
Output formatSelf-contained HTML
Max size5 MB hard cap, 2 MB recommended
Asset loadingAll embedded — external requests prohibited
Click-through APIFbPlayableAd.onCTAClick() only
AudioMust wait for user interaction; no autoplay
MRAIDNot supported — MRAID-format creatives are rejected

Accepted formats and size limits

Meta only accepts a single HTML file as the playable asset — there's no separate video-plus-interactive-overlay option and no ZIP upload path the way some other placements allow. The 5 MB ceiling is enforced at upload; go over it and the file is rejected before it reaches human or automated review. The 2 MB figure isn't a hard limit, but treat it as one anyway: Meta explicitly calls it out as the recommended size because feed and story placements need the creative to render within a tight load-time budget, and a 4.8 MB file that technically clears the cap can still under-deliver relative to a leaner build.

Common upload errors

  • Referencing assets externally instead of embedding them. The most frequent rejection cause. Any export tool that outputs an HTML file alongside a folder of images, audio, or JSON — the normal shape for a build meant to run from disk — will fail the instant it's uploaded on its own, because those sibling files are exactly the external references Meta's spec prohibits.
  • Wrong CTA call. A CTA wired to a different network's click API — MRAID's mraid.open(), Google's clickTag, Mintegral's window.install(), TikTok's openAppStore() — looks correct in testing but fails Meta's review because it isn't calling FbPlayableAd.onCTAClick(). This is especially common when the same source build is being adapted for multiple networks and the CTA rewiring step gets missed or copy-pasted from the wrong target.
  • Auto-redirect instead of onCTAClick(). A creative that opens the store link automatically on load, or on any tap rather than the designated CTA element, doesn't give Meta's SDK the click event it expects and gets flagged during review.
  • Oversized single file. Unoptimized textures, uncompressed audio, or verbose base64 encoding of large binary assets can push a single-file export past 5 MB quickly — often without the file appearing unusually large until it's actually built as one HTML document rather than a folder of separate assets.

Best practices

  • Compress art and audio before embedding — base64 encoding adds roughly 33% overhead on top of the original binary size, so start from the smallest assets that still look and sound right.
  • Build and test against the 2 MB target, not the 5 MB ceiling, so delivery isn't penalized even on a technically compliant file.
  • Wire exactly one click handler to FbPlayableAd.onCTAClick() and remove any leftover click logic from other networks' builds before submitting.
  • Gate all audio behind a user-interaction check — don't rely on browser autoplay policies to enforce this for you, since Meta's review checks the code path directly.
  • Validate the file is genuinely self-contained by opening it in isolation, away from its original export folder — if anything breaks, something outside the HTML file is still being referenced externally.

You can check a file against Meta's size cap for free with PlayableKit's size checker, or run a fuller compliance pass — asset embedding, click API, MRAID/CTA checks — with the playable ad validator. Neither requires a signup.

Exporting a Unity Playworks/Luna build for Meta with PlayableKit

If your playable started as a Unity Playworks (Luna) export, it was built to run from a folder of sibling assets — the opposite of what Meta requires. PlayableKit takes that same export ZIP, inlines every asset as base64 into a single file, and rewires the CTA to FbPlayableAd.onCTAClick() automatically, checking the result against the 5 MB cap before you download it. The full workflow — what breaks in a raw export and exactly what PlayableKit changes — is covered on the export Unity Playworks/Luna to Meta page.

Shipping to more than Meta? The same source build can be converted for Google Ads and AppLovin at the same time, each with its own click API and packaging rules generated from that one build.

What it costs

Meta exports are included on every paid PlayableKit plan, starting with Starter at $400/mo (which also covers Google Ads, AppLovin, and Unity Ads). Studio at $560/mo and Scale at $800/mo unlock every network — including Mintegral, TikTok, and Vungle — with higher build limits and more seats. Enterprise pricing is custom for teams needing dedicated infrastructure. Full details are on the pricing page.