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

yl-tracker-sdk

v1.1.2

Published

Multi-tenant user behavior tracking SDK for Nuxt/Vue/React

Readme

yl-tracker-sdk

多租户用户行为埋点 SDK — Nuxt 3 (SSR) / Vue 3 / React 18+ / Vanilla TS,开箱即用

A multi-tenant front-end analytics SDK with first-touch UTM attribution, auto page-view & click tracking, batched send with retry, and SSR-safe storage.

npm version npm downloads bundle size license TypeScript

✨ 特性 / Features

| 能力 | 说明 | |------|------| | 🏢 多租户隔离 | 所有存储键带 ana_{appId}_ 前缀,同一域名可安全接入多个应用 | | 🧭 自动页面浏览 | 监听 SPA 路由变化,自动上报 $page_view | | 🖱️ 自动点击采集 | 事件委托,捕获 tag/text/href/xpath,无侵入 | | ⏱️ 页面停留时长 | 记录进入/离开时间,自动附带 page_stay_time | | 🎯 UTM 首触点归因 | 仅在首次访问时持久化,后续跨会话保留 | | 🔄 会话管理 | 30 分钟无活动自动开新会话(可配) | | 📦 批量发送 | 默认 10 条/批、5s 间隔,支持 Beacon 降级和指数退避重试 | | 🌐 SSR 友好 | Nuxt 3 提供 createNuxtServerTracker,自动从请求头提取 IP/UA/Cookie | | 🍪 可插拔存储 | 内置 localStorage / Memory / Cookie 三种,可自定义 | | 🪶 轻量 | 主入口 gzip 后约 4.8 kB,零运行时依赖 | | 📜 完整类型 | 全量 .d.ts 导出,IDE 智能提示开箱即用 |

📦 安装 / Installation

# pnpm(推荐)
pnpm add yl-tracker-sdk

# npm
npm install yl-tracker-sdk

# yarn
yarn add yl-tracker-sdk

按框架导入对应子包,构建工具会自动 tree-shake:

import { Tracker } from 'yl-tracker-sdk'        // 核心类(任意环境)
import { ... } from 'yl-tracker-sdk/nuxt'       // Nuxt 3 专用
import { ... } from 'yl-tracker-sdk/vue'        // Vue 3 专用
import { ... } from 'yl-tracker-sdk/react'      // React 18+ 专用

🚀 快速开始 / Quick Start

Nuxt 3 (推荐,支持 SSR)

// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      tracker: {
        appId: 'my_app',
        apiUrl: 'https://api.example.com/api/track',
      },
    },
  },
})
// plugins/tracker.client.ts
import { createNuxtTracker } from 'yl-tracker-sdk/nuxt'

export default defineNuxtPlugin((nuxtApp) => {
  const config = useRuntimeConfig()
  const tracker = createNuxtTracker(config.public.tracker)

  nuxtApp.provide('tracker', tracker)
})
<!-- 任意 .vue 文件 -->
<script setup lang="ts">
const { $tracker } = useNuxtApp()
$tracker.track('login_success', { method: 'email' })
</script>

SSR 场景需在服务端补一个 plugins/tracker.server.ts,完整示例见下方 "Nuxt 3 SSR 集成" 章节。

Nuxt 3 SSR 集成

SSR 下需要在服务端用一个单独的 tracker 实例(读不到 localStorage,要用 Cookie 共享 ID),并在响应回写 Set-Cookie:

// plugins/tracker.server.ts
import { createNuxtServerTracker } from 'yl-tracker-sdk/nuxt'

