H5 集成说明
概述
优聚智汇 H5 广告 SDK 采用统一入口设计:
- 单例入口:
UjuAdSdk单例,通过init()初始化、createAd()创建广告 - 统一创建:所有广告类型通过同一个
createAd(container, options)方法创建,广告类型由服务端返回的adType字段决定,客户端无需指定 - 自动渲染:SDK 内部完成广告素材的 DOM 渲染,无需手动拼接 HTML
- 自动上报:曝光、点击、视频进度等事件由 SDK 内部自动监听并上报,不提供外部事件订阅 API(无
on()/off()/emit()方法)
本文档基于 H5 SDK 源码(
h5/src/)编写,所有 API 均为真实存在的方法签名。
SDK 初始化
1. 构造配置对象
// 构造 SDK 配置(appId 和 adEndpoint 必填)
const config = {
appId: "YOUR_APP_ID", // 必填:应用 ID
adEndpoint: "https://adx.ujuad.com/bid", // 必填:广告请求地址
accessKey: "YOUR_ACCESS_KEY", // ADX 协议必填:访问密钥
secretKey: "YOUR_SECRET_KEY", // ADX 协议必填:加密密钥
keyEndpoint: "https://adx.ujuad.com/key", // 可选:会话密钥交换地址
reportEndpoint: "https://adx.ujuad.com/report", // 可选:事件上报地址
debug: true, // 可选:调试模式,生产环境请设为 false
};2. 调用 init 初始化
// 初始化 SDK(幂等,重复调用会直接返回)
UjuAdSdk.init(config);
// 初始化后即可创建广告实例注意:
init()是同步方法,无返回值。若未调用init()直接调用createAd(),会抛出Error("UjuAdSdk.init must be called first")。
SdkConfig 字段参考
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
appId | string | ✅ 是 | — | 应用 ID |
adEndpoint | string | ✅ 是 | — | 广告请求服务地址 |
keyEndpoint | string | ❌ 否 | — | 会话密钥交换地址(会话密钥模式必填) |
accessKey | string | ❌ 否 | — | ADX 协议访问密钥(ADX 协议必填) |
secretKey | string | ❌ 否 | — | ADX 协议加密密钥(ADX 协议必填) |
protocolVersion | string | ❌ 否 | "3.3.0" | ADX 协议版本 |
reportEndpoint | string | ❌ 否 | — | 事件上报地址 |
maxConcurrency | number | ❌ 否 | 3 | 最大并发请求数 |
requestTimeoutMs | number | ❌ 否 | 200 | 单次请求超时(毫秒) |
retryCount | number | ❌ 否 | 2 | 失败重试次数(退避 200×2^attempt ms) |
debug | boolean | ❌ 否 | false | 是否开启调试日志 |
allowHttpsOnlyFallback | boolean | ❌ 否 | false | 仅 HTTPS 回退开关 |
hmacSecret | string | ❌ 否 | — | HMAC 签名密钥 |
创建广告
基本用法
通过 UjuAdSdk.createAd(container, options) 创建广告实例:
// 方式一:container 为选择器字符串
const ad = UjuAdSdk.createAd("#ad-container", {
slotId: "YOUR_SLOT_ID", // 必填:广告位 ID
autoLoad: true, // 可选:创建后自动加载
});
// 方式二:container 为 DOM 元素
const containerEl = document.getElementById("ad-container");
const ad = UjuAdSdk.createAd(containerEl, {
slotId: "YOUR_SLOT_ID",
});说明:若
container为字符串但找不到对应元素,会抛出Error("ad container not found")。
AdCreateOptions 字段参考
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
slotId | string | ✅ 是 | — | 广告位 ID |
autoLoad | boolean | ❌ 否 | undefined | 是否创建后自动调用 load() |
priority | number | ❌ 否 | 0 | 请求优先级,数值越大越优先 |
userId | string | ❌ 否 | — | 用户 ID(会被 hash 后作为 userIdHash) |
AdInstance 方法
createAd() 返回一个 AdInstance 对象,提供以下方法:
| 方法 | 签名 | 说明 |
|---|---|---|
load() | () => Promise<void> | 加载广告;成功后状态变为 rendered,DOM 自动渲染 |
refresh() | () => Promise<void> | 刷新广告(等同于再次 load());已销毁时静默返回 |
destroy() | () => void | 销毁广告实例;解绑事件、清空容器、状态变为 destroyed(幂等) |
getState() | () => AdState | 获取当前状态:"idle" / "loading" / "rendered" / "destroyed" |
getMetrics() | () => AdMetrics | 获取性能指标快照(浅拷贝) |
registerMacro(name, resolver) | (string, (ad: AdPayload) => string) => void | 注册自定义宏 |
加载与刷新
const ad = UjuAdSdk.createAd("#ad-container", {
slotId: "YOUR_SLOT_ID",
});
// 手动加载广告
ad.load()
.then(() => {
console.log("广告加载并渲染成功");
console.log("当前状态:", ad.getState()); // "rendered"
})
.catch((err) => {
console.error("广告加载失败:", err.message);
console.log("当前状态:", ad.getState()); // "idle"
});
// 刷新广告(重新请求并渲染)
ad.refresh().catch((err) => {
console.error("刷新失败:", err.message);
});状态查询
// 获取广告状态
const state = ad.getState();
// 可能的值:"idle" | "loading" | "rendered" | "destroyed"
// 获取性能指标
const metrics = ad.getMetrics();
console.log(metrics);
// {
// requestStartAt: 1700000000000, // 请求开始时间戳
// requestEndAt: 1700000000200, // 请求结束时间戳
// renderStartAt: 1700000000201, // 渲染开始时间戳
// renderEndAt: 1700000000250, // 渲染结束时间戳
// errors: 0 // 错误计数
// }销毁广告
// 销毁广告实例(幂等,可安全多次调用)
ad.destroy();
// 销毁后状态变为 "destroyed",容器内容被清空
console.log(ad.getState()); // "destroyed"
// 销毁后调用 load() 会抛出 Error("cannot load destroyed ad")
// 销毁后调用 refresh() 会静默返回(不抛错)销毁所有广告
// 一次性销毁所有已创建的广告实例
UjuAdSdk.destroyAll();广告类型
H5 SDK 采用服务端决定广告类型的设计:广告类型由服务端返回的 AdPayload.adType 字段决定,客户端无需也无法指定广告类型。
| adType 值 | 广告类型 | 渲染说明 |
|---|---|---|
1 | 信息流 / Native | 默认类型,支持 wide / narrow / mini 三种子布局 |
2 | 激励视频 | 含"激励视频"标识徽章 |
3 | 横幅 Banner | 横幅尺寸 |
4 | 插屏 Interstitial | 全屏覆盖,底部 overlay |
5 | 开屏 Splash | 全屏,含"跳过"按钮 |
// 所有广告类型的创建方式完全相同
const ad = UjuAdSdk.createAd("#ad-container", {
slotId: "YOUR_SLOT_ID",
autoLoad: true,
});
// 服务端会根据 slotId 配置返回对应类型的广告
// SDK 自动根据返回的 adType 选择对应的渲染模板事件上报机制
重要说明:无外部事件订阅 API
H5 SDK 不提供 on() / off() / emit() 等事件订阅方法。所有广告事件(曝光、点击、视频进度)均由 SDK 内部自动监听并上报,开发者无需也无法手动触发或订阅。
自动上报的事件
| 事件类型 | 触发条件 | 上报方式 |
|---|---|---|
impression(曝光) | 广告容器可见面积 ≥ 50% 且持续 1000ms | IntersectionObserver 监测 |
click(点击) | 用户点击广告容器 | capture 阶段捕获,先上报再执行跳转 |
video_progress(视频进度) | 视频播放至 0% / 25% / 50% / 75% / 100% | <video> 的 timeupdate 事件 |
error(错误) | 广告加载或渲染失败 | AdInstance 内部自动上报 |
上报通道优先级
- 优先使用广告返回的
trackers.impression/trackers.click地址 - 其次使用
SdkConfig.reportEndpoint配置的全局上报地址 - 上报方式优先级:
navigator.sendBeacon→fetch(keepalive: true)→ IndexedDB 队列(可重发)
// 开发者无需编写任何事件上报代码
// SDK 在 ad.load() 成功并渲染后,自动绑定事件监听器
// 广告销毁时(ad.destroy())自动解绑所有监听器自定义宏
SDK 内置宏引擎,支持在广告素材 URL 中使用宏占位符,在渲染时自动替换。
内置宏
| 宏名 | 说明 |
|---|---|
__TIMESTAMP__ | 当前时间戳 |
__DEVICE_ID__ | 设备 ID |
__OS__ | 操作系统 |
__SLOT_ID__ | 广告位 ID |
__REQUEST_ID__ | 请求 ID |
__CREATIVE_ID__ | 创意 ID |
__RANDOM__ | 随机数 |
__AUCTION_PRICE__ | 竞价价格 |
注册自定义宏
const ad = UjuAdSdk.createAd("#ad-container", {
slotId: "YOUR_SLOT_ID",
});
// 注册自定义宏(宏名必须匹配 /^__[A-Z_]+__$/ 格式)
ad.registerMacro("__USER_ID__", (adPayload) => {
return "user_12345";
});
// 注册后,广告素材中出现的 __USER_ID__ 会被自动替换为 "user_12345"注意:宏名必须匹配正则
/^__[A-Z_]+__$/,否则抛出Error("invalid macro name: ${name}")。
错误处理
H5 SDK 不使用错误码枚举,所有错误均通过 throw new Error(message) 抛出标准 Error 对象。使用 try-catch 或 Promise.catch() 捕获。
常见错误消息
| 错误消息 | 触发场景 | 解决方案 |
|---|---|---|
"UjuAdSdk.init must be called first" | 未调用 init() 就调用 createAd() | 确保先调用 UjuAdSdk.init(config) |
"UjuAdSdk is not initialized" | 配置未初始化就访问 | 检查 init() 是否被正确调用 |
"ad container not found" | createAd() 的 container 选择器找不到元素 | 检查 DOM 元素是否存在、选择器是否正确 |
"cannot load destroyed ad" | 对已 destroy() 的实例调用 load() | 销毁后不要再调用 load(),如需重新加载请创建新实例 |
"ADX protocol requires accessKey and secretKey" | ADX 协议模式下缺少密钥 | 在 SdkConfig 中提供 accessKey 和 secretKey |
"keyEndpoint is required for session key exchange mode" | 会话密钥模式缺少 keyEndpoint | 在 SdkConfig 中提供 keyEndpoint |
"invalid macro name: ${name}" | registerMacro 的宏名格式不对 | 宏名须匹配 /^__[A-Z_]+__$/ |
错误处理示例
const ad = UjuAdSdk.createAd("#ad-container", {
slotId: "YOUR_SLOT_ID",
});
// 使用 Promise.catch 捕获加载错误
ad.load().catch((err) => {
console.error("广告加载失败:", err.message);
// SDK 内部会自动通过 reportEndpoint 上报错误事件
});
// 或使用 try-catch(需 async 函数)
async function loadAd() {
try {
await ad.load();
console.log("加载成功");
} catch (err) {
console.error("加载失败:", err.message);
}
}完整集成示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>优聚智汇 H5 SDK 集成示例</title>
<!-- 引入 UMD 格式 SDK -->
<script src="ad-sdk.umd.js"></script>
<style>
#ad-container {
width: 100%;
max-width: 640px;
margin: 20px auto;
min-height: 100px;
}
</style>
</head>
<body>
<h1>H5 广告集成示例</h1>
<!-- 广告容器 -->
<div id="ad-container"></div>
<button id="refresh-btn">刷新广告</button>
<button id="destroy-btn">销毁广告</button>
<script>
// 1. 初始化 SDK
UjuAdSdk.init({
appId: "YOUR_APP_ID",
adEndpoint: "https://adx.ujuad.com/bid",
accessKey: "YOUR_ACCESS_KEY",
secretKey: "YOUR_SECRET_KEY",
reportEndpoint: "https://adx.ujuad.com/report",
debug: true, // 生产环境请设为 false
});
// 2. 创建广告实例
const ad = UjuAdSdk.createAd("#ad-container", {
slotId: "YOUR_SLOT_ID",
autoLoad: true, // 自动加载
});
// 3. 监听加载结果(通过 Promise,非事件订阅)
ad.load().catch((err) => {
console.error("广告加载失败:", err.message);
});
// 4. 刷新按钮
document.getElementById("refresh-btn").addEventListener("click", () => {
ad.refresh().catch((err) => {
console.error("刷新失败:", err.message);
});
});
// 5. 销毁按钮
document.getElementById("destroy-btn").addEventListener("click", () => {
ad.destroy();
console.log("广告已销毁,状态:", ad.getState());
});
</script>
</body>
</html>常见问题
Q: 为什么没有 on('load') / on('click') 等事件监听方法?
A: H5 SDK 采用自动上报设计,不提供外部事件订阅 API。曝光、点击、视频进度等事件由 SDK 内部通过 IntersectionObserver 和事件捕获自动监听并上报到服务端。开发者只需调用 load() 并处理 Promise 的 resolve/reject 即可。
Q: 如何指定广告类型(Banner / 激励视频 / 插屏等)?
A: 广告类型由服务端根据 slotId 配置返回,客户端无法指定。不同的 slotId 对应不同的广告类型,请在优聚智汇后台配置广告位时选择对应的广告类型。
Q: 广告加载失败后如何重试?
A: load() 失败后状态会回到 idle,可以直接再次调用 load() 或 refresh() 重试。SDK 内部也有 retryCount(默认 2 次)的自动重试机制。
Q: 页面切换或广告容器被移除后会怎样?
A: SDK 通过 MutationObserver 监听容器从 DOM 移除的事件,会自动触发销毁逻辑(等同于调用 destroy()),无需手动处理。
Q: 如何获取广告的性能数据?
A: 调用 ad.getMetrics() 可获取性能指标快照,包含 requestStartAt、requestEndAt、renderStartAt、renderEndAt、errors 等字段。
技术支持
如在集成过程中遇到问题,请联系:
- 邮箱:marco@ujuad.com
- 官网:https://www.ujuad.com
- 客服电话:18825052976
