跳至内容
Vercel+Umami实现网站流量监控

Vercel+Umami实现网站流量监控

想给自己的博客加个流量统计,又不想用 Google Analytics 那么重的,就折腾了下 Umami。Vercel 一键部署,免费 Neon 数据库,跑起来挺快。但 vercel.app 域名国内得翻墙才能访问,踩了个坑。试了两种方案:一是 Cloudflare Worker 做代理,二是直接绑自己的域名。最后选了绑域名,管理后台和统计脚本都走国内可直连的地址,舒服多了。记录一下完整流程,省得以后重装再查一遍。

1.Fork 官方仓库

在 Vercel 上,通过 Fork Umami 的 GitHub 仓库,将仓库复制到你的 GitHub 账号中。

2.导入Umami项目

打开 https://vercel.com,如果没有账号需要先注册,来到 Overview 面板,点击 Add New,选择 Project

选择刚刚 fork 的 umami 项目,点击 Import,然后直接点击最下方Deploy,因为我们未提供环境变量,Vercel 会提示部署失败。不过没关系,我们先把这个Project创建起来了。

3.创建数据库

Vercel 上进入 Storage 界面。点击 Create Database,因为Umami 官方文档要求使用 PostgreSQL, 所以我们选择 Neon (Serverless Postgres)数据库类型。

所在区域选默认推荐的即可,我这里显示的是华盛顿特区。

Install Plan选择Free即可,容量够我们用的了。

在创建数据库的最后步骤中,它会让你选需要连接的Project,选择我们刚才创建的umami项目即可(其他配置项不用动,包括前缀那个)。

4.重新部署 umami 项目

连接好数据库后,就可以重新部署了,点击 umami 项目,进入 Deployments 面板,找到刚才部署失败的 deployment,点击 Redeploy 重新部署,成功部署大约需要几分钟时间。

5.使用 umami 监控网站

部署完成之后,我们从部署详情中可以看到,Umami的访问地址,类似xxx.vercel.app/login这样的,初始账号密码:

  • UserName: admin
  • Password: umami

首次登录后,在左下角切换Language,然后修改管理员密码。

然后点击 Settings 面板,选择 Websites,点击 Add Website 按钮添加需要监控的域名。

接下来,为需要监控的网站添加 tracking code,点击刚刚添加的Website最右侧的 Edit,进入刚刚添加的网站,其中有一段跟踪代码,将这段 script 添加到网站的 <head></head> 中。

以 hugo 为例,我使用的hextra主题,无法直接修改主题文件。我的做法是直接复制一份 hextra 的 layouts/partials/head.html 文件到自己的 hugo 项目中,添加上 umami 提供的 tracking code。

6.Cloudflare配置Worker代理(vercel.app访问限制解决方式一)

我的 umami 在 vercel, 但 vercel.app 这个域名不翻墙好像访问不到,我的 blog 在 cloudflare上,所以我打算通过Worker代理的方式。通过 Cloudflare Worker 代理,不仅能解决 vercel.app 域名被屏蔽的问题,还能顺带解决广告拦截器屏蔽统计脚本的问题,一举两得。具体步骤如下:

6.1 创建并配置 Cloudflare Worker

  • 登录 Cloudflare 后台,进入 Workers 和 Pages 面板,点击 创建应用程序 > 创建 Worker,给你的 Worker 起个名字(比如 umami-proxy)。
