Strapi 管理后台前端遥测:useTracking 与 trackUsage 事件体系全解

Strapi 管理后台前端遥测:useTracking 与 trackUsage 事件体系全解
Strapi 管理后台前端遥测useTracking 与 trackUsage 事件体系全解【免费下载链接】strapi Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable, and developer-first.项目地址: https://gitcode.com/GitHub_Trending/st/strapiStrapi 管理面板会把用户在后台的操作行为以事件形式直接从浏览器发送到 Strapi 分析端点这套前端遥测机制与strapi.telemetry.send所代表的服务端遥测相互独立。本文基于 Strapi 仓库中的docs/docs/docs/01-core/admin/04-features/telemetry.md文档与对应源码完整解析其架构分层、发送门禁、请求负载结构、事件命名规范以及插件/包如何以 wrapper hook 模式接入统一的上报 API。读完本文你将能够准确理解前端事件的触发时机与隐私设计并能在核心模块或自定义插件中按官方约定新增一个类型安全的前端遥测事件。架构总览浏览器直连分析端点前端遥测的调用链路如下引自文档并已对照源码核实┌──────────────────────────────────────────────────────────────────┐ │ React components / hooks │ │ trackUsage(didSaveContentType) │ │ trackUsage(didCreateEntry, { documentId, status }) │ └────────────────────────────┬─────────────────────────────────────┘ │ ┌────────────────────────────▼─────────────────────────────────────┐ │ packages/core/admin/admin/src/features/Tracking.tsx │ │ TrackingProvider → context (uuid, telemetryProperties) │ │ useTracking() → trackUsage() │ └────────────┬───────────────────────────────┬───────────────────────┘ │ │ │ GET /admin/telemetry-properties│ POST /api/v2/track ▼ ▼ Strapi backend analytics.strapi.io (group metadata) (override: STRAPI_ANALYTICS_URL)从源码结构看整条链路的关键事实是常规 UI 事件没有服务端代理admin SPA 直接用axios向分析端点发起 POST 请求且失败被静默吞掉——追踪永不阻塞 UI 流程。这一设计在 Tracking.tsx 中可以直接印证trackUsage主体包在try/catch中catch分支只留了一句注释// Silence is golden异常时函数返回null。核心 API 之一useTracking()useTracking是管理后台与所有插件使用遥测的主入口实现位于 Tracking.tsx并通过 admin/src/index.ts 从strapi/admin导出。官方用法示例与源码 JSDoc 注释一致import { useTracking } from strapi/admin/strapi-admin; const MyComponent () { const { trackUsage } useTracking(); const handleSave () { trackUsage(didSaveContentType); // or with properties: trackUsage(didCreateEntry, { documentId: abc, status: draft }); }; };trackUsage的类型签名通过三组重载见 Tracking.tsx#L507-L525实现了一个关键能力有属性的事件必须传属性无属性的事件禁止传属性——export interface UseTrackingReturn { trackUsageTEvent extends TrackingEvent( event: TEvent[name], properties: TEvent[properties] ): Promisenull | AxiosResponsestring; trackUsageTEvent extends ExtractTrackingEvent, { properties?: never }( event: TEvent[name], properties?: never ): Promisenull | AxiosResponsestring; trackUsageTEvent extends ExtractTrackingEvent, { properties: object }( event: TEvent[name], properties: TEvent[properties] ): Promisenull | AxiosResponsestring; }返回值是Promisenull | AxiosResponsestring发送成功返回 axios 响应被门禁拦截或请求失败则返回null。核心 API 之二TrackingProvider 与 didInitializeAdministrationTrackingProvider挂载在 Providers.tsx 中位于AuthProvider、HistoryProvider、Theme等 Provider 之内包裹整个已认证应用树负责三件事通过useInitQuery()读取项目uuid对应GET /admin/init用户登录后通过useTelemetryPropertiesQuery()拉取telemetryProperties——源码中该查询带skip: !initData?.uuid || !token条件见 Tracking.tsx#L49-L51即没有 uuid 或没有登录 token 时根本不会发起该请求当uuid与遥测属性同时就绪时用原生fetch而非trackUsage发送一次didInitializeAdministration且该事件是匿名的userId: 见 Tracking.tsx#L52-L78。值得注意的一个源码细节didInitializeAdministration的匿名事件体中groupProperties除了展开服务端返回的遥测属性外还会附带projectId: uuid与registeredWidgets当前注册的全部 widget uid。这与常规事件的负载略有不同属于“会话级初始化”特有的字段组合。发送门禁事件什么时候才真正发出trackUsage只有在所有条件同时满足时才发出网络请求门禁来源项目uuid为真值GET /admin/init——当package.json中禁用遥测时为falsewindow.strapi.telemetryDisabled false构建时由STRAPI_TELEMETRY_DISABLED在render.ts中注入只要任一门禁不满足trackUsage直接返回null不产生任何网络请求。源码中的判断只有一行Tracking.tsx#L557if (uuid !window.strapi.telemetryDisabled) { /* 才会 POST */ }两个门禁的上游分别在哪里生成window.strapi.telemetryDisabled在 render.ts 中被初始化为process.env.STRAPI_TELEMETRY_DISABLED true即构建期由环境变量决定uuid由服务端 controllers/admin.ts 的initaction 返回。该 action 会读取strapi.config.get(packageJsonStrapi.telemetryDisabled)若用户在项目package.json的strapi.telemetryDisabled中显式置为true则uuid被强制改为false——这是在用户侧永久关闭前端遥测的官方配置点另外服务端strapi.telemetry.isDisabled还会影响GET /admin/telemetry-properties的返回禁用时直接返回204 No Content见 controllers/admin.ts#L103-L108使 group 元数据不可用。也就是说Strapi 把遥测开关做成了“构建期环境变量 项目 package.json 服务端运行时状态”三层任一层关闭都会让前端事件静默消失。请求负载结构POST /api/v2/track 的 Body每次通过门禁的trackUsage调用都会向以下地址发起 POSTTracking.tsx#L559${STRAPI_ANALYTICS_URL || https://analytics.strapi.io}/api/v2/track请求体各字段的来源前端视角如下端点与服务端遥测相同字段前端来源eventtrackUsage的第一个参数userId管理员邮箱的 SHA-256 哈希hashAdminUserEmail在AuthenticatedLayout中计算eventPropertiestrackUsage的第二个参数各事件自定义属性userProperties.deviceTypedesktop \| tablet \| mobile来自useDeviceType()的 user-agent 启发式判断groupPropertiestelemetryProperties展开 projectId: uuidprojectType: window.strapi.projectType请求头额外携带X-Strapi-Event: event name便于接收侧按事件名路由。其中隐私处理最典型的是userId的生成AuthenticatedLayout挂载后调用 users.ts 中的hashAdminUserEmail内部用 Web Crypto 的crypto.subtle.digest(SHA-256, ...)对邮箱做单向哈希后再转 16 进制字符串——邮箱原文从不离开浏览器失败时返回null而不是抛错。服务端提供的 group 元数据GET /admin/telemetry-properties由 controllers/admin.ts 的telemetryPropertiesaction 实现要求已认证的管理员身份返回的字段及其计算方式均摘自该 action 源码useTypescriptOnServer/useTypescriptOnAdmin懒加载strapi/typescript-utils分别探测项目根目录与src/admin是否使用 TypeScriptisHostedOnStrapiCloud判断环境变量STRAPI_HOSTING strapi.cloudnumberOfAllContentTypesstrapi.contentTypes的条目数numberOfComponentsstrapi.components的条目数numberOfDynamicZones用 lodash/fp 管道map(attributes) → flatMap(values) → sumBy(propEq(type, dynamiczone))统计所有内容类型 attributes 中的动态区数量。生命周期与会话事件以下事件由框架自动发出通常不需要在业务代码里手动添加事件触发时机说明didInitializeAdministrationuuid telemetry properties 齐备后的首次加载匿名userId: 走原生fetch而非trackUsagedidAccessAuthenticatedAdministration认证布局挂载且projectId可用时携带registeredWidgets与projectId第二个事件的源码在 AuthenticatedLayout.tsx#L82-L89当useInformationQuery()返回的projectId就绪时useEffect依赖projectId触发一次trackUsage(didAccessAuthenticatedAdministration, { registeredWidgets, projectId })——依赖数组的写法保证了每次进入已认证布局都会上报一次“管理员访问”事实。事件命名规范与类型定义前端遥测沿用与服务端遥测相同的词表并额外强调will*意图事件用户在 UI 中启动了某个动作前缀含义示例will*用户发起 / 即将执行willCreateEntry、willNavigate、willSaveContentTypedid*动作完成didCreateEntry、didSaveContentType、didPublishEntrydidNot*失败或取消didNotCreateEntry、didNotDeleteEntry事件名被定义为 Tracking.tsx 中的 TypeScript 联合类型TrackingEvent分为两组EventWithoutProperties无第二参数的约 100 个事件名如didSaveContentType、willCreateContentType、didClickOnDocLink等properties?: never强制禁止传属性EventsWithProperties带类型化属性形状的事件按业务域划分接口例如interface CreateEntryEvents { name: willCreateEntry | didCreateEntry | didNotCreateEntry; properties: { documentId?: string; status?: string; error?: unknown; fromPreview?: boolean; fromRelationModal?: boolean; }; } interface WillNavigateEvent { name: willNavigate; properties: { from: string; to: string; }; } interface DidPublishRelease { name: didPublishRelease; properties: { totalEntries: number; totalPublishedEntries: number; totalUnpublishedEntries: number; }; }从源码结构看覆盖的属性化事件域包括内容管理器的条目 CRUDCreateEntryEvents/UpdateEntryEvents/DeleteEntryEvents/PublishEntryEvents、媒体库MediaEvents、DidFilterMediaLibraryElementsEvent等、API tokenTokenEvents、引导式教程DidStartGuidedTour/DidCompleteGuidedTour/DidSkipGuidedTour、content-releases 的DidPublishRelease、CTB 的 AI 事件DidUsePresetPromptEvent、DidAnswerMessageEvent、DidUpdateCTBSchema以及首页 widgetDidOpenHomeWidgetLink等。新增事件必须更新Tracking.tsx中的联合类型调用方才能获得类型检查与自动补全绕过类型系统直接传字符串事件名在 TS 下会编译报错。插件与包的接入模式wrapper hook 而非直接 POST各插件统一从strapi/admin/strapi-admin导入useTracking在组件或 hook 中调用trackUsage。主要消费方一览包典型事件strapi/adminSettings、roles、tokens、导航、引导教程、widgetsstrapi/content-manager条目 CRUD、批量操作、列表配置、过滤器、历史记录strapi/content-type-builderSchema 编辑、AI 对话经下述 wrapperstrapi/upload媒体库操作经下述 wrapperstrapi/content-releasesdidPublishRelease两个 wrapper hook 是官方推荐的“扩展属性但不替换 API”范式CTB 的useCTBTrackinguseCTBTracking.ts包装useTracking从useCTBSession()取sessionId并自动合并ctbSessionId到每个事件的属性中同时刻意放宽了类型接受任意字符串事件名使 CTB 特有事件不必每次都去更新上游中央类型定义。Upload 的useTrackingupload/admin/src/hooks/useTracking.ts包装核心useTracking在 AI 可用时useAIAvailability()向属性中追加isAiMediaLibraryConfigured字段与服务端 upload 指标的模式保持一致。官方约定很明确为插件添加遥测时若每个事件都需要一致的额外字段优先包装核心 hook而不是自己直接向分析端点 POST——这样可以统一继承门禁、负载封装与静默失败行为。其他分析端点不走 trackUsage除标准事件外还有两处请求绕过Tracking.tsx但访问同一分析主机端点组件用途POST /api/v2/trackTracking.tsx、useTracking标准事件POST /registerUseCasePage.tsx首个管理员的 persona 登记email、rolePOST /submit-npsNpsSurvey.tsxNPS 问卷提交其中 NPS 端点可从源码直接验证NpsSurvey.tsx#L200-L204 用原生fetch向${STRAPI_ANALYTICS_URL || https://analytics.strapi.io}/submit-nps发送问卷响应负载中附带isHostedOnStrapiCloud: process.env.STRAPI_HOSTING strapi.cloud问卷的触发时机详见 NPS 文档。请求量与速率控制约定与服务端遥测不同admin 前端没有任何速率限制器或批量合并机制——每一次通过门禁的trackUsage调用都会产生一个独立的 HTTP 请求。实践中依靠以下约定控制量级will*与did*/didNot*配对只在有意义的完成点发出而不是每次按键都发属性上优先使用类别而非高基数标识符尽管部分事件确实包含documentId导航追踪willNavigate在菜单点击时触发而不是每次路由渲染都触发。文档同时给出明确约束不要在没有明确产品需求的情况下添加 per-render 或高频追踪。window.strapi 上的遥测字段render.ts 在挂载 admin 应用前初始化window.strapi与遥测相关的字段为window.strapi.telemetryDisabled process.env.STRAPI_TELEMETRY_DISABLED true; window.strapi.projectType Community | Enterprise; // 由 /admin/project-type 返回后更新其中projectType初始为Community随后render.ts会调用GET /admin/project-type并以getProjectType({ isEE, planPriceId })更新它render.ts#L88-L113失败时保持默认值不报错。这些全局字段的完整 TypeScript 声明在 admin/custom.d.ts 的BrowserStrapi接口中包括telemetryDisabled: boolean与projectType: Community | Growth | Enterprise。新增一个前端遥测事件的检查清单命名——遵循will*/did*/didNot*约定更新类型——加入EventWithoutProperties或在 Tracking.tsx 中新建属性接口并纳入EventsWithProperties联合调用trackUsage——在组件或 hook 的正确生命周期时机按钮点击、mutation 成功/失败调用属性设计——用eventProperties承载动作上下文项目与设备元数据交给自动填充的groupProperties/userProperties插件场景——从strapi/admin/strapi-admin导入若每个事件都需要额外字段考虑写一个 wrapper hook测试——mockaxios.post和/或useTracking参考Tracking.test.tsx与各插件的__mocks__/useTracking.ts。特别提醒不要为纯服务端功能例如 MCP 类能力添加前端追踪——那类场景应使用服务端的strapi.telemetry.send参见 Server-side telemetry 文档。测试实践Tracking.test.tsx 是前端遥测的行为契约覆盖三类断言负载形状断言axios.post以https://analytics.strapi.io/api/v2/track为 URL 被调用且 body 含userId、eventProperties、groupProperties、userProperties.deviceType门禁行为telemetryDisabled为真或缺少uuid时不发出请求失败降级axios.postreject 时trackUsage静默返回而非抛错。插件侧测试则普遍采用jest.mock(strapi/admin/strapi-admin, () ({ useTracking: ... }))或本地__mocks__/useTracking.ts来隔离遥测依赖避免单测产生真实网络调用。小结Strapi 管理后台的前端遥测是一个“轻量、匿名、可整体关闭”的浏览器端事件体系TrackingProvider负责聚合 uuid 与服务端 group 元数据useTracking().trackUsage以类型安全的联合类型约束事件名与属性两层门禁uuidtelemetryDisabled保证尊重用户与环境的关闭配置SHA-256 邮箱哈希保证不上报个人标识原文。对插件开发者而言正确的接入姿势是包装核心 hook 附加属性并更新Tracking.tsx的类型定义让新事件进入编译期检查——这套约定与 docs/docs/docs/01-core/admin/04-features/telemetry.md 文档、Tracking.tsx 实现及其测试用例完全一致。【免费下载链接】strapi Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable, and developer-first.项目地址: https://gitcode.com/GitHub_Trending/st/strapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

最新新闻

日新闻

周新闻

月新闻