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

@pang3fan-creator/analytics-kit

v0.5.0

Published

Typed clients for querying Google Search Console, Google Analytics 4, Microsoft Clarity, Bing Webmaster Tools, Ahrefs, and keyword difficulty data. Runtime-agnostic (Node.js / Cloudflare Workers / edge).

Readme

analytics-kit

类型安全的网站分析数据查询客户端,用于在 Node.js 项目中查询六个平台的数据:

  • Google Search Console(搜索表现:点击/展示/排名/CTR)
  • Google Analytics 4(runReport 报表)
  • Microsoft Clarity(仪表盘指标 + 实验性会话列表)
  • Bing Webmaster Tools(排名与流量 / 关键词 / 页面)
  • Ahrefs(免费公开端点:域名权重 DR 查询)
  • 关键词难度(哥飞版)(seo.web.cafe 的关键词难度分、搜索量趋势与外链预算)

零 Node 专有依赖(仅 jose),基于全局 fetch,可在 Node.js 18+ / Cloudflare Workers / Deno / Bun 中运行。刻意不使用 googleapis 等官方包,因为它们依赖的 google-auth-library/gaxios 栈无法可靠运行在 Workers 等 edge 运行时。

安装

# 发布后(推荐)
pnpm add @pang3fan-creator/analytics-kit

# 发布前的私有引用方式:
pnpm add git+ssh://[email protected]/pang3fan-creator/analytics-kit.git

前置配置(一次性)

Google(GSC + GA4 共用一套服务账号)

  1. Google Cloud Console 创建项目,启用两个 API:
    • Search Console API
    • Google Analytics Data API
  2. 创建服务账号(IAM → Service Accounts),生成 JSON 密钥并下载。
  3. 授权访问数据(最常见踩坑点,漏掉必 403):
    • GSC:设置 → 用户和权限 → 添加服务账号邮箱为用户(Restricted 权限即可)
    • GA4:管理 → 属性访问管理 → 添加服务账号邮箱为 Viewer

Microsoft Clarity

  • Clarity 项目 → Settings → Data Export → Generate new API Token(仅项目管理员可操作)
  • Token 与单个项目绑定;每个项目需要各自的 token

