npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@macroui/event-tracker

v1.3.1

Published

A self-developed web event tracking SDK, inspired by Sensors Analytics. Supports image/beacon/ajax/batch send, full auto-tracking, WebView bridge, and pluggable encryption.

Readme

@macroui/event-tracker

自研的 Web 埋点 SDK,参考神策 sa-sdk-javascript 的 API 风格

4 种发送方式 / 全埋点 / WebView 桥 / 加密插件 —— 全 TypeScript 源码,全 Jest 单测

Coverage Tests License TypeScript

特性

  • 多发送方式image / beacon / ajax / batch,自动降级
  • 多 sink 上报server_url: string | string[]
  • 预置事件$pageview / $WebClick / $WebStay / $SignUp / $BindID / $UnbindID
  • 公共属性$lib / $app_id / $screen_width / $viewport_width / $url / $referrer / $latest_utm_* ...
  • 用户身份distinct_id / anonymous_id / first_id / login_id / original_id
  • 3 阶段拦截器buildDataStage / businessStage / sendDataStage,priority 排序
  • 7 生命周期钩子sdkReady / sdkInitPara / sdkAfterInitPara / sdkInitAPI / sdkAfterInitAPI / changeDistinctId / switch
  • 加密插件:XOR+Base64 / AES-GCM(Web Crypto)
  • WebView 桥:vapph5 协议,自动取 app_version / app_id / channel
  • 失败重试:指数退避 1s→2s→4s→30s cap
  • 失败队列:localStorage 暂存,断网时延后上报
  • 跨实例通信BroadcastChannel(localStorage 兜底)
  • 签名身份HMAC-SHA256 防 cookie 篡改
  • 13 个官方插件:pageload / pageleave / exposure / session-event / debug-sender / indexeddb-sender / auto-track / webview-bridge / encrypt / etc.
  • TypeScript:完整 .d.ts,IDE 提示
  • 多格式ESM / CJS / UMD / UMD-min
  • 零依赖:核心 SDK 无第三方依赖
  • 测试:Jest 90 测试 / 15 套件 + fast-check 属性测试 + tsd 类型测试
  • 覆盖率:51% lines(开发期阈值:30%)

快速开始

安装

npm install @macroui/event-tracker

初始化(UMD)

<script src="https://cdn.jsdelivr.net/npm/@macroui/event-tracker/dist/event-tracker.min.js"></script>
<script>
  eventTracker.init({
    app_id: 'demo',
    server_url: 'https://api.example.com/sa',
    send_type: 'beacon', // 'image' | 'beacon' | 'ajax' | 'batch'
    debug: 1,            // 0=关闭 1=basic 2=verbose
  });
  eventTracker.track('user_login', { method: 'email' });
</script>

ESM

import { EventTracker, pageLoad, sessionEvent } from '@macroui/event-tracker';

const sdk = new EventTracker();
sdk.init({
  app_id: 'demo',
  server_url: 'https://api.example.com/sa',
  send_type: 'ajax',
});

sdk.use(pageLoad());
sdk.use(sessionEvent());

sdk.track('button_click', { btn_id: 'submit' });
sdk.setProfile({ $city: 'Beijing', $plan: 'pro' });

多 sink / 多实例

sdk.switchServer(['https://primary.example.com/sa', 'https://backup.example.com/sa']);

const tracker2 = initPara({
  app_id: 'demo',
  server_url: 'https://api2.example.com/sa',
  client_id: 'm2',
});

API 一览

事件

| API | 说明 | |---|---| | track(event, props, cb?) | 自定义事件 | | trackSignup(userId, props?, cb?) | 注册即触发($SignUp) | | trackLinkage(props, cb?) | 关联事件 | | trackLink(el, props?, cb?) | 单链接点击 | | trackLinks(els, props?, cb?) | 多链接点击 | | trackHeatMap(props, cb?) | 热力图事件 | | trackWebClick(props, cb?) | $WebClick | | trackWebStay(props, cb?) | $WebStay | | alias(newId, originalId?) | 合并身份 |

Profile