export default defineNuxtPlugin((nuxtApp) => {
  const config = useRuntimeConfig()
  const event = useRequestEvent()
  const { tracker, cookieAdapter } = createNuxtServerTracker(
    config.public.tracker,
    event,
  )

  // 把 ID 写回 Cookie,让客户端能接力
  const headers = cookieAdapter.getSetCookieHeaders()
  if (event?.node?.res && headers.length) {
    event.node.res.setHeader('Set-Cookie', headers)
  }

  // 异步事件别忘了在请求结束时 flush
  event?.node?.res?.on?.('close', () => {
    tracker.flush().catch(() => {})
  })

  return {
    provide: { tracker },
  }
})
// plugins/tracker.client.ts
import { createNuxtTracker } from 'yl-tracker-sdk/nuxt'

export default defineNuxtPlugin((nuxtApp) => {
  const config = useRuntimeConfig()
  const tracker = createNuxtTracker(config.public.tracker)

  return {
    provide: { tracker },
  }
})

Vue 3

// main.ts
import { createApp } from 'vue'
import { TrackerPlugin } from 'yl-tracker-sdk/vue'
import App from './App.vue'

const app = createApp(App)
app.use(TrackerPlugin, {
  appId: 'my_app',
  apiUrl: 'https://api.example.com/api/track',
})
app.mount('#app')
<script setup lang="ts">
import { useTracker } from 'yl-tracker-sdk/vue'

const { track, setUserId } = useTracker()

function handleLogin(userId: string) {
  setUserId(userId)
  track('login_success')
}
</script>

React 18+

// main.tsx
import { TrackerProvider } from 'yl-tracker-sdk/react'

function App() {
  return (
    <TrackerProvider
      appId="my_app"
      apiUrl="https://api.example.com/api/track"
    >
      <Router />
    </TrackerProvider>
  )
}
// 任意组件
import { useTracker } from 'yl-tracker-sdk/react'

function LoginButton() {
  const { track, setUserId } = useTracker()

  const handleLogin = (userId: string) => {
    setUserId(userId)
    track('login_success', { method: 'google' })
  }

  return <button onClick={() => handleLogin('user_123')}>Login</button>
}

Vanilla / 其他框架

import { Tracker, BrowserStorage } from 'yl-tracker-sdk'

const tracker = new Tracker(
  {
    appId: 'my_app',
    apiUrl: 'https://api.example.com/api/track',
  },
  new BrowserStorage(),
)

tracker.track('button_click', { btn: 'submit' })

📖 核心 API

tracker.track(eventName, properties?)

手动追踪自定义事件。事件会进入发送队列,按 batchSize / flushInterval 批量上报。

tracker.track('purchase', { price: 99, currency: 'CNY', sku: 'A001' })

tracker.trackPageView(properties?)

手动触发一次页面浏览事件。默认情况下 SDK 会在 SPA 路由切换时自动调用。

tracker.setUserId(userId) / tracker.clearUserId()

登录/登出时调用,会持久化到存储并附带在之后所有事件上。

tracker.setUserId('user_123')
// ...
tracker.clearUserId()  // 登出

tracker.setUserProperties(props)

设置用户属性(如 VIP 等级、用户名等),合并到之后所有事件的 properties 中,自动持久化。

tracker.setUserProperties({ vip_level: 'gold', register_date: '2024-01-01' })

tracker.flush()

立即刷新发送队列,返回 Promise。SSR 环境下需要在请求结束时调用,否则事件可能丢失。

await tracker.flush()

tracker.destroy()

停止定时器、解绑事件监听,会先尝试 flush 剩余事件。SPA 卸载或测试时调用。

tracker.getAnonymousId() / tracker.getSessionId()

获取当前访客的匿名 ID(首次访问时生成,永久保留)和会话 ID(30 分钟无活动后重置)。

⚙️ 配置项 / Configuration

interface TrackerConfig {
  /** 必填 · 应用 ID(多租户隔离的 key) */
  appId: string

  /** 必填 · 上报接口地址,如 https://api.example.com/api/track */
  apiUrl: string

  /** 可选 · API Key(后端鉴权,优先级高于 appId) */
  apiKey?: string

  /** 批量发送条数,默认 10 */
  batchSize?: number

