@jolibox/ads
v1.4.16
Published
This project is for integrating Jolibox ads providers
Readme
@jolibox/ads
1. 背景
@jolibox/ads 是 Jolibox JSSDK 的核心包之一,主要负责业务层面的广告调用与聚合。它为不同类型的接入方提供了统一的广告接入规范:
- 游戏接入方:对外暴露 AdSense for Game (AFG) 接口,支持激励视频、插屏广告及 Preroll 等格式。
- 短剧接入方:对外暴露特定的 AFV (AdSense for Video) 接口,主要用于视频流中的广告插入。
为了最大化广告收益并保证填充率,该包实现了一套高效的广告聚合逻辑,支持从多个广告源 (Provider) 进行瀑布流式的广告加载。
2. 目的
- 统一接口:为前端业务屏蔽底层不同广告供应商(如 Google AdSense, OKSpin, AppsRockets 等)的 API 差异。
- 聚合下发:通过后端下发的配置,动态决定广告供应商的优先级和调用顺序。
- 高填充率:通过“瀑布流” (Waterfall) 机制,在一间供应商失败时自动尝试下一间,确保广告展示机会。
- 解耦业务:将复杂的广告加载、超检测、埋点监控等逻辑封装内部,业务方只需关注简单的
adBreak或requestAd调用。
3. 技术选型
- TypeScript: 核心逻辑编写,提供强类型定义。
- Preact & @preact/signals: 部分 native 广告 UI 组件的渲染与状态管理。
- Vite & Esbuild: 高性能的构建工具链,支持 ESM/CJS/IIFE 多种输出格式。
- Async/Await Hooks: 利用 Promise 封装异步回调,简化瀑布流逻辑。
4. 架构
项目采用 Provider 模式 结合 Orchestrator (协调者) 的架构:
- Providers: 每个广告平台(如 Google, OKSpin)都被实现为一个独立的 Provider 子类,遵循统一的接口契约 (
IAbstractAFGProvider/IAbstractAFVProvider)。 - Async Proxies:
AdBreakAsyncProxy和AdRequestAsyncProxy作为中间件,负责包装 Provider 的回调函数,并将异步回调转化为 Promise 状态,从而支持在循环中按序等待。 - Orchestrator:
JoliboxAdsForGame和JoliboxAdsForVideo作为入口类,负责初始化各 Provider,并根据后端下发的序列执行循环调用。
graph TD
User([业务方调用]) --> Main[JoliboxAdsForGame / Video]
Main --> FetchConfig[AdsRequest: 获取广告策略]
FetchConfig --> Loop{瀑布流循环}
Loop --> Proxy[Async Proxy: 包装回调]
Proxy --> Provider[Concrete Provider: Google/OKSpin...]
Provider -- 失败/超时 --> Loop
Provider -- 成功渲染 --> Done([流程结束])5. 目录结构
src/
├── afg/ # AdSense for Game 相关实现
│ ├── adsense/ # Google AdSense Provider
│ ├── okspin/ # OKSpin Provider
│ ├── native/ # Native 广告逻辑
│ ├── adbreak-async-proxy.ts # AFG 异步代理逻辑
│ └── index.ts # AFG 入口及瀑布流编排
├── afv/ # AdSense for Video 相关实现
│ ├── ima/ # Google IMA Provider
│ ├── adrequest-async-proxy.ts # AFV 异步代理逻辑
│ └── index.ts # AFV 入口
├── components/ # 公共组件(如 AdsRequest 请求封装)
├── type/ # 公共类型定义
└── utils/ # 工具函数6. 业务分层
- 接入层 (Access Layer):
JoliboxAdsForGame/JoliboxAdsForVideo类,负责面向接入方提供标准的、归一化的 API 接口(如adBreak,requestAd)。 - 调度与代理层 (Orchestration & Proxy Layer):通过
AsyncProxy将异步回调模式转化为同步await语义,并实现核心的瀑布流调度逻辑。 - 委派与适配层 (Delegation & Adaptation Layer):
- 二级委派机制:这是实现的核心。外露接口不直接参与具体的广告加载逻辑,而是将其委派给具体的
Provider。 - 某些复杂的 Provider(如
GoogleGPT或Native)会进行二次委派给专有的AdManager,从而实现统一外露接口与不同广告源具体实现细节的彻底分离。
- 二级委派机制:这是实现的核心。外露接口不直接参与具体的广告加载逻辑,而是将其委派给具体的
- 基础层 (Base Layer):
AdsContext提供埋点、请求、环境感知的底层支撑。
7. 一些实现细节
Async-Proxy 的实现
为了让分布在不同回调函数(如 beforeAd, adBreakDone 等)中的逻辑能像同步代码一样在一个循环中执行,我们使用了 AsyncProxy 模式:
callAdBreakAndContinue返回一个Promise。- 内部通过
wrapAdBreakDone等闭包捕获原始回调。 - 当广告完成、出错或超时时,调用
resolve并返回一个continueLoop标志。
超时处理
在 AdBreakAsyncProxy 中内置了 5 秒的保护性超时。如果 Provider 在规定时间内没有触发任何有效回调(如 beforeAd),代理层会自动触发 timeout 并让瀑布流进入下一个节点。
Native 广告集成
对于 Native 环境,通过 NativeProvider 与客户端通信。在 Web 端,则通过 AppsRockets 或 GoogleGPT 渲染特定的 UI 组件。
8. Provider 重组逻辑 (Reorganization)
在 init 和获取广告策略 (getAFGAdsInfo/getAFVAdsInfo) 阶段,SDK 会对后端下发的 Provider 列表进行重组。其核心目的是将所有 Native 类型的 Provider 虚拟化为一个统一的 INTERNAL_NATIVE 节点。
为什么需要重组?
- 统一调度语义:在 JS 层的瀑布流逻辑中,不需要感知 Native 侧具体包含多少个三方 SDK(如 Mintegral, AppLovin 等)。通过重组,JS 侧只需与一个
NativeProvider交互。 - 职责分离:JS 侧负责处理 Web 端的多个渠道(Google, OKSpin 等)与 Native 整体之间的优先级;而 Native 侧则利用原生 SDK 的优势,在
NativeProvider内部处理其子级的广告竞价与切换。 - 简化序列管理:后端下发的
seq(优先级)可以在重组后被重新映射。所有 Native 广告通常被视为一个高优先级的整体块(Block),这保证了在原生 APP 环境下,原生广告始终能被优先调用。
9. 广告源实现详情
针对各个广告源的具体实现细节,请参阅以下文档:
- Google AdSense & BannerAsAFG
- OKSpin (AFG & AFV)
- AppsRockets (AFG & AFV)
- Google GPT (AFG & AFV)
- Google IMA (AFV)
- Native Provider (Internal)
10. 开发者深度指南 (AI/Developer Onboarding)
如果你需要在此包上进行二次开发或接入新的广告源,请务必阅读以下规范文档:
- 开发与贡献指南 - 环境搭建与编码准则。
- New Provider 接入规范 - 定义了接口契约与事件流。
- 跨端通信与原生桥接协议 - 定义了 Iframe 与 Native Bridge 的交互细节。
- 后端配置与数据规范 - 详细说明了广告策略接口的字段含义。