| API | 说明 | |---|---| | setProfile(props, cb?) | 设置 | | setOnceProfile(props, cb?) | 仅首次 | | incrementProfile(props, cb?) | 累加 | | appendProfile(props, cb?) | 追加 | | unsetProfile(prop, cb?) | 取消 | | deleteProfile(cb?) | 删除 |

身份

| API | 说明 | |---|---| | identify(id, save=true) | 设置 distinct_id | | login(id) | 登录 | | logout(newAnon?) | 登出 + 重置匿名 | | resetAnonymousIdentity(newAnon?) | 同 logout | | getDistinctId() | 当前 distinct_id | | getAnonymousId() | 匿名 ID | | getFirstId() | 首次访问 ID | | getLoginId() | 登录 ID | | getOriginalId() | 登录前 ID |

公共属性

| API | 说明 | |---|---| | register(props) | 永久属性 | | registerOnce(props) | 一次性 | | registerPage(props) | 页面(一次性) | | registerSession(props) | 会话(永久) | | registerSessionOnce(props) | 会话(一次性) | | clearAllRegister() | 清空 | | unsetRegister(key) | 单个清空 |

控制

| API | 说明 | |---|---| | flush() | 强制 flush batch + failed queue | | waitUntilIdle() | 等待所有 in-flight 完成 | | abort(reason?) | Abort 所有挂起任务 | | close() / shutdown() | 完整关闭 | | disable() / enable() | 禁用 / 启用 | | setServerURL(url) | 切换 sink | | use(plugin) | 注册插件 | | getPresetProperties() | 当前 preset |

插件

13 个官方插件,按场景分组:

自动采集

  • pageLoad() — $WebPageLoad(性能 API)
  • pageLeave() — $WebPageLeave(visibilitychange)
  • exposure(opts) — $element_exposure(IntersectionObserver)
  • sessionEvent(opts) — $session_start / $session_end
  • autoTrack() — pageview / webclick / webstay

发送增强

  • debugSender(opts) — debug 模式(GET 到 ?debug URL + alert)
  • indexedDBSender(opts) — 写到 IDB outbox
  • webviewBridge() — vapph5 协议

安全 / 隐私

  • encryptor({ encrypt, decrypt?, encryptEvent?, decryptEvent? }) — 通用加密
  • xorEncryptor(key) — XOR+Base64 便捷工厂
  • aesGcmEncryptAsync(key) / aesGcmDecryptAsync(key) — AES-GCM

Plugin Authoring Guide

写自定义插件非常简单:

import type { Plugin, InstallContext } from '@macroui/event-tracker';

export function myPlugin(): Plugin {
  return {
    name: 'my-plugin',
    install({ stages, config, sdk }: InstallContext) {
      // 注册阶段拦截器
      stages.sendDataStage.register({
        name: 'my-modifier',
        priority: 50,                         // 越大越晚
        entry(ctx) {
          // 修改 ctx.data(事件或属性)
          if (ctx.data && ctx.data.properties) {
            ctx.data.properties.$my_plugin = 'ran';
          }
        },
      });
    },
    uninstall({ config }) {
      // 清理工作:删除 config 字段、解除事件监听等
    },
  };
}

sdk.use(myPlugin());

阶段(stage)约定

| 阶段 | 用途 | 推荐 priority | |---|---|---| | buildDataStage | 事件构造后,encrypt / send 之前 | 1-50(低) | | businessStage | 业务校验 / 转换 / 风控 | 50-150 | | sendDataStage | 实际发送 / 加密 / 落盘 | 100+(高) |

生命周期钩子

install({ sdk }) {
  sdk.getRegistry().on('sdkReady', (cfg) => { /* cfg: TrackerConfig */ });
  sdk.getRegistry().on('changeDistinctId', (id) => { /* 用户切换身份 */ });
}

钩子列表:sdkReady / sdkInitPara / sdkAfterInitPara / sdkInitAPI / sdkAfterInitAPI / changeDistinctId / switch

加密 / 解密

import { encryptor, aesGcmEncryptAsync, aesGcmDecryptAsync } from '@macroui/event-tracker';

