playable 广告制作管理平台

guoziyun fe7891972e feat: 颜色按钮自适应居中 & 平板横竖屏 CTA 优化 2 週間 前
docs 85463fec76 build 3 週間 前
platform 7bb9a81e9e feat: storeUrl 改造为可配置参数,移除 userAgent 动态检测 2 週間 前
scripts 6a0d237656 feat: 广告制作管理平台二期 3 週間 前
templates fe7891972e feat: 颜色按钮自适应居中 & 平板横竖屏 CTA 优化 2 週間 前
.dockerignore 6a0d237656 feat: 广告制作管理平台二期 3 週間 前
.gitignore b2fd7f99c7 fix: 生成临时 vite.config.preview.js 硬编码 base 路径 3 週間 前
Dockerfile 6a0d237656 feat: 广告制作管理平台二期 3 週間 前
README.md 6a0d237656 feat: 广告制作管理平台二期 3 週間 前
agent.md 794b3daa37 first commit 3 週間 前
ecosystem.config.js 7e2839cb01 refactor: use dedicated nginx port (5198) for Vite preview 3 週間 前
package.json 3a656069a8 chore: 添加 build:prod 脚本避免遗漏 BASE_PATH 3 週間 前

README.md

Playable Ads

本项目是一个基于 Vue3 + TypeScript + Vite 的项目,核心是基于webgl的web端填色,用于创建可播放的广告。

背景

我们有一个填色应用app,已经上架到google play 和 app store。 但是投放的广告基本上是静态图片或视频, 没有playable的广告, 本项目立足制作playable的广告, 用于提升广告的互动性和效果。

playable广告的核心是H5页面, 本工程已经实现了基于webgl的web端填色核心玩法,现在需要进一步完善制作成可播放的广告。

竞品分析

以下是几家竞品的playbale 广告, 可以作为分析参考, 尤其是页面的规范方面。

Paint by Number:

1.

https://creative-ag-global.umcdn.cn/html/14/df/cf/14dfcf467412065a43ec4d2f1ad63971.html

主要展示了一屏十几个填色作品的填列表页,所谓互动的部分其实就是可以滑动该列表页,点击某个列表页进入一个详情页,这属于简单的内容互动展示,没有涉及游戏核心玩法

2.

https://creative-ag-global.umcdn.cn/html/df/3a/14/df3a14870fcb67b02292a0eac34c5ab1.html

可以滑动选择几个有吸引力的上色作品,点击进入填色详情页, 但同样不能进行填色操作,没有涉及游戏核心玩法,本质还是简单的内容互动展示

Happy Color

1.

https://creative-ag-global.umcdn.cn/html/83/d5/81/83d5810d37e36b92ee5d90517e31b0f9.html

页面动效较好, 但也属于内容展示,没有体现核心玩法, 能够互动的部分就是一个手指指向的 PLAY NOW 按钮,点击即进入安装弹框

2.

https://creative-ag-global.umcdn.cn/html/85/8a/03/858a031936edfda1009dd6acb5c3ec2f.html

这个有涉及一点核心玩法,有提示手型,可点击上色。

Color asis

https://creative-ag-global.umcdn.cn/html/09/2d/44/092d441b80639f462fa667bb3f8964bf.html

这个有涉及核心玩法, 可点击上色,结束后撒花动画,展示典型内容,显示“Over 10,000+ pictures”, 可以作为重点对标研究对象

playable广告规范

各家广告平台对于playable的广告规范如下, 需要仔细研读理解,我们最终发布的内容要符合所有平台的规范:

  1. mintergal

    https://www.playturbo.com/review/doc
    
  2. applovin

    https://p.applov.in/playablePreview?create=1
    
  3. unity

    https://docs.unity.com/zh-cn/grow/acquire/creatives/playable/specifications
    
  4. google admod

    https://support.google.com/google-ads/answer/9981650?hl=en#_HTML
    

gemini关于playable广告的讲解:

https://gemini.google.com/share/8340c20dd2d1

项目目标

制作符合各广告平台的playable ads, 当前可聚焦核心填色玩法的模版, 未来可以可能开发更多模版。

技术栈

层级 技术
渲染引擎 WebGL 2(自研,无外部 GL 框架)
构建工具 Vite 5 + TypeScript 5
打包插件 vite-plugin-singlefile(输出单文件 HTML)
广告平台适配 AdPlatformAdapter(Applovin / Unity / Playturbo-Mintegral / Google)
单文件产物 默认与各平台 profile 均输出自包含 HTML

项目结构

src/
  filler/         # 广告主逻辑
    index.ts      # 入口,整合加载/CTA/平台初始化
    cta.ts        # CTA 按钮点击 + 高亮动画
    ad-platform/  # 平台 Adapter;构建时通过 Vite alias 选择目标平台
    FillerScene.ts# WebGL 填色场景
    FingerHint.ts # 指引手指 DOM overlay
    Loader.ts     # 资源加载
  base/           # 自研 WebGL 2 渲染层
assets/
  res/            # 填色资源包(config.json + 图片)
  css/            # 样式