// 1. 请将此处的 URL 替换为你的 Vercel Umami 地址
const UMAMI_HOST = 'https://你的项目名.vercel.app'; 
const UMAMI_RAW_DOMAIN = '你的项目名.vercel.app';
const PROXY_DOMAIN = 'umami.yourblog.com'; // 你的Cloudflare子域名

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    const { pathname, search } = url;

    // 统一构造上游请求公共逻辑
    const buildUpstreamReq = (targetUrl) => {
      const upstreamReq = new Request(targetUrl, {
        method: request.method,
        headers: request.headers,
        body: request.body,
        redirect: 'manual'
      });
      // 修正Host头,适配Vercel
      upstreamReq.headers.set('Host', UMAMI_RAW_DOMAIN);
      upstreamReq.headers.delete('cf-worker');
      // 不要删除Cookie,否则登录直接401
      return upstreamReq;
    }

    // 统一处理3xx重定向:替换Location里的vercel域名
    const rewriteRedirect = async (res) => {
      const location = res.headers.get('location');
      if (!location) return res;

      const newHeaders = new Headers(res.headers);
      // 把vercel域名全部替换为你的代理域名
      const fixedLoc = location.replaceAll(UMAMI_RAW_DOMAIN, PROXY_DOMAIN);
      newHeaders.set('location', fixedLoc);
      return new Response(null, {
        status: res.status,
        headers: newHeaders
      });
    }

    // --- 处理 /script.js 缓存分支 ---
    if (pathname.endsWith('.js')) {
      let response = await caches.default.match(request);
      if (!response) {
        const upstreamRequest = buildUpstreamReq(`${UMAMI_HOST}/script.js`);
        response = await fetch(upstreamRequest);

        // 捕获重定向并改写地址
        if (response.status >= 300 && response.status < 400) {
          return rewriteRedirect(response);
        }

        if (response.status === 200) {
          ctx.waitUntil(caches.default.put(request, response.clone()));
        }
      }
      return response;
    }

    // --- 页面/API 通用转发分支 ---
    const upstreamUrl = `${UMAMI_HOST}${pathname}${search}`;
    const upstreamRequest = buildUpstreamReq(upstreamUrl);

    const response = await fetch(upstreamRequest);

    // 重写跳转地址,不再直接返回原始302
    if (response.status >= 300 && response.status < 400) {
      return rewriteRedirect(response);
    }

    return response;
  },
};

点击保存并部署

6.2 为 Worker 绑定自定义域名

  • 为了让统计脚本更稳定,建议给 Worker 绑定一个你自己的域名(如 umami.yourblog.com)。
  • 在 Worker 的 设置 > 触发器 > 自定义域 中添加你的域名并按提示完成 DNS 配置。

6.3 更新Blog中集成的监控代码

  • 将你博客中原来的 Umami 统计代码,修改为指向你刚刚创建的 Worker 地址。
  • 如果绑定了自定义域名(例如 umami.yourblog.com),代码应类似:
<script defer src="https://umami.yourblog.com/script.js" data-website-id="你的网站ID"></script>

6.4 访问测试

访问https://umami.yourblog.com/script.js, 如果返回这样一个界面:

image.png 这说明:Cloudflare Worker 将请求转发给了 Vercel。但 Vercel 发现这个请求来自“外部”,而你的项目设置要求只有团队成员才能访问,因此它拒绝提供服务,并展示了这个页面。

6.5 在 Vercel 上关闭部署保护

要解决这个问题,你需要登录 Vercel 后台,修改你 Umami 项目的部署保护设置,将其对公网开放

  1. 登录 Vercel:访问 vercel.com 并登录你的账户。
  2. 进入项目:在仪表盘(Dashboard)中找到并点击你的项目。
  3. 打开设置:在项目页面顶部的导航栏中,点击 “Settings” (设置) 标签。
  4. 找到部署保护:在左侧菜单中,找到 “Deployment Protection” (部署保护) 选项并点击。
  5. 关闭保护:在 “Deployment Protection” 页面,你应该能看到一个类似 “Vercel Authentication” (Vercel 身份验证) 的设置。将其切换为 “Disabled” (禁用) 或 “Off” (关闭)

然后重新测试,即可以正常返回js内容。

7.Vercel中配置另外域名(vercel.app访问限制解决方式二,推荐)

这个是针对vercel.app 必须翻墙访问的解决方式之二,和前面通过Worker代理的方式二选一即可,这个方式还有一个优势,就是访问Umami的管理台也不用翻墙了。

  • 首先删除之前的Worker。
  • Vercel 项目绑定 umami.emerex.ai 并通过所有权验证
  • Cloudflare DNS 用 CNAME 指向 Vercel(务必确保 umami.emerex.ai 的 DNS 记录在 Cloudflare 上是 “仅 DNS”(灰色云朵),而不是“已代理”(橙色云朵)。如果开启了代理,Vercel 的 SSL 证书验证会失败,导致域名无法生效。)
  • 在 Vercel 上打开部署保护,因为添加了域名后,Vercel Authentication保护会自动对该域名失效
本文为本站原创内容,除非另有声明,均采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。转载时请务必注明作者及原始链接,且不得用于商业目的。