ANALYTICS_API.md 7.9 KB

用户行为埋点 API 文档

基本信息

项目 说明
接口路径 POST /api/v1/analytics/events
请求方式 POST
Content-Type application/json
返回格式 {code, message, data}
认证 无需认证(有 Token 时自动记录用户标识,无 Token 记录为 anonymous)

一、上报行为埋点

请求

POST /api/v1/analytics/events
Content-Type: application/json
Authorization: Bearer <token>   (可选)

请求体

字段 类型 必填 说明
event_type string 事件类型,不传则默认为 unknown
event_data object 事件附加数据,JSON 对象
page_url string 触发事件的页面 URL(建议传完整地址)
referrer string 来源页面 URL

服务端自动记录

以下字段由服务端从请求中自动提取,无需前端传入

字段 来源
user_key JWT Token 中的用户标识,未登录为 anonymous
ip 请求来源 IP
user_agent User-Agent 请求头

响应

{
  "code": 202,
  "message": "accepted",
  "data": {
    "status": "accepted"
  }
}

注意:接口返回 202,写入是异步的(fire-and-forget),前端无需等待或处理结果。

示例

curl -X POST https://pharmacopoeia.kailin.com.cn/api/v1/analytics/events \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "page_view",
    "event_data": {},
    "page_url": "https://pharmacopoeia.kailin.com.cn/?token=xxx"
  }'

二、标准事件类型定义

页面行为

event_type 触发时机 event_data
page_view 页面加载/进入 {}{referrer: "来源URL"}

用户交互

event_type 触发时机 event_data
click 点击快捷提问标签 {label: "标签名称"}
switch_tab 切换导航标签页 {tab: "chat" \| "drugs"}

对话行为

event_type 触发时机 event_data
chat 用户发送提问 {query: "用户输入的问题", has_media: true \| false}

搜索行为

event_type 触发时机 event_data
search 搜索药品 {keyword: "搜索关键词"}

浏览行为

event_type 触发时机 event_data
drug_detail 查看药品详情 {drug_id: "H20000001", drug_name: "阿莫西林"}

品牌推荐

event_type 触发时机 event_data
brand_recommend 品牌推荐匹配命中 {recommendations: [{brand_name, matched_keyword, tier}]}

品牌推荐匹配由后端在 SSE 流中自动注入 brand_recommend 事件,前端收到后渲染推荐卡片。事件数据详见 HANDOVER.md 第十六章节。

管理端——品牌管理 API

方法 路径 说明
GET /api/v1/admin/knowledge/brands 品牌列表(分页+搜索 keyword/name)
POST /api/v1/admin/knowledge/brands 新增品牌(name + 10个长文本字段 + jump_url + sort_order)
PUT /api/v1/admin/knowledge/brands/{id} 修改品牌
DELETE /api/v1/admin/knowledge/brands/{id} 删除品牌
POST /api/v1/admin/knowledge/brands/import 品牌 CSV 导入
GET /api/v1/admin/knowledge/brands/export 品牌 CSV 导出
GET /api/v1/admin/knowledge/brands/template 下载品牌导入模板

管理端——品牌推荐规则 API

方法 路径 说明
GET /api/v1/admin/knowledge/brand-recommend-rules 规则列表(分页+搜索 keyword)
POST /api/v1/admin/knowledge/brand-recommend-rules 新增规则(keyword + brand_id + tier)
PUT /api/v1/admin/knowledge/brand-recommend-rules/{id} 修改规则
PATCH /api/v1/admin/knowledge/brand-recommend-rules/{id}/toggle 启用/停用规则
DELETE /api/v1/admin/knowledge/brand-recommend-rules/{id} 删除规则
POST /api/v1/admin/knowledge/brand-recommend-rules/import 规则 CSV 导入
GET /api/v1/admin/knowledge/brand-recommend-rules/export 规则 CSV 导出
GET /api/v1/admin/knowledge/brand-recommend-rules/template 下载规则导入模板

品牌实体字段

{
  "id": 1,
  "name": "芬必得布洛芬缓释胶囊",
  "function_indication": "用于缓解轻至中度疼痛...",
  "usage_dosage": "口服。成人一次1粒,一日2次...",
  "contraindication": "对本品过敏者禁用...",
  "ingredients": "每粒含布洛芬300mg",
  "properties": "本品为胶囊剂,内容物为白色粉末",
  "specification": "0.3g×20粒/盒",
  "adverse_reactions": "偶见恶心、呕吐...",
  "precautions": "孕妇及哺乳期妇女慎用...",
  "execution_standard": "《中国药典》2025年版二部",
  "storage": "密封,在阴凉干燥处保存",
  "jump_url": "https://example.com/product/123",
  "description": "知名止痛品牌",
  "sort_order": 0,
  "is_active": true
}

匹配规则实体字段

{
  "id": 1,
  "keyword": "布洛芬",
  "brand_id": 1,
  "tier": 1,
  "is_active": true
}

接口调用(自动埋点)

event_type 触发时机 event_data
api_call 任意 API 调用完成 {url: "/api/v1/chat/stream", method: "POST", status: 200, elapsed_ms: 342}
api_call API 调用失败 {url: "/api/v1/drug/search", method: "GET", status: 0, elapsed_ms: 5000, error: "network_error"}

三、前端接入示例

最小接入(推荐封装 track 函数)

function track(eventType, eventData) {
  var payload = {
    event_type: eventType,
    event_data: eventData || {},
    page_url: window.location.href,
    referrer: document.referrer || ''
  };
  try {
    fetch('https://pharmacopoeia.kailin.com.cn/api/v1/analytics/events', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
      keepalive: true   // 页面关闭时也能发出
    }).catch(function(){});
  } catch(e) {}
}

使用示例

// 页面浏览
track('page_view');

// 搜索
track('search', { keyword: '阿莫西林' });

// 点击
track('click', { label: '感冒药推荐', position: 1 });

// 提问
track('chat', { query: '布洛芬怎么吃', has_media: false });

// 自定义事件
track('custom_event', { key1: 'value1', key2: 'value2' });

自动拦截 fetch(可选,自动记录所有 API 调用)

(function(){
  var _fetch = window.fetch;
  window.fetch = function(url, opts){
    var t0 = Date.now();
    var method = (opts && opts.method) || 'GET';
    return _fetch.apply(this, arguments).then(function(r){
      track('api_call', {
        url: typeof url === 'string' ? url : '',
        method: method,
        status: r.status,
        elapsed_ms: Date.now() - t0
      });
      return r;
    }).catch(function(e){
      track('api_call', {
        url: typeof url === 'string' ? url : '',
        method: method,
        status: 0,
        elapsed_ms: Date.now() - t0,
        error: e.message || 'network_error'
      });
      throw e;
    });
  };
})();

四、注意事项

  1. fire-and-forget — 埋点接口返回 202,异步写入,前端不要 await,不要阻塞主流程
  2. keepalive — fetch 带上 keepalive: true,确保页面关闭/跳转时也能发出
  3. 容错track() 必须放在 try/catch 里,埋点失败不能影响正常功能
  4. user_key — 建议前端传 JWT Token(Authorization: Bearer xxx),后端自动提取用户标识;不传则记为 anonymous
  5. event_data — 建议始终传 {} 而非 null,方便后端统一处理
  6. page_url — 建议传完整 URL,方便分析不同页面的行为分布