dist/
  index.html                 # 默认产物
  applovin/index.html        # Applovin 产物
  unity/index.html           # Unity 产物
  playturbo/index.html       # Playturbo 产物
  mintegral/index.html       # Mintegral 产物
  google/index.html          # Google 产物

开发调试

安装依赖

npm install

启动本地开发服务器

npm run dev

映射端口到云服务器

ssh -R 0.0.0.0:5173:localhost:5173 ecs

然后可以在浏览器打开:

http://42.193.231.145:5173

构建

本项目保持一套业务源码,通过 Vite --mode 在构建期选择平台 Adapter,并输出平台专用单文件 HTML。默认构建使用 Google-like adapter,输出 dist/index.html

npm run build           # dist/index.html
npm run build:applovin  # dist/applovin/index.html
npm run build:unity     # dist/unity/index.html
npm run build:playturbo # dist/playturbo/index.html
npm run build:mintegral # dist/mintegral/index.html
npm run build:google    # dist/google/index.html
npm run build:all       # 依次输出以上全部产物

所有产物均为单文件自包含 HTML,JS/CSS/图片/字体均内联。构建后会移除 Vite 单文件产物中的 type="module"crossorigin 属性,以满足 Playturbo 对本地 HTML 文件的扫描要求。

指标 数值
文件大小 ~1.02 MB
Gzip 大小 ~673 KB
平台大小限制 5 MB(各平台均满足)

平台选择由 vite.config.js 中的 platformBuilds 控制:playturbomintegral 都使用 Playturbo adapter,但输出到不同目录和文件名。当前不需要 .env.applovin / .env.unity 等环境文件。

注意:非 Playturbo/Mintegral 平台的 Store 链接集中在 src/filler/ad-platform/adapters/storeUrls.ts

  • 测试阶段:使用 PBN 落地页(当前默认),避免产生无效转化
  • 正式上线:换回自己 app 的 Store 链接(文件内有注释说明)

Playturbo/Mintegral 产物不会内置 Store URL,CTA 只调用平台要求的 window.install()

多平台测试

测试前准备

  1. 根据目标平台执行对应构建命令,或执行 npm run build:all 生成全部产物
  2. 检查 src/filler/ad-platform/adapters/storeUrls.ts 中的落地页 URL 符合当前测试目的

Applovin

预览工具https://p.applov.in/playablePreview?create=1

  1. 执行 npm run build:applovin,打开预览工具,上传 dist/applovin/index.html
  2. 检查项:
    • 广告正常加载,WebGL 填色可交互
    • CTA 按钮可点击(Applovin 通过 ExitApi.exit() 关闭广告,落地页由平台后台配置)
    • 手指引导动画正常显示
    • 完成填色后撒花 + 结算屏正常展示

Unity Ads

规范文档https://docs.unity.com/zh-cn/grow/acquire/creatives/playable/specifications

验证方式:Unity 没有 Web 端预览工具,需通过 Ad Testing App(iOS / Android,最新版 4.0.0)扫码验证。

  1. 执行 npm run build:unity,将 dist/unity/index.html 托管到可访问的 HTTPS URL
  2. 在 Unity Ads Dashboard 上传素材,或在 Ad Testing App 中直接扫码加载
  3. 检查项:
    • dapi.gameReady() 被正确调用(可在控制台确认)
    • CTA 跳转正常(Unity 使用 MRAID mraid.open(url) 跳转)
    • 广告尺寸符合规范(单文件 HTML,无外部请求)
    • 文件大小 ≤ 5 MB

Google AdMob / Google Ads

规范文档https://support.google.com/google-ads/answer/9981650?hl=en#_HTML

验证工具https://h5validator.appspot.com/adwords/asset

