The Multi-Platform Nightmare
A single playable ad needs to run on Facebook, TikTok (Pangle), Google Ads, and often a custom landing page. Each platform has its own MRAID specification, its own event API, and its own file format requirements. Facebook expects a single HTML file with FbPlayableAd.js. TikTok expects a ZIP with an index.html entry point. Google expects MRAID 2.0 compliance.
Building one creative that works everywhere is hard enough. Building 50 variants — each with different CTAs, color schemes, and game mechanics — without a dedicated engineering team per platform is where most playable ad programs stall.
PlayableAd Studio solves this with a build pipeline that takes a single Cocos Creator project and automatically generates platform-specific builds. This post breaks down the pipeline architecture, the template system, and the cloud infrastructure that makes it possible.
Pipeline Architecture
```
[Cocos Creator Project (.ccreator)]
↓
Template Parameters (JSON config)
↓
gulp build task
↓
Platform Adapter Layer
├── Facebook Adapter → FbPlayableAd wrapper
├── TikTok Adapter → ZIP + Pangle APIs
└── MRAID Adapter → MRAID 2.0/3.0 + Generic
↓
Minification (html-minifier, uglify-js)
↓
Output verified by platform SDK
↓
Upload to R2 + Shortlink
```
The Template Engine
At the heart of the pipeline is a JSON-based template parameter system. Instead of editing Cocos Creator scenes for each variant, the pipeline takes a config file:
```json
{
"variant_id": "v3",
"cta": {
"text": "Play Now",
"color": "#FF6B35",
"delay_ms": 3000,
"position": "bottom-center"
},
"game": {
"difficulty": 1.5,
"time_limit": 30,
"level_count": 3
},
"branding": {
"logo_url": "https://cdn.example.com/logo.png",
"accent_color": "#FF6B35"
}
}
```
The build pipeline reads these parameters and injects them into the Cocos Creator build output by patching the generated `settings.js` and `project.js` files. This is done via a Node.js script that runs after `gulp build`:
```javascript
// Template injection (simplified)
function injectTemplate(buildDir, params) {
const settingsPath = path.join(buildDir, 'src', 'settings.js');
let settings = fs.readFileSync(settingsPath, 'utf8');
// Inject template params as global config
const injection = `window.__PAS_CONFIG = ${JSON.stringify(params)};`;
settings = injection + settings;
// Apply CTA color to game config
const colorRe = /ctaColor:\\s*['\"][^'\"]*['\"]/;
settings = settings.replace(colorRe, `ctaColor: '${params.cta.color}'`);
fs.writeFileSync(settingsPath, settings);
}
```
Platform Adapters
Each platform adapter is a standalone Node.js module that takes the base Cocos Creator build and wraps it in the platform's required format:
| Platform | Format | SDK | Adapter Size |
|----------|--------|-----|-------------|
| Facebook | Single HTML | FbPlayableAd.js | +2KB |
| TikTok | ZIP archive | Pangle API | +3KB |
| Google Ads | MRAID HTML | MRAID 2.0 polyfill | +1KB |
| Generic | Standalone HTML | None | 0KB |
The adapters share a common MRAID compatibility layer. Each implements the same interface — `initAd()`, `startGame()`, `showCTA()`, `closeAd()` — but maps them to platform-specific APIs under the hood.
The Facebook Adapter in Detail
The Facebook adapter is the most popular, so it's the most optimized. It:
1. Takes the minified Cocos Creator HTML build
2. Injects Facebook's MRAID polyfill (`FbPlayableAd.js`)
3. Wraps game completion detection in `FbPlayableAd.onComplete()`
4. Wraps CTA clicks in `FbPlayableAd.onCTAClick()`
5. Adds Facebook's `fbq` tracking pixel
6. Validates output against Facebook's SDK validator
```javascript
// Facebook adapter core
function buildFacebook(buildDir, params) {
const baseHtml = fs.readFileSync(path.join(buildDir, 'index.html'), 'utf8');
const facebookWrapper = `
<script>
// FbPlayableAd integration
window.FbPlayableAd = window.FbPlayableAd || {};
function onGameComplete() {
if (window.FbPlayableAd.onComplete) {
window.FbPlayableAd.onComplete();
}
}
function onCTA() {
if (window.FbPlayableAd.onCTAClick) {
window.FbPlayableAd.onCTAClick();
}
window.open('${params.cta.url}', '_blank');
}
</script>
`;
// Inject before closing </body>
const output = baseHtml.replace('</body>', facebookWrapper + '</body>');
return output;
}
```
Cloud Infrastructure
The pipeline runs on GitHub Actions with Workers integration. When a new variant is requested:
1. **GitHub Action** clones the Cocos Creator project, runs build + template injection + platform adapters
2. **Workers API** receives the build artifacts and stores them in R2 (`pas-builds/<campaign_id>/<variant_id>/<platform>/index.html`)
3. **Shortlink Worker** generates a unique URL per build (`https://pas.ai-kit.net/c/abc123/v3/fb`)
4. **Status Worker** provides a dashboard showing build history, variant scores, and deployment status
The entire pipeline, from template config to deployed build, takes under 60 seconds for a single variant.
Why This Matters for Marketing Teams
For a marketing team managing multiple ad campaigns, the bottleneck isn't creative ideas — it's engineering bandwidth. Each new variant means a developer writing Cocos Creator code, running builds, and exporting platform-specific files.
PlayableAd Studio's pipeline reduces that to: a marketer edits a JSON config → bot builds and deploys → ad goes live. The developer writes the template once; the marketer generates 50 variants from it.
This is the Hybrid Dev+Marketing philosophy in action: build tools that let non-developers execute technical workflows without breaking the abstraction. The marketer doesn't need to know what MRAID stands for. They just need to know that changing the CTA color to #FF6B35 improved click-through rates.
Next Steps
PlayableAd Studio's build pipeline is Apache 2.0 licensed and available on GitHub. The template parameter system is extensible — add your own config keys and injection rules via a plugin API.
For teams running Cocos Creator 2.4.x playable ads, this pipeline cuts per-variant production time from 30 minutes of developer work to 30 seconds of automated processing. That's the difference between testing 3 variants per campaign and testing 30.