The problem
You open the build in a browser, in MRAID test harnesses, or on your phone, and every tap works — the end-card shows, the button responds, the store link fires. You zip it up, upload it to Google Ads, Meta, AppLovin, or another network, and the exact same build now does nothing when tapped. No error, no console log the reviewer will show you, just a dead button. QA flags it, or worse, the network's review team does.
The real root cause
A raw Playworks/Luna export has its own internal click handling — a function like Luna.Unity.Playable.InstallFullGame that fires when the end-card or CTA is tapped inside the Unity-authored scene. That function was written to do something generically install-like, but it has no idea which ad network is about to host it. Every network runs its own click-through API, and none of them are interchangeable:
| Network | Click-through API it actually expects |
|---|---|
| Google Ads | ExitApi.exit() (with a clickTag variable as fallback) |
| Meta (Facebook) | FbPlayableAd.onCTAClick() |
| AppLovin | mraid.open(url) |
| Unity Ads | mraid.open(url) |
| Mintegral | window.install(), falling back to mraid.open(url) |
| TikTok | window.openAppStore() |
| Vungle (Liftoff) | window.parent.postMessage('download','*'), with MRAID open as fallback |
A Playworks/Luna export ships with none of this wired in, because Unity's export step has no way of knowing in advance which network you'll submit to. Until something bridges Playworks/Luna' internal call to the specific API above, tapping the CTA on the live network calls a function that simply isn't listening — so nothing happens. This is the single most common cause of "the click doesn't do anything" after upload, and it passes local testing every time, because your test harness usually isn't enforcing the real network's click contract at all.
Specific mistakes that cause this
- Wiring the wrong API for the target network. Copying the AppLovin
mraid.open()snippet into a Meta build (or vice versa) is a common copy-paste error once you're maintaining several per-network HTML files by hand. Meta and TikTok don't listen for MRAID calls at all — Meta needsFbPlayableAd.onCTAClick()specifically, and TikTok needs its own SDK'sopenAppStore(). - Gating the call on the wrong event. Some networks require the click-through to fire only after a genuine user tap — attaching it to an auto-fired timer or an unrelated animation-end event, rather than the actual tap on the CTA/end-card, is a rejection risk on top of a "does nothing" bug.
- Calling it before MRAID or the SDK is ready.
mraid.open()called while MRAID is still in itsloadingstate silently fails on several SDK implementations. The call has to wait for the ready event, not fire immediately when the end-card renders. - Leaving Playworks/Luna' own handler as the only handler. If
InstallFullGame(or whatever your scene's install callback is named) is never intercepted and redirected to the network's API, the tap event fires successfully inside Unity's code and simply terminates there — which is exactly what "worked locally, dead on the network" looks like from the outside.
How PlayableKit fixes this automatically
PlayableKit's conversion step exists specifically to close this gap. Upload the Playworks/Luna export once, pick the target network, and PlayableKit injects a per-network adapter that intercepts the export's own install callback and reroutes it to the correct API for that network — ExitApi.exit() for Google, FbPlayableAd.onCTAClick() for Meta, mraid.open() for AppLovin and Unity Ads (after waiting for MRAID's ready state), window.install() for Mintegral, openAppStore() for TikTok, and the postMessage('download','*') handshake for Vungle. It also tracks real user interaction so the call only fires on an actual tap, not before. Every network gets its own correctly wired output from the same source build — you never hand-edit the click logic per network.
mraid.getState() reports ready rather than firing immediately on end-card render.If you're not sure whether a build you already have is missing this wiring, run it through the free Playable Ad Validator first — it checks for the presence of the correct CTA call per network before you spend time debugging in the network's own dashboard. If you're starting from a fresh Playworks/Luna export, the playable ad converter handles the click-through rewiring as part of producing the per-network package. And if your export won't even open correctly before you get to testing clicks, see Unity Playworks/Luna export won't open.