首页
/ Cal.com 集成 Fathom Analytics:为预约事件接入隐私友好的网站分析

Cal.com 集成 Fathom Analytics:为预约事件接入隐私友好的网站分析

2026-09-08 21:13:56作者:魏侃纯Zoe

Fathom Analytics 是一款以“简单、隐私优先”为核心理念的网站分析服务,作为 GDPR 合规的 Google Analytics 替代方案,它在 Cal.com 中以内置应用(App)的形式存在,让你无需额外埋点即可跟踪预约(Booking)页面的访问与转化数据。本文以仓库中的 fathom 应用目录 为线索,完整讲解该应用的定位、安装机制、Tracking ID 配置方式,以及脚本注入到预约页面的底层渲染链路,读完你即可在自托管或云端 Cal.com 中独立完成配置并理解其实现原理。

Fathom 应用是什么

官方文档 DESCRIPTION.md 对该应用给出了精确定位:

Fathom Analytics provides simple, privacy-focused website analytics. We're a GDPR-compliant, Google Analytics alternative. Use the Fathom app to track analytics of your bookings.

翻译过来即:Fathom Analytics 提供简单、隐私优先的网站分析能力,是 GDPR 合规的 Google Analytics 替代方案;在 Cal.com 中使用 Fathom 应用,可以直接跟踪预约事件的埋点数据。这一定位同时回答了“为什么选 Fathom”——相比传统分析工具,它不依赖 Cookie 追踪,契合 GDPR 合规诉求;以及“在 Cal.com 中怎么用”——它不是独立部署的服务,而是作为事件类型(EventType)的一个扩展能力嵌入预约流程。

从包结构看,packages/app-store/fathom/ 是一个完整、自洽的应用模块,包含配置(config.json)、安装处理器(api/)、数据校验(zod.ts)与 UI 组件(components/),这使它能够无缝接入 Cal.com 的应用商店体系。

应用元数据与定位:config.json 详解

Fathom 应用的所有商店级元数据都定义在 config.json 中,这也是 Cal.com 应用商店识别、归类该应用的唯一依据:

配置字段 含义
name Fathom 应用在商店中的显示名称
slug fathom 应用唯一标识,官方注释明确要求“Don't modify slug”,如需改动须通过 CLI 编辑命令完成
type fathom_analytics 应用类型,用于在数据库中标识凭据类型
variant analytics 应用变体,归入分析类
categories ["analytics"] 应用分类,用于商店浏览与筛选
publisher Cal.com, Inc. 发布方
extendsFeature EventType 关键字段:该应用扩展的是“事件类型”功能,即按预约事件粒度生效
isOAuth false 非 OAuth 应用,无需授权码流程
appData.tag.scripts Fathom 官方脚本 注入到预约页面的脚本定义(见下文)

其中 extendsFeature: "EventType" 决定了该应用的集成深度:它不像连接器类应用那样同步日历或视频会议,而是给每个事件类型(EventType)追加一段可开关的分析脚本。typeslug 的组合则是运行时将应用与其存储数据关联起来的关键。

appData.tag:脚本注入的声明式定义

config.json 中最核心的部分是 appData.tag

"appData": {
  "tag": {
    "scripts": [
      {
        "src": "https://cdn.usefathom.com/script.js",
        "attrs": {
          "data-site": "{TRACKING_ID}"
        }
      }
    ]
  }
}

它声明:当该应用在某个事件类型上启用时,预约页面需要加载 https://cdn.usefathom.com/script.js,并携带 data-site 属性。属性值使用了 {TRACKING_ID} 占位符——这个占位符会在渲染时被替换为管理员在事件类型设置里填写的真实 Tracking ID(替换机制见下文“渲染链路”小节)。data-site 正是 Fathom 官方脚本识别站点 ID 的标准属性,与 Fathom 控制台中创建站点后生成的 ID 一一对应。

这种“配置驱动脚本注入”的设计意味着 Fathom 应用本身不包含任何服务器端埋点逻辑,完全依赖前端脚本标签完成数据采集,这是它与 Cal.com 中其他分析类应用共有的声明式(Declarative)模式。

安装机制:声明式处理器与默认凭据

Fathom 应用的安装逻辑位于 api/add.ts,整个文件只有十几行,体现了 Cal.com “声明式应用”(declarative app)的极简风格:

import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import { createDefaultInstallation } from "../../_utils/installation";
import appConfig from "../config.json";

const handler: AppDeclarativeHandler = {
  appType: appConfig.type,
  variant: appConfig.variant,
  slug: appConfig.slug,
  supportsMultipleInstalls: false,
  handlerType: "add",
  createCredential: ({ appType, user, slug, teamId }) =>
    createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};

export default handler;

