由于 utools 插件的限制,不能引用远程js,所以一般用于网页的三方统计使用都不太方便。

umami 是一款开源的访问、埋点流量统计系统,可自行部署,也有官方SaaS版。
2025-05-06T14:27:31.png
由于umami默认开启了机器人(蜘蛛)检测,utools 又定制了请求头大的userAgent字段,导致被识别成bot。
自己部署可以通过 DISABLE_BOT_CHECK = 1 参数关闭检测。
官方SaaS版可以通过api,使用node http模块发送请求:
把官方的node SDK 稍微改一下就行:

'use strict';
Object.defineProperty(exports, '__esModule', {
  value: true
});
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
  enumerable: true,
  configurable: true,
  writable: true,
  value
}) : obj[key] = value;
var __publicField = (obj, key, value) => {
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  return value;
};
class Umami {
  constructor(options = {}) {
    __publicField(this, "options");
    __publicField(this, "properties");
    this.options = options;
    this.properties = {};
  }
  init(options) {
    this.options = {
      ...this.options,
      ...options
    };
  }
  /**
  这里将原本用fetch实现的send方法 改为http模块实现
  **/
  send(payload, type = "event") {
    var {
      hostUrl,
      userAgent
    } = this.options;
    const httpModule = hostUrl.startsWith('https:') ? require('https') : require('http');
    const parsedUrl = new URL(hostUrl);
    try {
      userAgent = userAgent || `Mozilla/5.0 (${(() => {
        const os = require('os');
        const platformMap = {
          'darwin': `Macintosh; Intel Mac OS X ${os.release().replace(/\./g, '_')}`,
          'win32': `Windows NT ${os.release()}; Win64; x64`,
          'linux': `X11; Linux ${os.release()}`
        };
        return platformMap[process.platform] || 'Unknown Platform';
      })()}) Chrome/${process.versions.chrome}`;
    } catch (e) {
      console.error(e)
    }
    console.log(userAgent)
    return new Promise((resolve, reject) => {
      const req = httpModule.request({
        hostname: parsedUrl.hostname,
        port: parsedUrl.port,
        path: '/api/send',
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'User-Agent': userAgent || `Mozilla/5.0 Umami/${process.version}`,
        }
      }, (res) => {
        let data = '';
        res.on('data', chunk => data += chunk);
        res.on('end', () => {
          if (res.statusCode >= 200 && res.statusCode < 300) {
            resolve(data);
          } else {
            reject(new Error(`Request failed with status ${res.statusCode}`));
          }
        });
      });
      req.on('error', reject);
      req.write(JSON.stringify({
        type,
        payload
      }));
      req.end();
    });
  }
  track(event, eventData) {
    const type = typeof event;
    const {
      websiteId
    } = this.options;
    switch (type) {
      case "string":
        return this.send({
          website: websiteId,
          name: event,
          data: eventData
        });
      case "object":
        return this.send({
          website: websiteId,
          ...event
        });
    }
    return Promise.reject("Invalid payload.");
  }
  identify(properties = {}) {
    this.properties = {
      ...this.properties,
      ...properties
    };
    const {
      websiteId
    } = this.options;
    return this.send({
      website: websiteId,
      data: {
        ...this.properties
      }
    }, "identify");
  }
  reset() {
    this.properties = {};
  }
}
const umami = new Umami();
exports.Umami = Umami;
exports.default = umami;

使用方法不变:

umami.init({
      websiteId: 'your websiteId', // Your website id
      hostUrl: 'https://cloud.umami.is', // URL to your Umami instance
 });
 umami.track({ url: '/onPluginReady' });

这里有个小细节需要注意,track 方法的参数 “name” 如果传了会被识别为事件,只会在事件页面显示,页面统计就看不到了。

详细使用方法见文档:
https://umami.is/docs/api/node-client
官网:https://umami.is/
github:https://github.com/umami-software/umami

标签: utools, umami