@didit-protocol/signals

中文文档
0.1.0发布于 2026/10/27MITTypeScriptESM + CJS零依赖近 30 天下载 3779

Didit device signals and end-user event monitoring for the browser

原始使用文档
文档目录10 节
  1. Installation
  2. Quick start
  3. How events are sent
  4. API
  5. submitEvent({ monitoringToken, event, baseUrl? }): string
  6. flush(): Promise<DiditEventFlushResult>
  7. configureEvents(options)
  8. Device signals
  9. Development
  10. License

@didit-protocol/signals

Didit device signals and end-user event monitoring for the browser, in under 5 KB minified and gzipped.

  • submitEvent sends sign-ups, logins, failed logins, logouts and any other end-user event to Didit's event monitoring, tied to the same person as their verifications and transactions.
  • Device signals: the didit-fp-v2 device fingerprint is attached to every batch. Page exit uses the available signals if its composite hash is still pending.
  • Works alone or together with the other Didit SDKs: @didit-protocol/sdk-web depends on this package and re-exports it, so an app that uses both shares one event queue per module format. Standalone CDN and script-tag builds each carry their own queue.

Installation

npm install @didit-protocol/signals

Script tag (exposes window.DiditSignals):

<script src="https://unpkg.com/@didit-protocol/signals/dist/didit-signals.umd.min.js"></script>

Quick start

Your backend mints a short-lived monitoring token for the signed-in person with your API key:

curl -X POST https://verification.didit.me/v3/events/sdk-token/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "vendor_data": "user_391", "allowed_event_categories": ["auth", "session"] }'

The page submits events with it:

import { submitEvent, flush, configureEvents, DiditEventError } from "@didit-protocol/signals";

configureEvents({
  onError: (error: DiditEventError) => console.warn(error.type, error.eventIds, error.errors),
});

const eventId = submitEvent({
  monitoringToken, // from your backend - never ship an API key
  event: { category: "auth", actionType: "signup", payload: { method: "passkey" } },
});

// Optional: send right away (for example before a redirect you control) and read each outcome.
const result = await flush();
// { acceptedCount, replayedCount, rejectedCount, pendingCount, results: [{ eventId, outcome, eventUuid, status, score, error }] }

The person an event belongs to always comes from the token: Didit overwrites any subject in the request with the vendor_data the token was minted for, and takes the IP address, user agent and origin from the request.

How events are sent

WhenHow
25 events are waitingOne POST /v1/events/batch/ right away
5 seconds after an event was queuedEverything that is waiting
The page is hidden or closedWaiting events that fit the page-exit budget, with fetch and keepalive so the request outlives the page
You call flush()Everything that is waiting; resolves with each event's outcome
  • Every request carries the X-Monitoring-Token header and the device fingerprint (fingerprint_v2 in the body plus its matching X-Didit-* headers).
  • Each event keeps the token it was submitted with; events with different tokens never share a request, so a sign-out and a new sign-in on the same page never mix people.
  • Delivery is best effort: the in-memory queue is lost when the page closes, and browsers may terminate requests. At page exit, browsers allow 64 KiB of keepalive requests per page; what does not fit stays queued and is sent if the page comes back. sendBeacon is not used: it cannot carry the token header.
  • Exit requests start right away with the collected persistent device id, browser signals and bot context. If WebCrypto hashing is still pending, compositeHash is empty and X-Didit-FP-Hash is omitted, and those events are stored without the composite hash. Normal batches and flush() wait for the complete fingerprint, and exit requests use it once it is ready.
  • On a network error, HTTP timeout (408), rate limit (429), server error (5xx) or an unreadable answer, the same events are sent again after 10, 20 and 40 seconds, then every minute. They are re-sent byte for byte, so an event Didit already stored comes back as replayed instead of being stored twice.
  • A refusal is final and is reported through onError and in the flush() results:
error.typeMeaning
invalid_tokenThe token is unknown, revoked, out of uses or bound to another origin (HTTP 401)
expired_tokenThe token's lifetime has elapsed (HTTP 401)
monitoring_disabledEvent monitoring is not switched on for the application (HTTP 403)
validationThe event failed validation; error.errors has Didit's per-field details
droppedThe queue was full and the event was dropped before it was sent