关键点如下:

  • handlerType: "add" 表示这是安装型处理器,由 api/index.ts 统一导出。
  • supportsMultipleInstalls: false 表明每个用户/团队只允许安装一次——分析应用通常一个站点对应一个 ID,无需重复安装。
  • createCredential 调用 createDefaultInstallation(定义于 packages/app-store/_utils/installation 目录)创建一条空凭据记录key: {})。Fathom 不需要服务端密钥或 OAuth Token,因为真正的接入凭据是每个事件类型上独立的 Tracking ID,由用户在 UI 中填写,而非安装在应用级凭据里。这从源码结构看是“应用级空凭据 + 事件级 Tracking ID”的双层设计。

数据模型:trackingId 的 Zod 校验

事件类型上保存的 Fathom 配置由 zod.ts 定义:

import { z } from "zod";
import { eventTypeAppCardZod } from "../eventTypeAppCardZod";

export const appDataSchema = eventTypeAppCardZod.merge(
  z.object({
    trackingId: z.string().default("").optional(),
  })
);

export const appKeysSchema = z.object({});
  • appDataSchema 在共享的 eventTypeAppCardZod.ts(包含 enabledcredentialIdappCategories 三个通用字段)之上合并出 trackingId: z.string().default("").optional()——即每个事件类型可存一个字符串类型的 Tracking ID,默认为空字符串,可选。
  • appKeysSchema 为空对象,再次印证应用级密钥为空,全部配置都落在事件级别的 appData 中。

这段代码是“Tracking ID 存哪里、存什么类型”的唯一事实来源:它被写入事件类型的 metadata.apps 下对应 slug 的字段中,并在 UI 与页面渲染两侧共用同一 schema 保证类型安全。

事件类型设置界面:在哪里填写 Tracking ID

配置入口由两个组件组成:

const trackingId = getAppData("trackingId");
return (
  <TextField
    dataTestid={slug}
    name="Tracking ID"
    value={trackingId}
    disabled={disabled}
    onChange={(e) => {
      setAppData("trackingId", e.target.value);
    }}
  />
);

也就是说,你只需要在事件类型的 Fathom 卡片中填入 Fathom 控制台生成的站点 ID(Tracking ID),其余全部由系统接管。dataTestid={slug} 也便于 Playwright 等测试工具按 fathom 定位该输入框。

渲染链路:脚本如何出现在预约页面上

从应用配置到预约页面实际加载脚本,中间的关键枢纽是 BookingPageTagManager.tsx。从该文件的源码结构可以还原整条链路:

  1. BookingPageTagManager 遍历事件类型已启用的应用,读取每个应用的 app.appData.tag(注释明确说明“AnalyticApp has appData.tag always set”,即分析类应用必然携带 tag)。
  2. 取出 tag.scripts 数组,与可能的推送事件脚本合并后逐个渲染为 <script> 标签(对应 tag.scripts.concat(...)parsedAttributes 的属性解析逻辑)。
  3. 渲染前会把脚本 attrs 中的 {TRACKING_ID} 占位符替换为当前事件类型 appData 中保存的 trackingId 值——这正是 config.json"data-site": "{TRACKING_ID}"zod.tstrackingId 字段对接的落点。

因此完整的数据流是:

config.json (声明 script 模板)
        │
        ▼
zod.ts (定义 trackingId 字段并校验)
        │
        ▼
事件类型设置页 (EventTypeAppSettingsInterface 填写 Tracking ID)
        │
        ▼
BookingPageTagManager (读取 appData.tag,替换 {TRACKING_ID},注入 <script>)
        │
        ▼
预约页面 → 加载 cdn.usefathom.com/script.js → Fathom 采集数据

从源码结构看,这一“声明式 tag 渲染器”是通用的,其他分析类应用(同样通过 appData.tag.scripts 声明脚本)也复用同一条链路。

安装与使用步骤

  1. 安装应用:在 Cal.com 的应用商店中搜索并安装 Fathom(需具有事件类型管理权限)。由于 supportsMultipleInstalls: false,每个账户仅可安装一次。
  2. 创建 Fathom 站点:在 Fathom Analytics 控制台创建一个新站点,获取站点 Tracking ID(对应脚本中的 data-site 值)。
  3. 打开事件类型设置:进入任意事件类型的编辑页面,找到 Fathom 应用卡片,打开启用开关(触发 enabled 字段写入)。
  4. 填写 Tracking ID:在 “Tracking ID” 输入框中粘贴第 2 步获取的 ID,保存设置。
  5. 验证埋点:访问该事件类型的公开预约页面,在浏览器开发者工具中确认 https://cdn.usefathom.com/script.js 已加载,且 data-site 属性值为你的真实 ID;随后即可在 Fathom 控制台看到来自预约页面的实时访问数据。

总结与扩展阅读

Fathom 应用是 Cal.com 声明式应用架构的一个典型样例:配置文件声明脚本模板,Zod schema 定义数据结构,极简的 add 处理器完成空凭据安装,通用 Tag 渲染器负责把脚本注入预约页面。理解了它,也就理解了 Cal.com 应用商店中所有分析类应用的通用接入范式。

进一步探索可参考以下仓库文件:

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
924
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
599
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
394