# keentics 接入规格(AI 专用 / LLM-ready) > 本文件用于直接交给 AI 编码助手,让其把 keentics 埋点接入目标工程。内容自包含、无歧义。 > 开始前,使用方需提供三个值,替换全文占位符: > - `{{GATEWAY_URL}}` 采集网关地址,例如 `https://collect.example.com`(生产必须 https) > - `{{PROJECT_KEY}}` 项目标识,例如 `game_prod` > - `{{API_KEY}}` 项目写入密钥(可安全放客户端,仅能写不能读) ## TASK(给 AI 的任务) 把 keentics 埋点接入当前工程:①初始化 SDK;②在关键业务点调用 `track`;③登录处调用 `identify`;④按下方规范命名事件与属性;⑤完成后输出已埋的事件清单。若工程是多端,按对应端的 SDK 接入。不要发明本规格未定义的 API。 --- ## 1. 传输契约(唯一事实来源) - 端点:`POST {{GATEWAY_URL}}/collect` - 头: - `Content-Type: application/json` - `X-Keentics-Project: {{PROJECT_KEY}}`(必填) - `X-Keentics-Key: {{API_KEY}}`(生产必填) - `Content-Encoding: gzip`(可选) - Body(一次可批量多条 event): ```json { "project": "{{PROJECT_KEY}}", "sent_at": 1717600000123, "events": [ { "type": "track", "event": "level_complete", "event_id": "", "time": 1717600000000, "distinct_id": "", "account_id": "u_123", "properties": { "level": "3-2", "coins": 120, "win": true }, "context": { "platform": "web|ios|android|mp|server", "lib": "keentics-js", "sdk_version": "0.0.1", "os": "iOS", "os_version": "17.5", "app_version": "1.0.0", "device_id": "", "session_id": "<30min-timeout>", "url": "" } } ] } ``` ### 字段规则 - `type`:`track` | `identify` | `user_set` | `user_set_once` | `user_increment` | `user_append`。缺省视为 `track`。 - `event`:`type=track` 时必填,非空。 - `event_id`:UUID,**去重幂等键**。同一逻辑事件重发必须用同一 `event_id`(SDK 自动处理)。 - `time`:客户端事件发生时间,毫秒 epoch。 - `distinct_id`:必填。匿名/设备 ID,SDK 持久化。 - `account_id`:可选,登录后业务用户 ID。 - `properties`:任意键值;值会被规整为字符串存储(bool/number 照常传)。 - 响应 `200 {"ok":true,"accepted":N}`。非 2xx 表示该批失败,应保留重试(`event_id` 保证不重复计数)。 ### 拒绝原因(排错对照) `track 缺少 event 名` / `缺少 distinct_id` / `未知或停用的项目`(project_key 错) / `API Key 错误` / `触发限流` / 连接失败(用了 http 或域名未加白名单)。 --- ## 2. 优先用 SDK(不要手拼协议,除非服务端无 SDK) 各端 SDK 统一暴露以下方法(命名按各语言惯例): - `init/configure(url, project, key, appVersion?)` —— 初始化,仅一次 - `track(event, properties?)` - `identify(accountId, traits?)` —— 登录/注册成功后调用 - `reset()` —— 退出登录 - `register(superProps)` —— 注册超级属性(之后每个 track 自动携带) - `userSet(props)` / `userSetOnce(props)` / `userIncrement(props)` / `userAppend(props)` - `flush()` —— 立即发送 SDK 已内置:批量、离线缓存+失败重试、distinct_id/session_id/device_id 管理、`event_id` 去重、预置 `context`。**AI 不需要自己实现这些。** ### Web / JS ```js // SDK 文件: {{GATEWAY_URL}}/sdk/keentics.js (或自托管) keentics.init({ url: '{{GATEWAY_URL}}', project: '{{PROJECT_KEY}}', key: '{{API_KEY}}' }); keentics.register({ channel: 'xxx' }); keentics.track('level_complete', { level: '3-2', coins: 120, win: true }); keentics.identify('u_123', { vip: 2 }); keentics.userSet({ nickname: 'Neo' }); keentics.reset(); ``` 可选:`init({ ..., autoClick: true, autoPageView: true })`。 ### iOS (Swift, SPM 引入 sdk/ios) ```swift import Keentics Keentics.shared.configure(url: "{{GATEWAY_URL}}", project: "{{PROJECT_KEY}}", key: "{{API_KEY}}", appVersion: "1.0.0") Keentics.shared.track("level_complete", properties: ["level": "3-2", "coins": 120]) Keentics.shared.identify("u_123", traits: ["vip": 2]) Keentics.shared.userSet(["nickname": "Neo"]) ``` 生产 HTTPS 无需 ATS 例外。 ### Android (Kotlin, library module sdk/android) ```kotlin // AndroidManifest: Keentics.configure(this, "{{GATEWAY_URL}}", project = "{{PROJECT_KEY}}", key = "{{API_KEY}}", appVersion = "1.0.0") Keentics.track("level_complete", mapOf("level" to "3-2", "coins" to 120)) Keentics.identify("u_123", mapOf("vip" to 2)) ``` ### 微信小程序 (sdk/miniprogram/keentics.js) ```js // 后台需把 {{GATEWAY_URL}} 域名加入 request 合法域名 const keentics = require('.../keentics.js') keentics.init({ url: '{{GATEWAY_URL}}', project: '{{PROJECT_KEY}}', key: '{{API_KEY}}' }) keentics.track('level_complete', { level: '3-2' }) ``` ### 服务端(无 SDK,直接 HTTP) 按第 1 节 POST。`distinct_id` 用业务用户 ID,`time` 用事件真实时间,自行生成 `event_id`(UUID)。 --- ## 3. 事件与属性命名规范(AI 必须遵守) - 事件名:`snake_case`,动宾结构。例:`app_start` `level_complete` `item_purchase` `ad_click` `share_click`。 - 属性名:`snake_case`;同一含义全局同名(金额一律 `amount`,关卡一律 `level`)。 - 数值传数值类型,不要传字符串。 - 不要为同一行为创造多个事件名。 - 单事件属性数量保持精简(建议 < 30)。 ### 用户属性语义 - `userSet`:覆盖(昵称、当前等级) - `userSetOnce`:仅首次写入(注册时间、首充时间) - `userIncrement`:数值累加(累计付费、登录次数) - `userAppend`:数组追加(已获徽章) ### 调用时机 - 应用启动:`track('app_start')` - 登录/注册成功:`identify(account_id, traits)`(之后才有 account 维度) - 退出登录:`reset()` - 关键转化点(注册、关卡、付费、分享等):对应 `track` --- ## 4. 推荐最小事件集(游戏/App 通用,AI 可据此起步) | 事件 | 何时 | 关键属性 | |---|---|---| | `app_start` | 启动/前台 | `from` | | `register` | 注册成功 | `method` | | `login` | 登录成功 | `method` | | `level_complete` | 通关 | `level`, `win`, `duration_s`, `coins` | | `purchase` | 付费成功 | `product`, `amount`, `currency` | | `ad_show` / `ad_click` | 广告 | `placement` | | `share_click` | 分享 | `channel` | 网站类可替换为:`page_view`(SDK 自动)、`sign_up`、`add_to_cart`、`checkout`、`purchase`。 --- ## 5. 验证(接入完成后执行) 1. 触发若干事件。 2. 请求 `GET {{GATEWAY_URL}}/stats`,确认 `accepted` 增长、`invalid`/`rejected_*` 不异常增长,`recent_rejects` 无你的事件。 3. 或在控制台「总览 → 接入诊断」查看。 4. 输出已接入的事件清单(事件名 + 触发点 + 属性)给使用方复核。 ## 6. 约束(AI 不要做的事) - 不要发明本规格外的方法名或字段。 - 不要把 `{{API_KEY}}` 当机密硬藏(它是公开写入密钥),但也不要打日志泄露。 - 不要自己实现批量/重试/去重——SDK 已有。 - 不要用 http 明文指向公网采集域名。 - 不确定的属性宁可不加,保持事件干净。