submitEvent itself throws a DiditEventError only for a missing token (invalid_token), a missing category or actionType (validation), or an environment without fetch (network).

API

submitEvent({ monitoringToken, event, baseUrl? }): string

Queues one event and returns its id.

Event fieldDescription
categoryauth, session, security, payment, dispute, gameplay, bonus, affiliate, responsible_gambling or custom
actionTypeWhat happened, e.g. signup, login, login_failed, logout, password_reset, mfa_challenge
eventIdYour idempotency key (at most 128 characters); a UUID is generated when omitted
occurredAtDate or ISO 8601 string; defaults to now (at most 7 days in the past)
timeZoneIANA time zone; defaults to the browser's
payloadCategory-specific keys; payments need payment_reference_id, amount, currency, payment_method and status
customValuesScalar values your rules can address
session{ sessionId, sequence, pageUrl, referrer }
transactionContext{ amount, currency, direction, paymentReferenceId }
subjectProfile hints { fullName, email, phone, country }; the person always comes from the token
businessThe business the event belongs to

flush(): Promise<DiditEventFlushResult>

Sends everything that is waiting. Never rejects: events that could not be sent are counted in pendingCount and retried automatically.

configureEvents(options)

OptionDefaultDescription
baseUrlhttps://verification.didit.meDidit verification API base URL
batchSize25Send as soon as this many events are waiting (1 to 500)
flushIntervalMs5000Send waiting events after this many milliseconds
maxQueueSize1000Events held in memory. When full, low-value events (session.page_view and the like) are dropped first; security, payment, dispute, responsible_gambling and bet events are never dropped, so this is a soft limit
onErrornoneCalled with a DiditEventError for every refused or dropped event

Device signals

  • getDeviceFingerprintPayload(): Promise<DeviceFingerprintPayload | null> collects the didit-fp-v2 fingerprint (null outside a browser).
  • buildFingerprintHeaders(payload) returns the matching X-Didit-* headers.

Full guide: SDK Event Submission.

Development

This package lives in the sdk-web workspace. From the repository root:

npm ci
npm test -- --runInBand        # unit tests of both packages
npm run typecheck
npm run build                  # builds @didit-protocol/signals, then @didit-protocol/sdk-web
npm run test:size              # fails above 5 KB minified and gzipped
npm run test:e2e               # Chromium, Firefox and WebKit

The unit and browser tests replay real answers of the Didit verification API to POST /v1/events/batch/ (src/__tests__/fixtures/device-lane-recordings.json). To run the browser check against a live API instead (direct cross-origin requests, including CORS and Origin-bound token checks):

EVENTS_UPSTREAM=<API base URL> EVENTS_MONITORING_TOKEN=<token from POST /v3/events/sdk-token/> \
  npx playwright test e2e/events-live.spec.mjs --project=chromium

The API must allow X-Monitoring-Token, Content-Type and the fingerprint headers in its CORS policy before browser delivery can work. An Origin-bound token must allow the fixture origin http://127.0.0.1:4173. These tests do not establish staging or production readiness.

License

MIT

版本与发布记录

@didit-protocol/signals 共发布 2 个版本,首次发布于 2026/10/27;过去 12 个月发布了 2 个版本。

版本发布日期距今
0.1.0latest2026/10/2715 天前
0.0.0-stage2026/10/2715 天前

关于 @didit-protocol/signals 的常见问题

@didit-protocol/signals 是什么?

Didit device signals and end-user event monitoring for the browser

如何安装 @didit-protocol/signals?

在项目目录运行 npm install @didit-protocol/signals,或使用 pnpm add / yarn add / bun add。

@didit-protocol/signals 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@didit-protocol/signals 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@didit-protocol/signals 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=16.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@didit-protocol/signals 可以商用吗?

@didit-protocol/signals 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@didit-protocol/signals 的下载量有多少?

根据 npm 官方下载统计,@didit-protocol/signals 在 2026/10/12 – 2026/11/10 这 30 天内被下载 3,779 次,日均约 126 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@didit-protocol/signals 还在维护吗?

最新版本 0.1.0 发布于 2026/10/27(15 天前);至今共发布 2 个版本,其中过去 12 个月发布了 2 个;首次发布于 2026/10/27。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。