  /** 批量发送间隔(毫秒),默认 5000 */
  flushInterval?: number

  /** 调试模式:打印事件 payload,默认 false */
  debug?: boolean

  /** 自动采集页面浏览,默认 true */
  autoTrackPageView?: boolean

  /** 自动采集点击事件,默认 true */
  autoTrackClick?: boolean

  /** 会话超时(毫秒),默认 1800000(30 分钟) */
  sessionTimeout?: number

  /** 自定义追踪参数名列表,首触点归因,自动持久化并附加到所有事件 */
  trackingParams?: string[]
}

🧠 自动采集规则

| 事件 | 触发时机 | 附带属性 | |------|---------|---------| | $page_view | 初始化 + SPA 路由切换 | $url, $url_path, $title, $referrer | | $click | 全局事件委托捕获点击 | tag_name, text, href, class_name, id, xpath | | page_stay_time | 下一次 page_view 触发时附带 | 上一个页面的停留毫秒数 |

如需禁用,把对应 autoTrackXxx 设为 false 即可。

🗃️ 自定义存储

默认使用 localStorage。如需 Cookie(SSR 共享)或纯内存(隐私模式):

import { Tracker, CookieStorage, MemoryStorage } from 'yl-tracker-sdk'

// Cookie 存储(SSR 场景常用)
new Tracker(config, new CookieStorage(cookieAdapter))

// 内存存储(浏览器关闭即丢)
new Tracker(config, new MemoryStorage())

// 写你自己的存储:实现 { get, set, remove } 三个方法即可
class MyStorage {
  get(key: string) { /* ... */ }
  set(key: string, value: string) { /* ... */ }
  remove(key: string) { /* ... */ }
}
new Tracker(config, new MyStorage())

🛡️ 数据格式

上报到 apiUrl 的请求体为 JSON,结构如下:

interface TrackEvent {
  app_id: string                                    // 租户 ID
  event_name: string                                // 事件名
  user_id?: string                                  // 登录后才有
  anonymous_id: string                              // 匿名 ID(永久)
  session_id: string                                // 会话 ID
  timestamp: number                                 // 毫秒时间戳
  properties?: Record<string, any>                  // 自定义属性(含用户属性)
  context?: {                                       // 环境信息
    url?: string
    url_path?: string
    title?: string
    referrer?: string
    user_agent?: string
    screen?: string
    platform?: string
    viewport_width?: string
    viewport_height?: string
    screen_width?: string
    screen_height?: string
    timezone_offset?: string
    language?: string
    ip?: string                                     // SSR 注入
  }
  utm?: {                                           // 首触点归因
    utm_source?: string
    utm_medium?: string
    utm_campaign?: string
    utm_term?: string
    utm_content?: string
  }
  event_duration?: number                           // 事件耗时(可选)
  page_stay_time?: number                           // 页面停留时长(可选)
}

🌐 浏览器兼容性

  • Chrome / Edge / Firefox / Safari 最近 2 个大版本
  • 移动端 iOS Safari 14+、Android Chrome 90+
  • SSR:Node.js 18+ (Nuxt 3 / Nitro)

🛠️ 开发 / Development

# 装依赖
pnpm install

# 开发(监听文件变化并构建)
pnpm dev

# 完整构建(产物在 dist/)
pnpm build

# 跑测试
pnpm test

📚 文档 / Documentation

本 README 已覆盖所有公共 API、配置项、框架集成方式,适合作为接入起点。

🔒 团队内部详细文档(业务接入指南、管理后台、部署手册等)在源码仓库的 docs/ 目录,通过内网 GitLab 访问,不公开发布。

🤝 贡献 / Contributing

PR / Issue 欢迎!请确保:

  • 通过 pnpm test
  • 保持 100% TypeScript 类型覆盖
  • 公共 API 变更请先开 issue 讨论

📄 License

MIT © 2024-present