The scenario
You built the playable once, in Unity, and Playworks/Luna exported it as a ZIP — typically dropped somewhere like ProjectRoot\LunaTemp\stage4\create-hub. It runs fine in a browser. Now the media buy calls for it to run on Google Ads, Meta, AppLovin, and maybe Mintegral or TikTok too, in the same campaign window. The export you have doesn't natively satisfy any one of those networks' submission rules — it satisfies none of them, because none of them agree with each other on what a compliant creative even looks like.
Why hand-rebuilding it per network is genuinely painful
This isn't busywork you can shortcut by copy-pasting — the specs conflict at a structural level, so the rework is real:
- Different click APIs. Google expects
ExitApi.exit()via its hosted script; AppLovin and Unity Ads expect MRAID'smraid.open(url); Mintegral expectswindow.install()with an MRAID fallback; TikTok expectswindow.openAppStore()from its own Playable SDK; Meta expectsFbPlayableAd.onCTAClick(); Vungle expectswindow.parent.postMessage('download','*'). Wire the wrong one into the wrong network and the CTA silently does nothing — a common cause of a creative getting rejected on review. - ZIP vs. single file. Google, Mintegral, and TikTok expect a ZIP archive. AppLovin, Meta, Unity Ads, and Vungle require the opposite: one self-contained HTML file with every image, sound, and font inlined as data — no external requests, no separate assets, period. The same export can't be both at once; it has to be rebuilt two different ways.
- Different size caps in practice. Every network puts a hard ceiling at 5 MB, but Meta and Unity Ads specifically recommend staying near 2 MB, and Google additionally caps a ZIP at 512 files. A build sized fine for one target can blow past another's limit once its assets are properly embedded rather than loaded on demand.
- Naming and folder rules. Mintegral wants the archive name, top-level folder, and HTML filename to all match. TikTok wants a first-level
index.htmlplus aconfig.jsondeclaring orientation. AppLovin, Meta, Unity, and Vungle each expect their own fixed entry filename.
Doing that correctly once is tedious. Doing it correctly for five networks, then again for the next creative iteration, is where the manual approach stops scaling — and where a small packaging mistake turns into a rejected submission you only find out about after review.
The practical workflow with PlayableKit
PlayableKit doesn't touch how you build the playable — Playworks/Luna still does that part. It picks up at the export step:
- 1
Upload the Luna/Playworks export once. The same ZIP you'd otherwise be hand-editing per network goes in as a single source file for the whole job.
- 2
Select your target networks. Pick from PlayableKit's supported networks — limited to whichever ones your plan actually includes (more on that below).
- 3
Run the conversion. PlayableKit extracts the source once and produces a separately packaged output per selected network — correct click-through wiring, correct asset encoding, correct package shape and naming — from that same extracted build.
- 4
Review the report, then submit. Each job returns pass/fail status, output size, and entry-file details per network, so you know before submission whether a package is actually compliant.
A note on plan-based build limits
Every paid plan can select any of the seven supported networks in step 2 — Google Ads, Meta, AppLovin, Unity Ads, Mintegral, TikTok, and Vungle are all available from Starter up. What differs by plan is your monthly build volume, and a build request that would exceed your remaining credits for the month is rejected before conversion runs, so it's worth checking your build count against your plan before you upload, not after. Full plan-by-plan detail is on the multi-network export overview and the pricing page.