Google 的官方验证器要求上传 .zip 而非裸 HTML。需要先将产物打包为 zip,上传时勾选 "Select for App Campaigns",然后点击眼睛图标预览。

  1. 执行 npm run build:google,将 dist/google/index.html 打包为 google-ad.zip
  2. 打开 h5validator,上传 zip,勾选 "Select for App Campaigns"
  3. 点击眼睛图标预览,测试交互和 CTA 点击
  4. 检查项:
    • 无外部网络请求(所有资源均已内联)
    • 文件大小满足限制(≤5 MB,zip 内 ≤512 个文件)
    • CTA 可正常触发跳转(Google 平台使用 ExitApi.exit()
    • 不依赖 document.write 或被禁用 API
    • 包含方向 meta 标签(<meta name="ad.orientation" content="portrait">

Mintergal / Playturbo

规范文档https://www.playturbo.com/review/doc

预览工具https://www.playturbo.com/review

  1. 执行 npm run build:playturbonpm run build:mintegral,按平台文档要求上传对应产物
  2. 检查项:
    • 资源加载完成后调用 window.gameReady()
    • 结束流程调用 window.gameEnd()
    • CTA 只调用 window.install(),不主动 window.open 或跳 Store URL
    • 产物不包含 type="module"crossoriginimportexport
    • 暴露 window.gameStart / window.gameClose
    • 音频在用户首次交互后解锁(iOS 限制)

真机测试

在真实设备上直接用浏览器打开 dist/index.html(可通过云服务器地址访问):

http://42.193.231.145:5173   # dev 模式
# 或将 dist/index.html 放到静态服务器后访问
设备 浏览器 检查项
iOS Safari 音频首次交互解锁、手势填色、CTA 跳转 App Store
Android Chrome 音频、手势、CTA 跳转 Google Play
Android WebView 广告平台内嵌 WebView 行为是否一致

常见问题

Q: 填色区域点击没反应? A: 检查 WebGL context 是否初始化成功,Console 有无报错。

Q: 音效不播放(iOS)? A: iOS 要求用户交互后才能播放音频,代码已有 unlock 逻辑,确认首次点击后音效正常即可。

Q: CTA 点击没有跳转? A: 各平台跳转机制不同:Applovin 优先用 ExitApi.exit();Unity/通用 MRAID 环境用 mraid.open(url);Google-like 环境用 window.open(url);Playturbo/Mintegral 只允许调用 window.install(),不应主动跳 Store URL。

Q: 构建产物超过平台大小限制? A: 检查 assets/res/ 下的图片资源,压缩大尺寸图片后重新构建。

二期规划

在当前一期 playable 广告的基础上,构建一个 广告制作管理平台(Playable Ads Platform),供广告运营团队(5-10人)通过浏览器完成"上传素材 → 配置参数 → 选择平台 → 一键生成广告文件"的完整流程,无需接触源代码和命令行。

详细技术方案见 二期细化方案

核心概念

概念 说明
模板(Template) 可复用的广告框架。当前有 coloring(填色玩法),未来可扩展更多
创意(Creative) 一个模板的实例 = 运营选择的模板 + 上传的素材 + 主题配置 + 构建产物
素材包 运营上传的 .zip 文件,包含 config.json(必)、page.png(必)、map.png(必)、special.jpeg(可选)
构建产物 各广告平台的单文件 HTML,以及全部产物的 ZIP 包

技术架构

React SPA (浏览器)
    │
    ▼
Express API (:3001)
    ├── REST API (/api/v1/*)
    ├── Build Service (调用 Vite 程序化构建)
    ├── SQLite (creatives, builds, templates)
    └── storage/creatives/<id>/  (素材 + 产物)
  • 前端:React + Vite + TypeScript
  • 后端:Node.js / Express + TypeScript
  • 数据库:SQLite (better-sqlite3)
  • 构建:调用现有 Vite 项目,通过 #ad-config alias 注入用户素材和主题
  • 部署:单体部署到 ECS,Express 同时服务 API + 静态文件

项目结构

playableads-platform/
├── templates/                  # 模板根目录(扩展点:新模板 = 新子目录)
│   └── coloring/               #   填色玩法模板(当前一期代码)
│       ├── manifest.json       #     模板元信息(驱动前后端 UI 和校验)
│       ├── src/filler/         #     业务逻辑
│       │   ├── index.ts        #       入口(从 #ad-config 导入素材+主题)
│       │   ├── ad-config.ts    #       默认配置(dev / CLI 构建)
│       │   └── _ad_config_.ts  #       gitignored,平台构建时动态生成
│       └── assets/user/        #       gitignored,平台构建时 symlink → storage
│
├── platform/                   # 二期平台
│   ├── server/                 #   Express API + Build Service
│   └── client/                 #   React SPA
│
└── storage/                    # gitignored,运行时数据
    ├── data.db                 #   SQLite
    └── creatives/<uuid>/
        ├── assets/             #   用户上传的 zip 解压产物
        └── builds/<uuid>/      #   构建输出

运营操作流程

新建创意 → 选择模板(填色玩法)
    │
    ▼
上传素材 zip(config.json + page.png + map.png ± special.jpeg)
    │
    ▼
配置主题(背景渐变、CTA 文案/颜色、进度条颜色…)
    │
    ▼
勾选目标平台(Google / Applovin / Unity / Playturbo / Mintegral)
    │
    ▼
点击构建 → 等待完成 → 下载单平台 HTML 或全部产物 ZIP

模板参数化

核心思路:配置集中化 + Vite alias 切换

  • 模板 index.ts#ad-config 单入口导入所有素材和主题
  • 日常 npm run dev → alias 指向 ad-config.ts(默认素材)
  • 平台构建 → 环境变量 AD_CONFIG_PATH=_ad_config_.ts,alias 指向动态生成的配置
  • 每个模板通过 manifest.json 声明需要哪些素材、哪些主题参数,前端据此渲染 UI,后端据此校验

实施阶段

阶段 内容 预计
1. 基础搭建 目录重构、Express/React 脚手架、DB 初始化 2-3天
2. 模板参数化 index.ts 重构、#ad-config alias、dev/CLI 行为不变 1.5-2天
3. 后端 API 素材存取、构建服务、全部 API 端点 2-3天
4. 前端 UI Dashboard、CreativeDetail、构建交互 2-3天
5. 部署 Docker 化、ECS 部署、端到端测试 1-2天