Bing Webmaster Tools

  • Bing Webmaster → 右上角 Settings → API Access → 接受条款 → API Key → Generate API Key
  • API Key 按账号生成(不是站点),一个 Key 可用于账号下所有已验证站点;删除后必须更新所有引用它的项目
  • 站点标识为 URL-prefix 形式(如 https://example.com/),Bing 不支持 Google 的 sc-domain: 网域资源语法

Ahrefs(当前仅免费公开端点)

  • Ahrefs → Account settings → API keys → 生成 APIv3 Key(无需付费订阅;公共端点免费、消耗 0 units)
  • 注意:site-audit/*keywords-explorer/* 等订阅端点在公共 Key 下会 401(返 ["Error","Unauthorized"]),仅 subscription-info/limits-and-usage 在付费计划下可用;本库目前只实现免费能力,付费端点待升级 Lite+ 后按需扩展
  • 域名权重数据公开显示需标注 "Domain Rating by Ahrefs"(许可条款

环境变量

| 变量 | 说明 | |---|---| | GOOGLE_SERVICE_ACCOUNT_EMAIL | 服务账号邮箱(client_email) | | GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY | 服务账号私钥(private_key),单行 \n 转义自动还原 | | GSC_SITE_URL | GSC 属性:https://example.com/sc-domain:example.com | | GA4_PROPERTY_ID | GA4 纯数字 Property ID(不是 G- 开头的数据流 ID) | | CLARITY_API_TOKEN | Clarity 项目 API Token | | BING_API_KEY | Bing Webmaster API Key(设置 → API Access → API Key,账号级) | | BING_SITE_URL | Bing 站点标识,URL-prefix 形式,如 https://example.com/ | | AHREFS_API_KEY | Ahrefs APIv3 Key(Account settings → API keys;免费公共端点无需订阅) | | KD_API_TOKEN | 关键词难度(哥飞版)API Token,在 seo.web.cafe/kd 登录后生成(wc_mcp_ 前缀) |

所有变量都可以不设——改为在创建客户端时显式传参(Cloudflare Workers 无 process.env 时用这种方式)。

用法

Google Search Console

import { createGscClient } from '@pang3fan-creator/analytics-kit'

const gsc = createGscClient() // 自动读环境变量

const result = await gsc.searchAnalytics({
  startDate: '2026-08-01',
  endDate: '2026-08-21',
  dimensions: ['query', 'page'],
  rowLimit: 1000,
})

// 自动分页拉全量(内部循环 startRow)
const allRows = await gsc.searchAnalyticsAll({
  startDate: '2026-08-01',
  endDate: '2026-08-21',
  dimensions: ['query'],
}, { maxRows: 50_000 })

结果固定按 clicks 降序;keys[] 的顺序与请求的 dimensions 一致。

Google Analytics 4

import { createGa4Client, toRowObjects } from '@pang3fan-creator/analytics-kit'

const ga4 = createGa4Client()

const report = await ga4.runReport({
  dateRanges: [{ startDate: '29daysAgo', endDate: 'today' }],
  dimensions: [{ name: 'country' }],
  metrics: [{ name: 'sessions' }, { name: 'activeUsers' }],
  returnPropertyQuota: true,
})

// 行转对象:{ country: 'China', sessions: '123', ... }
const rows = toRowObjects(report)

// 自动分页(按 rowCount 循环 offset)
const all = await ga4.runReportAll({
  dateRanges: [{ startDate: '90daysAgo', endDate: 'today' }],
  dimensions: [{ name: 'pagePath' }],
  metrics: [{ name: 'screenPageViews' }],
})

GA4 与 GSC 共享同一服务账号凭据时,access token 自动复用缓存:两个客户端默认都以合并后的只读 scopes(webmasters.readonly + analytics.readonly)请求 token,同凭据每小时只换一次。

所有客户端都支持 timeoutMs(毫秒)为每次请求注入超时:

const gsc = createGscClient({ timeoutMs: 30_000 })

Bing Webmaster Tools

import { createBingClient } from '@pang3fan-creator/analytics-kit'

const bing = createBingClient() // 自动读环境变量

// 排名与流量(按天,近一个月)
const traffic = await bing.getRankAndTrafficStats()
// [{ date: '2026-08-21', clicks: 16, impressions: 202 }, ...]

// 关键词明细(官方扁平结构:每行一个查询词)
const queries = await bing.getQueryStats()
// [{ query: 'schedule maker', clicks: 15, impressions: 100, avgClickPosition: 18, avgImpressionPosition: 17, date: '2011-09-16' }, ...]

// 页面流量(官方 Query 字段承载页面 URL)
const pages = await bing.getPageStats()

Bing 走官方 JSON/HTTP 协议(其 SOAP/POX 协议将于 2026-08-31 退役,本库只使用 JSON 端点)。单个 API Key 可查询账号下所有已验证站点,按 BING_SITE_URL 区分目标站。注意三点:

  • 位置字段粒度avgClickPosition / avgImpressionPosition 与 GSC 的 position 不同,是 Bing 原始刻度(如 18 对应 UI 显示的 1.8),展示前请自行 ÷10
  • 日期格式:微软序列化为 /Date(毫秒数±时区)/,本库已按带时区的本地日历日期归一化为 YYYY-MM-DD(不会因 UTC 截断出现跨日偏移)
  • 日期范围GetQueryStats / GetPageStats 不支持服务端日期参数,返回全量数据,需要窗口时请客户端过滤
  • 误传 sc-domain: 形式的站点标识会抛出带说明的 AnalyticsKitConfigError

Ahrefs

import { createAhrefsClient } from '@pang3fan-creator/analytics-kit'

const ahrefs = createAhrefsClient() // 自动读环境变量

// 任意域名/URL 的 Domain Rating(0 units,免费)
const dr = await ahrefs.getDomainRating('tanship.app')
console.log(dr.domainRating) // 22
console.log(dr.license)      // 署名条款 URL(公开显示时需标注 "Domain Rating by Ahrefs")

// 查看当前 Key 的计划/额度(0 units;公共 Key 会 401,需 Lite+ 计划)
const limits = await ahrefs.getLimitsAndUsage()
console.log(limits.subscription, limits.unitsUsageApiKey, limits.unitsLimitApiKey, limits.usageResetDate)

当前覆盖官方免费公开端点;site-audit / keywords-explorer 等订阅端点消耗 API units(50/次起),需要升级到 Lite 及以上后才可用(届时再按需扩展方法)。

Microsoft Clarity

import { createClarityClient } from '@pang3fan-creator/analytics-kit'

const clarity = createClarityClient()

// 官方 Export API:仅最近 1-3 天,10 次/项目/天
const insights = await clarity.getLiveInsights({
  numOfDays: 3,
  dimensions: ['Device', 'Country/Region'], // 最多 3 个
})

for (const metric of insights) {
  console.log(metric.metricName)          // 如 "Traffic"、"RageClickCount"
  for (const row of metric.rows) {
    console.log(row.dimensions)           // { Device: 'Mobile', ... }
    console.log(row.values)               // 计数字符串已转为数字
  }
}

归一化处理了官方响应的已知陷阱:

  • 计数字段是 JSON 字符串 → 已转为 number
  • 维度回显键名大小写不稳定(如 URL 回显为 Url)→ 统一映射回请求时的维度名
  • 注意:totalSessionCount 包含 bot 会话(totalBotSessionCount),人类会话需自行相减;摩擦类指标没有原始计数,只有发生率与 subTotal/sessionsCount
  • 需要原始结构时改用 getRawLiveInsights()

实验性:会话列表(走未文档化的 clarity.microsoft.com/mcp/recordings/sample 端点,即官方 MCP 服务器所用接口;无 SLA,可能随官方变更失效):

const sessions = await clarity.listSessions({
  start: new Date('2026-08-20T00:00:00Z'),
  end: new Date('2026-08-21T00:00:00Z'),
  sortBy: 'SessionDuration_DESC', // 可选,默认 SessionStart_DESC
  count: 100,                     // 上限 250
  filters: {
    deviceType: ['Mobile'],
    rageClickPresent: true,
    deadClickPresent: true,
    javascriptErrors: [''],
  },
})

响应结构未文档化,返回解析后的 JSON 原样值。

关键词难度(哥飞版)

import { createKdClient } from '@pang3fan-creator/analytics-kit'

const kd = createKdClient()

const result = await kd.estimateKeywordDifficulty({
  keyword: 'ai photo editor', // 必填,英文关键词
  gl: 'us',                   // 可选,默认 us
  hl: 'en',                   // 可选,默认 en
  force: true,                // 可选,跳过 7 天结论缓存强制重算
})

result.score          // 难度分 0–100(品牌词为「衍生内容进入难度」口径)
result.level          // '极易' | '容易' | '中等' | '困难' | '极难'
result.keywordType    // 'generic' | 'brand'(自动识别品牌词)
result.reasons        // 中文判断原因与各信号加减分明细
result.keywordVolume  // 月搜索量(可能为 null)
result.keywordTrend   // { domain, volume, estimatedValue, ratio },ratio ≥ 1 表示快速上升期
result.linkBudget     // 进入前十的引用域预算:quality / directory 两轨 low/mid/high
result.details        // 前十盘面明细:DR、访问量、域名年龄、是否专门经营、体验数据等

// 自包含 Markdown 报告(适合存档 / 转发 / 喂给 AI)
const report = await kd.estimateKeywordDifficultyMarkdown({ keyword: 'ai logo maker' })

额度说明:网页 / MCP / HTTP API 三端共用每日额度(游客 10 次、登录用户 100 次、VIP 500 次),另有每分钟 10 次的瞬时保险丝;429 错误体中的 error 字段可区分 rate(触发保险丝)与 quota(日额度用完)。

Cloudflare Workers 中使用

Workers 没有 process.env,创建客户端时显式传配置即可:

export default {
  async fetch(request: Request, env: Env) {
    const gsc = createGscClient({
      siteUrl: env.GSC_SITE_URL,
      clientEmail: env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
      privateKey: env.GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY,
    })
    // ...
  },
}

错误处理

所有失败都抛出统一的 AnalyticsKitError——HTTP 错误、网络失败、超时、外部中断和响应解析失败都不会漏网,调用方只需 instanceof 一种判断:

import { AnalyticsKitError } from '@pang3fan-creator/analytics-kit'

try {
  await gsc.searchAnalytics({ ... })
} catch (error) {
  if (error instanceof AnalyticsKitError) {
    error.platform  // 'gsc' | 'ga4' | 'clarity' | 'kd' | 'bing' | 'ahrefs' | 'google-auth'
    error.kind      // 'http' | 'network' | 'timeout' | 'abort' | 'parse'
    error.status    // HTTP 状态码(仅 kind === 'http' 时存在)
    error.body      // 服务端错误体(仅 HTTP 错误)
    error.cause     // 原始错误(仅非 HTTP 错误)
  }
}

已知边界:本库不做自动重试/退避(由调用方决定策略)、不对响应做运行时 schema 校验(类型安全覆盖输入与文档化契约);配置类问题抛 AnalyticsKitConfigError

平台限制速查

| 限制 | GSC | GA4 | Clarity | 关键词难度(哥飞版) | Bing | Ahrefs | |---|---|---|---|---|---|---| | 单请求行数上限 | 25,000 | 250,000 | 1,000(不可分页) | 单关键词一次查询 | 近月按天聚合,无分行参数 | 单域名 DR 一次查询 | | 数据窗口 | 16 个月 | 视属性配置 | 仅最近 3 天 | 实时计算 + 7 天结论缓存 | 约一个月(按天) | 实时 | | 频率限制 | 1,200 QPM/站点 | 按 token 配额(标准属性约 200k tokens/天) | 10 次/天/项目 | 三端共享日额度(游客 10 / 登录 100 / VIP 500)+ 10 次/分钟 | 官方未公开限额(宽松) | 免费公开端点 0 units,无公布限额 | | 数据延迟 | 2–3 天 | 数小时–1 天 | 数小时 | 实时 | 4–5 天 | 实时 |

GA4 注意:单请求最多返回 250,000 行;runReportAll 通过 offset 深翻页拉取更大结果集时,官方服务端在大 offset 下可能出现不稳定或超时,建议用 maxRows 控制总量或缩小维度基数。

Clarity 官方 API 只覆盖近 72 小时且每天仅 10 次调用——若需历史留存,请在业务侧定时调用并将结果持久化到自己的存储。

开发

pnpm test        # vitest 单测(全部 mock fetch,不发真实网络请求)
pnpm typecheck   # tsc --noEmit
pnpm build       # tsdown 构建 dist/

发布:npm publish(需先登录 npm 账号 pang3fan-creatorprepublishOnly 钩子会自动跑 typecheck + test + build)。接入真实凭据的冒烟验证建议在各业务项目中进行。