激励视频+大转盘小程序完整开源实践:变现与积分体系设计

发布时间:2026/10/10 5:49:37
激励视频+大转盘小程序完整开源实践:变现与积分体系设计
先说结论看广告激励视频积分大转盘抽奖这类微信小程序本质上就是用流量主广告位换用户参与感再用积分体系把用户留下来。最近我把这套玩法整理成了一个开源项目完整覆盖了大转盘抽奖、激励视频看广告、积分累计与多端适配正好可以聊一聊从设计到上线的完整链路。我一直觉得小程序里最“顺”的变现方式就是激励视频。用户主动点、主动看完换来的是实打实的奖励平台给广告费也不心疼。而大转盘抽奖又是激励视频最好的搭档——奖品随机、反馈即时、用户为了“下一抽”愿意持续回来。这篇文章会从变现逻辑、核心模块、实操接入、踩坑记录到开源仓库的结构设计完整拆一遍这套项目。1. 项目整体设计与变现逻辑拆解1.1 为什么选择“激励视频大转盘”这个组合先说激励视频。这种广告形态和开屏、Banner、插屏最大的区别在于用户是“主动选择”观看的。在小程序场景里用户想看广告必然是被某个激励钩子吸引比如看一次给3次抽奖机会、看一次送100积分。因为用户有明确的目标广告完播率会非常高广告主的预算也愿意倾斜到这类高完播的流量位上。大转盘抽奖负责把“看广告”变成一件不枯燥的事。单纯让用户“看广告送积分”前3次可能愿意第10次就麻木了。但大转盘不一样每次转都有不确定性用户会想“万一这次转到手机呢”。即便实际中奖概率不高抽奖本身带来的情绪反馈已经足够驱动用户连续触发激励视频。这两个模块组合在一起形成了一条非常顺畅的路径用户想抽奖 → 没机会了 → 看广告 → 获得机会 → 抽奖 → 无论中没中都想再来一次。从开发者收益角度拆单价高、填充率高、用户主动点击这三个指标同时满足的广告位其实不多。激励视频是整个流量主体系里 eCPM 最稳的类型之一。大转盘这种玩法不会像“看视频得现金”那样引起用户反感因为它披着“游戏抽奖”的外衣用户心理负担小。1.2 开源项目的代码结构与功能模块划分这套项目的核心模块可以分成四块页面展示层、交互控制层、广告管理层、数据与业务层。页面展示层就是大转盘的 UI、积分余额、抽奖记录这些交互控制层处理转盘动画、按钮状态和流程调度广告管理层封装了微信、抖音、快手各端的激励视频 API数据与业务层负责积分增减、库存消耗、中奖结果校验。整个工程我建议用 uni-app 来做原因只有一个标题里的三个端——微信小程序、抖音小程序、快手小程序——用 uni-app 可以一套代码打包到三端。虽然微信原生开发的体验也很好但现在这个项目既然定位是“多端适配开源”跨端框架能省掉大量重复开发工作。开源仓库的结构大体是这样的├── pages │ ├── index // 首页大转盘、积分展示 │ ├── prizeList // 奖品列表与概率公示 │ └── record // 抽奖记录与积分明细 ├── components │ ├── wheel // 大转盘组件 │ └── adButton // 激励视频入口按钮 ├── utils │ ├── ad.js // 多端广告统一封装 │ ├── lottery.js // 抽奖概率算法 │ └── request.js // 接口请求封装 ├── services │ └── api.js // 后端接口定义 └── config └── index.js // 平台配置、广告位ID等为什么要这么分层我在初版代码里把广告逻辑直接写进了页面里结果后面想加一个新平台的时候几乎所有页面都要改。后来把广告封装成utils/ad.js之后换一个端只需要改配置和广告管理内部实现页面层完全不动。1.3 流量主收益模型与各方角色很多人对流量主有个误解以为“我的小程序只要有人看广告就有钱”实际上收益和这几个因素强相关广告填充率、eCPM、用户地区、设备类型。一线城市 iPhone 用户的 eCPM 和低线城市安卓机的 eCPM 能差出好几倍这不是你代码能控制的属于流量主平台的自动分发逻辑。在收益模型里四方角色的关系是这样的广告主出钱投放平台通过算法把广告分发给合适的小程序流量主开发者在自己的页面里展示广告位用户主动观看广告并完成互动。整个闭环里开发者能做的只有两件事提高广告曝光量、提高用户观看意愿。激励视频大转盘本质就是同时优化这两件事。做开源项目还有一个额外优势每接入一个开发者你的广告位曝光场景就多一个。所以我把项目做成了一套可以自己换主题、配置奖品、调整概率的框架甚至支持把转盘换成刮刮卡或者盲盒代码改动成本都很低。2. 核心功能细节解析与关键参数2.1 大转盘抽奖的UI与旋转动画实现要点大转盘看起来是个简单组件做起来细节非常多。UI 上需要一张 PNG 转盘图或者 Canvas 实时绘制我推荐直接用 Canvas 绘制扇区。理由有两条第一Canvas 绘制的图片在小程序里可以动态配色、动态改奖品数量不用频繁切图第二Canvas 的旋转动画可以配合requestAnimationFrame手动控制比 CSS transform 更容易处理“多圈旋转缓动回弹”的效果。旋转动画的核心参数有三个旋转总角度、旋转圈数、缓动函数。总角度决定了转盘最终停在哪个扇区圈数决定了视觉效果有没有“转了老半天”的爽感缓动函数则决定了最后停下来时候的阻尼手感。我当时实现的时候用了一个比较稳妥的方案先由后端/前端算法计算出中奖奖品序号再反推目标角度然后从当前角度累加360 * 圈数 目标角度偏移用三次缓动曲线完成动画。注意一点转盘指示器一般固定在顶部所以扇区的起始角度要换算好不然会出现“明明中了三等奖指针却指在二等奖上”的尴尬。一个关键细节是动画时长。太短了用户觉得“糊弄”太长了用户着急。我测试下来总时长控制在 3.5 秒到 4.5 秒之间最舒服前 30% 快速启动中间保持匀速最后 15% 明显减速给人“差一点就中大奖”的惋惜感。2.2 抽奖概率控制这是最容易踩坑的地方概率控制是整个项目里最容易想简单、最容易出事故的模块。很多新手直接写Math.random() 0.01来判一等奖这种写法在奖品数量少的时候勉强能用但一旦奖品有十几种、概率各不相同就会出大问题。更麻烦的是纯前端随机很容易被用户破解复现。推荐用加权随机算法。先给每个奖品配一个权重值比如const prizes [ { id: 1, name: 手机, weight: 1 }, { id: 2, name: 10元红包, weight: 20 }, { id: 3, name: 100积分, weight: 100 }, { id: 4, name: 谢谢参与, weight: 500 }, ]; function weightedRandom(prizes) { const totalWeight prizes.reduce((sum, p) sum p.weight, 0); let randomNum Math.random() * totalWeight; for (const prize of prizes) { randomNum - prize.weight; if (randomNum 0) return prize; } return prizes[prizes.length - 1]; }这里的totalWeight不需要刻意抽稀但每个奖品的权重必须精确到用户能感知的节奏。比如“谢谢参与”权重 500 看起来中奖率低但如果奖品列表里有多个高权重小奖整体中奖率并不低。用户会自己形成“今天运气不错”的心理预期。在此基础上我还建议加保底机制。连续 N 次没中到大奖下一次自动提升大奖权重。这在抽奖玩家里叫“伪随机”但对于留存非常有效。用户在抽了第 9 次“谢谢参与”之后第 10 次看到“恭喜”会是什么体验直接拉满。保底机制的实现就是在服务端额外存一个用户累计未中大奖次数的字段达到阈值后把大奖权重临时提高到 100%。还有一条硬性要求平台审核会要求抽奖规则透明。所以奖品列表页必须展示每个奖品的概率或“中奖概率由平台根据活动动态调整”的说明。概率公示不只是合规要求也能减少用户投诉间接保护你的小程序评分。2.3 积分体系设计与用户留存平衡积分是连接“看广告”和“抽奖”的中间货币。想让用户源源不断看广告就必须让积分既不能太多也不能太少。积分给太多用户攒够一次抽奖就不再想看广告了给太少用户觉得看广告不值直接放弃。我建议初始版本采用这套规则看一次激励视频得 50 积分抽一次大转盘消耗 100 积分抽奖获得的小奖返还 30-200 积分不等。这样用户看 2 次广告可以抽 1 次抽到“谢谢参与”也会给少量积分补偿不会彻底打击积极性。同时要设置每日获取上限。不是怕用户薅羊毛而是为了保护 eCPM。如果一个用户一天看了 300 次激励视频他的广告价值会快速下降平台会认为这个用户的广告位质量不高导致后续填充率和价格都跌。合理做法是每天限制前 20 次激励视频给全积分之后降为 20 积分超过 30 次后不再给积分。这样既控制成本又不会完全切断收益。积分存储不建议用uni.setStorage这种本地方案。用户卸载重装、换设备、清缓存都会导致积分丢失投诉率很高。开源项目里保留了一个services/api.js入口实际部署推荐接微信云开发或自建后端至少把积分流水和防刷校验放到服务端。3. 实操过程从0到1搭建可上线的完整项目3.1 环境准备与项目初始化不管你是用微信原生开发还是 uni-app第一步都是到对应平台注册小程序账号。微信公众平台、抖音开放平台、快手开放平台三个地方我都注册过过程大同小异先注册主体信息再创建小程序应用拿到 AppID。个人主体也能注册但要注意流量主功能对账号有开通门槛微信这边通常需要小程序累计独立访客超过 1000抖音和快手也有类似的活跃要求。项目初始化我用的是 HBuilderX 创建 uni-app 默认模板然后装好dcloudio/uni-ui。在manifest.json里配置微信小程序、抖音小程序、快手小程序的 AppID这是多端打包的前提。这里有一个我项目里一直保留的习惯把广告位 ID 统一放在config/index.js里不写死在页面中。因为微信的广告位 ID 在正式版和体验版里是不同的而且抖音、快手的广告位规则也不一样。统一配置能避免改一次广告位就把页面翻个底朝天。开通流量主之后在平台后台创建“激励视频广告位”会得到一个广告位 ID。注意微信这边在“流量主-广告位管理”里可以设置“是否开启视频广告”要确保状态是开启。广告位创建完成后可能有几分钟到几小时的审核生效期刚建完去调用容易报“广告位无效”。3.2 激励视频广告组件接入与调试在 uni-app 里激励视频广告可以直接用uni.createRewardedVideoAd。但为了让代码适配微信、抖音、快手三端我在utils/ad.js里做了一层封装。核心代码大致是这样// utils/ad.js let rewardedVideoAd null; export function createRewardedVideoAd(options) { // #ifdef MP-WEIXIN rewardedVideoAd wx.createRewardedVideoAd({ adUnitId: options.adUnitId, multiton: false, // 微信新版本建议单例 }); // #endif // #ifdef MP-TOUTIAO rewardedVideoAd tt.createRewardedVideoAd({ adUnitId: options.adUnitId, }); // #endif // #ifdef MP-KUAISHOU rewardedVideoAd ks.createRewardedVideoAd({ adUnitId: options.adUnitId, }); // #endif if (!rewardedVideoAd) return Promise.reject(当前平台不支持); // 处理好加载失败后的重新加载 rewardedVideoAd.onError(e { console.error(激励视频广告错误, e); }); return rewardedVideoAd; } export function showRewardedVideoAd() { return new Promise((resolve, reject) { if (!rewardedVideoAd) { reject(广告未初始化); return; } rewardedVideoAd.show().catch(() { rewardedVideoAd.load() .then(() rewardedVideoAd.show()) .then(res resolve(res)) .catch(err reject(err)); }); }); }很多新手的错误是show()失败后直接拒绝没有做reload再show。广告组件经常会出现拉取失败的情况尤其是第一次启动的时候。上面代码里先show()失败再load()再show()是一个比较稳妥的降级方案。还有一个细节激励视频的onClose回调里需要区分“正常看完”和“中途退出”。微信的onClose里 res 参数带有isEnded字段抖音和快手也有类似的字段。只有isEnded为 true 时才给用户发积分否则坚决不放奖励。这是防止用户白嫖广告奖励的基础防线。3.3 看广告领积分完整闭环流程实现完整流程是这样的用户点击“看广告抽奖”按钮 → 前端请求后端生成一个带签名的一次性任务 ID → 前端调起激励视频广告 → 用户完整观看 →onClose返回isEndedtrue→ 前端带着任务 ID 请求后端发积分接口 → 后端校验任务 ID 未使用、用户当日次数未超限、单次积分金额正确 → 积分入账 → 前端更新积分余额并调起大转盘。把“一次性任务 ID”这个概念引入是为了防止用户抓包后自己伪造发积分请求。后端生成任务时可以把用户 ID、当前时间、积分数量、随机数绑在一起做签名。前端上传签名后端验签通过才发积分。这里我不推荐纯前端判断因为任何纯前端逻辑都可以被破解。开源版本里我留了一个mock模式方便演示但代码注释里明确写了“上线必须接服务端校验”。积分到账后大转盘就可以进入了。这一步的UI反馈也很重要积分到账后用一个小弹窗显示“50”再用一个轻微的震动反馈微信端可以用wx.vibrateShort会让用户觉得“这次看广告值了”。3.4 抖音快手等其他平台的适配思路虽然 uni-app 统一了 API但细节差异仍然不少。我做了一个简单的对照表方便你在开发时快速排查功能点微信小程序抖音小程序快手小程序创建激励视频wx.createRewardedVideoAdtt.createRewardedVideoAdks.createRewardedVideoAd广告关闭回调字段isEndedisEndedisEnded用户ID标识wx.getUserInfo受限tt.getUserInfoks.getUserInfo振动反馈wx.vibrateShorttt.vibrateShortks.vibrateShort云开发微信云开发抖音云能力快手没有类似能力三端最核心的差异是初始化方式。微信的广告对象建议单例复用但抖音和快手在部分版本上同一个广告对象连续显示会出现空白页需要在每次展示前重新创建或重新 load。我在ad.js里针对抖音端加了一个load().then(show)的强制串行流程实测下来稳定很多。还有登录态的问题。微信端获取用户信息需要用户手动点击授权按钮抖音端相对宽松一些。做积分系统不一定要拿到用户真实身份用每个平台自带的openid或设备唯一标识做用户区分就够了。4. 常见问题与排查技巧实录4.1 激励视频无法播放或加载失败的排查激励视频加载失败是我收到最多的问题反馈而且大部分时候不是代码写错了是配置或者环境没到位。常见场景有这几个。第一体验版/开发版里广告组件调不起来。很多平台的广告组件在开发者工具里是模拟环境能弹出模拟广告但不能真正计费真机预览如果账号没开通流量主也只会看到加载失败。解决办法是去后台确认流量主是否开通、广告位是否处于投放中状态。第二onError返回adUnitId invalid或1004之类错误码。基本是广告位 ID 填错或者广告位创建后还没生效。把config/index.js里的 ID 和后台核对一遍确认前后没有多余空格。第三同一页面频繁创建广告实例导致白屏。这个问题微信端不太常见但抖音端确实碰到过。解决思路是全局只保留一个广告实例关闭后不销毁只做load重试。如果依然白屏就在show()前加一个 300ms 的延时给 WebView 一个缓存释放的时间。4.2 iOS/安卓与不同平台差异处理iOS 和安卓之间的广告表现差异是很多人没预料到的。首先iOS 端的 eCPM 通常显著高于安卓这是公开规律。其次iOS 端对广告加载的隐私限制更严格同一设备反复调用广告接口更容易出现“无广告可投”的情况。实践中我看到过 iOS 用户连续看了 20 个广告后第 21 个广告怎么都拉不出来的情况安卓反而能继续拉。处理方式是在前端加一个失败后的友好提示不要直接让用户干等。如果广告加载失败自动弹窗告诉用户“当前广告资源紧张稍后再试”同时给一个“观看失败补偿 10 积分”的兜底按钮。用少量积分稳住用户情绪比让用户觉得“白看了”强得多。多端差异里还有一个容易踩坑的点小程序包体大小。抖音快手平台对主包大小的限制比微信更严格如果项目里引入了比较大的图片或 UI 库很容易超出限制。建议转盘背景图和奖品图都用服务端图片链接不要在本地放大图。4.3 审核被拒的高频原因与规避抽奖类小程序的审核通过率偏低主要被拒原因集中在几个点。一是“谢谢参与”类奖品没有任何价值反馈严格一点的审核会认为这是纯抽奖、没有实质奖品。我处理的办法是给“谢谢参与”也发 30 积分相当于“安慰奖”这就从“抽奖”变成了“积分娱乐”性质不一样了。二是客服和投诉反馈机制不完善。微信要求开通客服消息用户投诉有入口可进。很多小开发者嫌麻烦不开客服审核往往因此被拒。抖音和快手也各有客服配置按平台指引配置好就能过。三是概率公示不明确。我见过有开发者把中奖概率写在“隐私协议”或者“活动规则”里其实这也是可以的但最好在页面里直接放一个入口名字就叫“中奖概率公示”跳转到一个规则页。这样既可以满足合规也给用户一种“这家小程序正规”的感觉。四是诱导分享。千万不要在抽奖流程里加“分享好友后获得更多抽奖次数”这种机制微信会直接判违规。如果确实想让用户裂变可以改成“分享到群后群里好友有 1 次助力机会”这个逻辑需要非常谨慎地评估。4.4 收益统计与对账注意事项流量主后台的数据一般有延迟通常 T1 才能看到昨天的完整数据。我今天看好几个开发者都在问“为什么后台收益和印象中不符”实际情况是不看完整完播只看展示次数是没用的激励视频的收益还要扣掉无效播放比如用户还没看完就关闭或者播放过程中切换到后台。如果你想对自己的小程序收益做心中有数除了看平台后台更建议自己在关键节点打数据日志广告请求次数、广告展示次数、广告完播次数、发放积分次数、参与抽奖次数。把这五个指标埋点你会清楚地看到每一步的转化漏斗。我见过不少项目广告展示率高但完播率只有 40%这时候不需要改代码只要把吸引用户看广告的钩子改得更明确一点收益就能提升一大截。结算时又要留意微信流量主按月结算有门槛金额没达到时累积到下月抖音和快手的结算周期略有差异。另外个人主体和企业主体的税率不同开票流程也不一样。这个不展开讲但新手一定要在平台后台把结算信息提前设置好。5. 开源项目的推广与后续扩展建议5.1 开源仓库的准备文档、示例和合规说明做开源项目代码只占一半另一半是文档和示例。我第一次开源的时候README 写得极其简陋导致很多人下载了源码不会配广告位。后来我重新整理了一套新手友好的文档包含三部分快速启动指南、平台配置说明、扩展开发说明。快速启动指南的核心是让一个零基础的人从下载到跑起来不超过 15 分钟。步骤写清楚导入 HBuilderX、填 AppID、填广告位 ID、运行到微信开发者工具。平台配置说明把微信、抖音、快手三端的差异做成表格配好各个按钮的截图这一步能减少大量issue咨询。合规说明我放在仓库的FAQ里主要是告诉接盘者抽奖活动必须遵守平台运营规范概率要公示不能做赌博式体验。开源不等于免责接盘者自己的小程序遇到了违规问题锅还是自己背。许可证方面我建议用 MIT 或 Apache 2.0。用 MIT 意味着别人可以随意改、随意商用曝光率会更大如果你不希望别人直接换个名字上架商用可以用 GPL不过那样传播范围会小很多。我做这个开源项目的主要目的是让大家看明白激励视频抽奖的完整链路所以选的是 MIT同时保留了NOTICE文件说明项目出处。5.2 基于这个项目还能扩展哪些玩法大转盘只是激励视频玩法的一种落地形态。代码跑通之后你可以把它改成刮刮卡、老虎机、盲盒机或者幸运转转转核心的广告管理、积分发放、概率控制模块完全不用动只需要替换交互层。我在项目里预留了几个扩展点。比如lottery.js的加权随机算法是可以直接复用到任何抽奖场景的services/api.js的后端接口规范默认兼容“签到 积分 抽奖记录”三张表想做每日签到也只需要加一个接口。更复杂一点的扩展方向包括任务中心邀请好友赠送积分、积分商城积分兑换实物/优惠券、排行榜周榜前10能参与周末瓜分积分。这些玩法都会提高用户留存但也会增加服务端压力需要评估好自己的后端能力不要一上来就全堆功能。我在实际开发中的体会是这一类小程序的护城河从来不是抽奖界面或广告代码而是你对用户心理的把握——什么时候该给甜头什么时候该卡一下广告和积分之间怎么保持动态平衡。开源代码只能给你一个起点真正的调整空间都在你后续的数据分析和迭代里。如果你准备拿这套项目上架建议第一版只保留“看广告得积分、积分大转盘”这个最小闭环跑两周数据看清用户留存和广告收益再逐步加新玩法。磨刀不误砍柴工功能堆得再多闭环没跑通也是白搭。