sdk.use(encryptor({
  encrypt: aesGcmEncryptAsync('my-32-byte-secret-key-1234567890ab'),
  decrypt: aesGcmDecryptAsync('my-32-byte-secret-key-1234567890ab'),
  encryptEvent: (e) => {
    // 脱敏:去掉 PII 字段
    if (e.properties?.phone) delete e.properties.phone;
    return e;
  },
}));

⚠️ aesGcmEncrypt 同步版本仅做 API 完整性占位(Web Crypto 是异步的); 真同步场景请用 XOR(xorEncryptor)。

失败处理

SDK 包含三层失败保护:

  1. 重试max_retry_count × 指数退避(默认 3 次)
  2. 失败队列:失败的事件入 localStorage,下次启动重发
  3. flush():手动强制 flush batch + failed queue
sdk.track('important_event');
await sdk.waitUntilIdle(); // 等待所有 in-flight

// 出错捕获
sdk.track('foo', {}, (err) => {
  if (err) console.error('send failed:', err);
});

从神策 v1.27 / v2.0 迁移

| 神策 API | event-tracker | 状态 | |---|---|---| | init(config) | init(config) | ✅ 完全兼容字段名 | | track(name, props) | track(name, props) | ✅ | | trackSignup(userId) | trackSignup(userId) | ✅ | | profileSet(props) | setProfile(props) | ✅ 别名 setProfile | | profileSetOnce(props) | setOnceProfile(props) | ✅ | | register(props) | register(props) | ✅ | | initPara(config) | initPara(config) | ✅ | | registerAppid(id) | registerAppid(id) | ✅ | | alias(newId) | alias(newId) | ✅ | | trackLinkage / trackLink / trackLinks | 同名 | ✅ | | trackHeatMap / trackWebClick / trackWebStay | 同名 | ✅ | | debug_mode 集成 | debugSender({ url }) 单独插件 | ⚠️ 需 use | | 38 个官方插件 | 13 个核心插件 | ⚠️ 关键已覆盖 | | 加密 encode | encryptor({ encrypt }) | ⚠️ 插件化,需 use |

开发

git clone https://github.com/macroui/event-tracker
cd event-tracker
npm install

# 开发
npm run typecheck      # tsc --noEmit
npm run lint           # eslint
npm test               # Jest
npm run test:cov       # 覆盖率
npm run test:bench     # 性能基准
npm run test:types     # 类型测试(tsd)

# 构建
npm run build          # rollup + tsc-dts

架构

src/
├── core/
│   ├── tracker.ts          主类(init + 公共 getter)
│   ├── track-api.ts        track 家族方法
│   ├── identity-api.ts     identify / login / logout / alias
│   ├── profile-api.ts      profile set/append/...
│   ├── register-api.ts     register / registerOnce
│   ├── send-pipeline.ts    sendEvent + flush + waitUntilIdle
│   ├── identity.ts         IdentityManager
│   ├── uuid.ts             UUID v4
│   ├── logger.ts           日志
│   ├── env.ts              浏览器能力
│   ├── stage.ts            StageChain(3 阶段)
│   ├── lifecycle.ts        7 生命周期钩子
│   ├── plugin.ts           PluginRegistry
│   ├── instance-channel.ts 跨实例通信
│   ├── retry-policy.ts     指数退避
│   ├── failed-queue.ts     失败队列
│   ├── profile-store.ts    用户档案(v1.2)
│   ├── signed-identity.ts  HMAC 签名
│   ├── errors.ts           SDKError 体系
│   └── instance-factory.ts initPara / registerAppid
├── storage/                KVStore + IndexedDB
├── send/                   ImageSender / BeaconSender / AjaxSender / BatchSender
├── presets/                预置属性
├── plugins/                13 个插件
└── types/                  TrackerConfig(10 个子集)+ EventData + 常量

路线图

  • v1.0:基础 6 插件 ✅
  • v1.1:完整神策 API + 3 阶段 + 7 钩子 + 多 sink + 加密 + 重试 + 跨实例 ✅
  • v1.1.1:架构重构 + 类型分层 + 错误体系 + signedIdentity + 9 个测试套件 ✅
  • v1.2:plugin marketplace / web worker / WebAssembly 加密
  • v2.0:service worker / Source Map / 多端协议统一

许可

MIT