返回文档导航
前台接口
GET /api/v1/campaigns/placements
一期 H5 展示位
Banner / 弹窗 / 悬浮入口
一、方案目标
首页活动 Banner、活动弹窗、悬浮活动入口不再写死在 H5 页面里,而是通过统一活动运营位配置下发。
后端负责按国家、人群规则、档期、启用状态和优先级筛选配置;H5 负责按展示位渲染、处理频控、跳转和埋点。
统一抽象:活动展示位 = 展示位置 + 国家 + 人群 + 档期 + 内容 + 跳转 + 频控 + 优先级。
二、一期范围
| 展示位 |
说明 |
当前状态 |
一期规则 |
HOME_BANNER |
首页活动 Banner,可单图或轮播。 |
首页已有静态占位,待接配置。 |
多条按 priority 排序,可轮播;无配置时隐藏。 |
HOME_POPUP |
首页进入后的活动弹窗。 |
待实现。 |
命中多条时取优先级最高一条,受频控限制。 |
HOME_FLOATING_ENTRY |
首页或 H5 全局悬浮活动入口。 |
待实现。 |
命中多条时取优先级最高一条,无配置时不渲染。 |
后续可复用扩展
| 展示位 |
说明 |
PRODUCT_DETAIL_CARD | 商品详情页活动卡。 |
COUPON_ENTRY | 优惠券入口。 |
HOME_NEW_USER_COUPON_CARD | 首页新用户奖励券卡片,来自首页结构需求,接入前需要后端注册展示位 code。 |
PROFILE_BANNER | 我的页 Banner。 |
WITHDRAW_SUCCESS | 提现成功页活动卡。 |
三、下发链路
flowchart TD
A["运营后台配置 campaign_placements"] --> B["前台批量查询 GET /api/v1/campaigns/placements"]
B --> C{"后端过滤"}
C --> D["国家 countryCode"]
C --> E["人群 audienceRule"]
C --> F["档期 startAt / endAt"]
C --> G["状态 ACTIVE"]
D --> H["按 placement 分组返回"]
E --> H
F --> H
G --> H
H --> I{"H5 本地频控"}
I -->|通过| J["渲染 Banner / 弹窗 / 悬浮入口"]
I -->|不通过| K["本次不展示"]
J --> L["点击后按 action 跳转"]
J --> M["曝光 / 点击 / 关闭埋点"]
四、核心数据模型
type CampaignPlacement = {
id: string
countryCode: string
name: string
placement: CampaignPlacementCode
status: 'DRAFT' | 'ACTIVE' | 'DISABLED'
priority: number
startAt: string
endAt?: string
audienceRule?: CampaignAudienceRule
content: CampaignPlacementContent
action: CampaignPlacementAction
frequencyRule?: CampaignFrequencyRule
}
展示位枚举
type CampaignPlacementCode =
| 'HOME_BANNER'
| 'HOME_POPUP'
| 'HOME_FLOATING_ENTRY'
| 'PRODUCT_DETAIL_CARD'
| 'COUPON_ENTRY'
| 'PROFILE_BANNER'
| 'WITHDRAW_SUCCESS'
数据表建议
| 表 |
用途 |
campaign_placements |
存储活动展示位配置,包括展示位、国家、状态、人群规则、内容、动作、频控和优先级。 |
五、配置字段
| 字段 |
说明 |
示例 |
id | 活动运营位配置 ID。 | cpl_home_banner_001 |
countryCode | 国家码。 | ID |
name | 后台可读名称。 | 新用户首单活动 |
placement | 展示位枚举。 | HOME_BANNER |
status | 配置状态。 | DRAFT / ACTIVE / DISABLED |
priority | 优先级,现有文档口径为数值越大越靠前。 | 10 |
startAt | 生效时间。 | 2026-06-01T00:00:00+07:00 |
endAt | 失效时间,可为空。 | 2026-06-30T23:59:59+07:00 |
audienceRule | 人群规则。 | 角色、新用户、版本范围。 |
content | 展示内容。 | 标题、图片、按钮文案、背景色。 |
action | 点击动作。 | 路由、商品、外链、领券、分享。 |
frequencyRule | 频控规则。 | 每次、每天一次、每活动一次。 |
六、人群、内容、动作和频控
人群规则
type CampaignAudienceRule = {
loginRequired?: boolean
roles?: Array<'USER'>
newUserOnly?: boolean
minAppVersion?: string
maxAppVersion?: string
}
当前所有业务用户都是 USER。roles 只为接口兼容保留,建议不传;受众主要按新用户、App 版本和活动时间窗筛选。
内容配置
type CampaignPlacementContent = {
title?: string
subtitle?: string
description?: string
imageUrl?: string
iconUrl?: string
buttonText?: string
backgroundColor?: string
}
跳转动作
| type |
target 示例 |
说明 |
ROUTE | /coupons | 跳 H5 内部路由。 |
PRODUCT | tiktok-1729618560920816365 | 跳商品详情。 |
EXTERNAL_URL | https://example.com | 跳外链。 |
CLAIM_COUPON | cpn_xxx | 触发领券。 |
SHARE | invite | 触发分享动作。 |
频控规则
type CampaignFrequencyRule = {
mode: 'EVERY_TIME' | 'ONCE_PER_DAY' | 'ONCE_PER_CAMPAIGN'
dismissTtlHours?: number
}
频控优先由 H5 使用 localStorage 处理。后续如果要跨设备严格控制,再增加后端记录。
七、前台查询接口
GET /api/v1/campaigns/placements?countryCode=ID&placements=HOME_BANNER,HOME_POPUP,HOME_FLOATING_ENTRY&userId=usr_xxx&role=USER&environmentId=id-test
| 参数 |
必填 |
说明 |
countryCode | 是 | 国家码,例如 ID。 |
placements | 是 | 逗号分隔展示位,当前首页使用 HOME_BANNER,HOME_POPUP,HOME_FLOATING_ENTRY。 |
userId | 否 | 当前用户 ID,未登录时不传。 |
role | 否 | 兼容参数;当前只能是 USER,新调用建议省略。 |
appVersion | 否 | App 版本,用于版本定向。 |
environmentId | 否 | 环境 ID,用于环境定向,例如 id-test。 |
响应结构
type CampaignPlacementsResponse = {
placements: Partial<Record<CampaignPlacementCode, CampaignPlacement[]>>
}
{
"success": true,
"message": "OK",
"data": {
"placements": {
"HOME_BANNER": [],
"HOME_POPUP": [],
"HOME_FLOATING_ENTRY": []
}
}
}
八、管理后台接口
| 接口 |
用途 |
GET /api/v1/admin/campaign-placements | 分页查询活动展示位配置。 |
GET /api/v1/admin/campaign-placements/{id} | 查询单个活动展示位配置。 |
POST /api/v1/admin/campaign-placements | 创建活动展示位配置。 |
PUT /api/v1/admin/campaign-placements/{id} | 更新活动展示位配置。 |
POST /api/v1/admin/campaign-placements/{id}/enable | 启用活动展示位配置。 |
POST /api/v1/admin/campaign-placements/{id}/disable | 停用活动展示位配置。 |
DELETE /api/v1/admin/campaign-placements/{id} | 删除活动展示位配置。 |
GET /api/v1/admin/campaign-placements/options | 查询展示位、状态等后台枚举。 |
POST /api/v1/admin/campaign-placements/{id}/preview | 预览指定用户是否命中活动展示位。 |
创建和更新请求
type AdminCampaignPlacementRequest = {
countryCode: CountryCode
name: string
placement: CampaignPlacementCode
status?: 'DRAFT' | 'ACTIVE' | 'DISABLED'
priority: number
startAt: string
endAt?: string
audienceRule?: CampaignAudienceRule
content: CampaignPlacementContent
action: CampaignPlacementAction
frequencyRule?: CampaignFrequencyRule
}
九、H5 接入方案
H5 增加统一组合函数 useCampaignPlacements(),集中处理拉取、频控、展示、跳转和埋点。
| 职责 |
说明 |
| 批量拉取配置 | 按当前页面需要的 placements 一次性请求。 |
| 按展示位取数据 | 分别返回 Banner、弹窗、悬浮入口可用数据。 |
| 处理频控 | 弹窗和悬浮入口优先使用 localStorage。 |
| 处理跳转 | 根据 action.type 跳内部路由、商品、外链、领券或分享。 |
| 记录事件 | 曝光、点击、关闭优先走现有埋点体系。 |
十、事件上报
活动曝光、点击、关闭、领券转化优先通过埋点体系上报。只有后端需要实时消费活动事件时,才启用业务接口。
POST /api/v1/campaigns/events
{
"campaignPlacementId": "cpl_home_banner_001",
"campaignId": "cmp_xxx",
"placement": "HOME_BANNER",
"eventType": "IMPRESSION",
"userId": "usr_xxx",
"countryCode": "ID",
"platform": "H5",
"extra": {
"route": "/"
}
}
事件类型:IMPRESSION、CLICK、DISMISS、CLAIM。
十一、当前状态与边界
| 能力 |
当前口径 |
| 后台配置 | 可创建、编辑、启停、删除、预览展示位;修改和发布必须记录操作人。 |
| 前台供数 | H5 通过 GET /api/v1/campaigns/placements 按展示位批量获取。 |
| 受众 | 当前只有 USER;可按新用户、App 版本和活动时间窗定向。 |
| 素材 | 上传到 OSS 并通过 CDN 访问;删除或替换配置时同步清理不再引用的对象。 |
| 埋点 | 曝光、点击、关闭优先走统一埋点;只有实时业务动作才进入活动事件接口。 |
十二、维护与发布
- 在 id-test 创建草稿并使用真接口预览,不把 mock 数据发布给运营。
- 素材上传后确认 CDN 可访问,检查目标页面、时间窗和 USER 命中结果。
- 测试通过后由管理后台把同一配置转入生产环境,再执行灰度和正式发布。
- 发布后验证供数、曝光和点击;回滚时停用配置,不直接改历史记录。