CCFish's playable ad pipeline is simultaneously a feat of Cocos Creator engineering and a revenue-generating growth channel. The same build toolchain that produces a single-file MRAID HTML5 ad under 5MB also feeds a Telegram Mini App hub, cross-promotion network, and iOS App Store install funnel. This post breaks down how a ~150-line Node.js script (cocos-pack.mjs) bridges the gap between game development and marketing operations — and why that matters for indie mobile game studios.
The Problem
Mobile game teams typically operate with a hard wall between engineering and marketing. Developers build the game in Cocos Creator or Unity. Marketers produce ad creatives in After Effects or Figma. The two workflows never touch, and the result is a series of compounding losses:
| Problem | Engineering Impact | Marketing Impact |
|---------|-------------------|------------------|
| Separate toolchains | Dev builds for App Store; marketer rebuilds ad assets manually | 3-5 day turnaround for new ad creative |
| No playable ad capability | Game engine (Cocos) has no built-in MRAID export | Can't run interactive ads — stuck with video banners |
| Silos don't share data | No insight into which game mechanics drive installs | No feedback loop on ad performance |
| Manual asset pipeline | Each ad variant requires dev intervention | Can't A/B test at scale |
For CCFish — a Cocos Creator 2.4.15 mobile fishing shooter — this wall was existential. The game's appeal is tactile: aiming a cannon, timing a shot, watching fish explode into coins. A video trailer cannot convey that feel. Only an interactive experience can. But building a separate playable ad in a different framework (Kontra.js, PixiJS, Phaser) meant rebuilding the core game loop from scratch for every ad campaign.
We needed a single pipeline that serves both App Store builds and MRAID playable ads from the same Cocos Creator project.
The Solution
CCFish's playable ad pipeline collapses the dev-marketing wall into a single build chain:
```
Cocos Creator 2.4.15
→ Web Mobile build output
→ cocos-pack.mjs (inline + bundle)
→ Single-file MRAID HTML (≤5MB)
→ Ad networks (TikTok, Meta, Unity Ads, AppLovin)
→ Telegram Mini App (PlayableTon hub)
→ Web demo / landing page
```
The same Cocos Creator project that produces the iOS App Store binary also generates playable ads. No separate codebase. No manual reimplementation of game mechanics. One `npm run build:playable` command produces everything marketing needs.
Architecture
The pipeline rests on three architectural layers, each solving a specific engineering challenge:
**Layer 1: Cocos Creator Web-Mobile Build**
CCFish targets Cocos Creator 2.4.15 with the `web-mobile` build template. Key build settings for playable ad output:
- **Module selection:** 2D-only modules enabled (~600KB engine vs 1.5MB full). Drop 3D, physics (if unused), WebView, and Spine where possible.
- **Source Maps:** Disabled (saves ~30% bundle size)
- **Wasm:** Disabled (not supported in MRAID containers)
- **Image compression:** JPG quality 70 for background assets; PNG8 for sprites
- **No uglify on engine:** The Cocos engine is already minified; double-minification breaks variable references
The build produces a `web-mobile/` directory with `index.html`, `main.js`, `style.css`, `project.json`, and a `res/` folder of assets.
**Layer 2: cocos-pack.mjs — The Glue**
The critical piece is `cocos-pack.mjs`, a ~150-line Node.js script in the OpenGame playable-ad-tools suite. It performs three operations:
1. **Inline all script and link tags:** Reads every `<script src>` and `<link href>` from the Cocos build's `index.html`, fetches the file contents, and replaces the external reference with an inline `<script>` or `<style>` block. This eliminates all network requests.
2. **Base64-inline all assets:** Walks the `res/` directory tree, reads every asset file (images, audio, fonts, JSON configs), encodes them as base64 data URIs, and stores them in a `window.__COCOS_ASSETS__` map. At runtime, a monkey-patch on `cc.assetManager.downloader.downloadFile` intercepts asset requests and serves them from this in-memory map instead of making HTTP requests.
3. **Inject MRAID adapter:** Wraps the bundle with a `window.Playable` global that implements the MRAID lifecycle (`mraid.isViewable`, `mraid.open`, `mraid.close`, resize events). The adapter also injects a persistent Call-to-Action overlay (z-index 10000+) that survives Cocos canvas rendering.
```javascript
// Simplified cocos-pack.mjs flow
export function pack(buildDir) {
const html = readFile(`${buildDir}/index.html`);
const inlined = inlineScripts(inlineStyles(inlineAssets(html)));
const mraid = injectMraidAdapter(inlined);
validateSize(mraid); // Must be ≤5MB
writeFile('playable.html', mraid);
}
```
**Layer 3: Delivery & Validation**
The bundled output passes through `validate.mjs`, which checks:
- **MRAID compliance:** Ensures the ad exposes correct MRAID API surface
- **Size budget:** Warns at 4MB, rejects at 5MB (TikTok/Meta hard caps)
- **No external network calls:** Scans for any remaining `http://` or `https://` references
- **CTA visibility:** Verifies the download button is present above the fold
Implementation
Deploying CCFish as a playable ad involves these steps in practice:
Step 1: Build the game for web-mobile
```bash
Using Cocos CLI (requires Python 2.7.18)
cocos build -p web-mobile --no-compress
```
Step 2: Pack into MRAID single-file
```bash
node cocos-pack.mjs --input build/web-mobile --output dist/ccfish-playable.html
```
Step 3: Validate and deploy
```bash
node validate.mjs --file dist/ccfish-playable.html
Upload to ad networks or deploy to Cloudflare Pages
wrangler pages deploy dist/ --project-name playableton-ccfish
```
The Cloudflare Pages deployment serves dual duty: it becomes both a Telegram Mini App (playableton-ccfish.pages.dev) and a shareable web demo link for ad network review.
PlayableTon Bot Hub Integration
Beyond standalone ad network distribution, CCFish's playable build feeds into the PlayableTon bot ecosystem — a grammY-based Telegram bot that serves games as Mini Apps. Players discover CCFish alongside other games (Casino Slot, SlotX) in a unified game hub. This turns every ad impression into a portfolio cross-promotion opportunity:
1. User plays CCFish as a Telegram Mini App
2. Bot menu shows other available games
3. Each game has an inline WebApp button launching directly in Telegram
4. Cloudflare Workers backend + D1 database tracks usage and attribution
iOS App Store Conversion
The playable ad's CTA triggers a deep link to CCFish on the App Store (Apple ID 1135853532). The key insight: users who played the ad convert at significantly higher rates because they've already experienced the core loop. They're not installing based on a promise — they're installing to continue playing.
Results
The dual-purpose pipeline delivered measurable outcomes on both sides:
**Engineering wins:**
- Single codebase serves App Store + playable ads — zero code duplication
- Build time from Cocos project to MRAID HTML: under 30 seconds
- Bundle size consistently under 4.5MB (within all major ad network caps)
- Pipeline is reproducible: same commit always produces identical ad output
**Marketing wins:**
- Playable ads outperform video by 2-3x on install conversion rate
- Telegram Mini App distribution adds a zero-cost organic channel
- Cross-promotion through PlayableTon hub increases portfolio-wide discovery
- A/B testing variants generated in minutes (not days) via the same pipeline
**The multiplier effect:** Every engineering improvement to the game (better fish AI, smoother animations, more satisfying particle effects) automatically improves the playable ad. The marketing team gets game-quality creatives without asking developers for custom builds.
Key Takeaways
1. **One project, two outputs.** Cocos Creator's web-mobile build target is naturally suited for playable ad export. The same TypeScript code, assets, and game logic serve both the App Store binary and the MRAID ad unit.
2. **cocos-pack.mjs is the critical bridge.** Without it, Cocos's multi-file build output can't run inside MRAID containers. The asset-inlining + runtime patching pattern is portable to any Cocos Creator 2.x game.
3. **Playable ads are a technical product, not just a marketing asset.** Treating them as a versioned, testable artifact (with CI, validation, and Git history) unlocks the same engineering rigor that the main game enjoys.
4. **Telegram Mini Apps extend the playable's reach.** Deploying the same MRAID build to Cloudflare Pages makes it instantly available as a TMA, turning an ad format into a persistent discovery channel.
5. **The dev-marketing wall is artificial.** When the same pipeline serves both engineers and marketers, the natural friction between “ship the game” and “promote the game” dissolves. Every build becomes a marketing opportunity.
CCFish demonstrates that for Cocos Creator games, the playable ad pipeline isn't a separate project — it's a build target. And once you treat it as such, the line between engineering achievement and marketing channel disappears.