The requirement, stated plainly

TikTok's playable spec requires the package to load TikTok's own Playable-sdk.js locally and fire the click-through via window.openAppStore() — that's the only supported CTA call. The same spec explicitly prohibits MRAID-format creatives; it isn't accepted as an alternate format or a fallback if the native TikTok integration isn't ready. That's a deliberate exclusion, not an oversight in the documentation.

Compare that with the rest of the field. AppLovin and Unity Ads both require MRAID 2.0 and route their click-through through mraid.open(url). Mintegral's spec lists window.install() as the primary call but names mraid.open(url) as an explicit fallback. Vungle's CTA is a postMessage call with MRAID open as its own fallback. Meta is the other outlier that also prohibits MRAID, but it does so in service of a single self-contained HTML file with its own FbPlayableAd.onCTAClick() call — a different shape of exclusion than TikTok's. Among the networks that ship a ZIP-based playable, TikTok is the one that asks for a proprietary SDK and a proprietary call with zero MRAID tolerance anywhere in the build.

What's confirmed: the SDK requirement, the CTA call, and the MRAID prohibition are all pulled directly from TikTok's own playable packaging spec. The rationale in the next section is not — TikTok hasn't published an explanation for the choice, so treat it as an informed inference, not a documented fact.

The likely rationale — inferred, not documented

TikTok doesn't publish a "why" behind this requirement, so the following is a reasonable read of the surrounding facts rather than something TikTok has stated outright. Playables inside TikTok run in TikTok's own in-app browser, not a generic third-party WebView shared across many networks' SDKs. MRAID exists as a cross-network standard precisely because most ad exchanges and mediation layers don't control the runtime end-to-end — they need one API that works across many different apps' embedded web views. TikTok is in a different position: it owns the app, the in-app browser, and the ad-serving pipeline that delivers the creative into it. Building a proprietary SDK tailored to that specific runtime, rather than adopting the general-purpose standard everyone else uses, is consistent with a platform that controls its own delivery surface rather than one that has to interoperate with arbitrary third-party containers.

That's a plausible explanation for why the two design choices — an in-house SDK and a flat prohibition on the alternative — travel together. It isn't confirmation of TikTok's actual reasoning, since TikTok's public documentation doesn't spell one out at all.

The practical consequence

Whatever the reasoning, the effect on a build pipeline is concrete and unforgiving. If a creative is built once and then adapted for several networks — a common pattern when the same Unity Playworks/Luna export feeds AppLovin, Unity Ads, Mintegral, and TikTok — it's easy for MRAID calls from one of those adapters to survive into the package meant for TikTok. A leftover mraid.open() call, an MRAID-ready listener, or an MRAID-shaped click handler doesn't get ignored by TikTok's review; it's exactly what the spec prohibits. That failure is also invisible locally — the HTML still runs fine in a browser, since MRAID code doesn't break page load. It only surfaces once the package reaches TikTok's review, so the usual "open it and see if it works" check won't catch it before submission.

The safer default is to treat a TikTok build as its own target from the start rather than a variant of an MRAID build with the CTA swapped out — strip MRAID entirely rather than leaving it as unused dead code, since dead code is still code TikTok's reviewers can find.

How PlayableKit handles this

When TikTok is one of the selected output targets, PlayableKit doesn't adapt an MRAID build — it generates a TikTok-specific package from the same source export. That means bundling TikTok's Playable-sdk.js locally, wiring the CTA exclusively to window.openAppStore(), and stripping any MRAID API calls, MRAID-ready listeners, or MRAID-conditioned logic that came from another network's adapter path in the same build. The TikTok output never carries MRAID code forward, so there's no leftover call for TikTok's review to reject. The same run also produces the correctly shaped config.json and first-level index.html that TikTok's package structure requires — see the full TikTok playable ads reference for the complete spec, or this page if openAppStore() specifically isn't firing.

For the broader question of which networks want a single self-contained HTML file versus a ZIP — and why that split exists independently of the MRAID question — see single-file vs ZIP playable ads.