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

@clue-ai/browser-sdk

v0.1.1

Published

Clue Browser SDK for raw telemetry capture and transport

Readme

@clue-ai/browser-sdk

Clue browser ingest SDK.

Minimal integration

After pnpm add @clue-ai/browser-sdk, the intended integration is:

import { ClueInit } from "@clue-ai/browser-sdk";

ClueInit({
  endpoint: process.env.NEXT_PUBLIC_CLUE_INGEST_ENDPOINT!,
  projectKey: "...",
  environment: "production",
});

projectKey is the public ingest key. The API resolves authoritative tenantId, projectId, and environmentId from that key. endpoint must be injected from the host app and passed to ClueInit.

Responsibility boundary

  • SDK captures browser signals and applies local minimization where the signal is obviously high-risk.
  • API ingest privacy gate is authoritative for final allow/deny/unmask policy.
  • Worker-side sanitize is defense-in-depth only.
  • SDK sends projectKey, environment, schemaVersion, sdkType, sdkVersion, stable keys, and minimized capture payloads.
  • SDK does not authoritatively stamp tenant_id, project_id, environment_id, or final archive-safe request/response payloads.

The browser SDK does not own final archive-safe allowlist decisions.

Default privacy/minimization behavior

The browser SDK avoids shipping obvious high-risk plaintext and keeps the MVP default event surface intentionally narrow.

  • input_change.value -> local value metadata only
  • selection_text -> metadata only
  • raw selector/path -> never serialized; stable key only

Current MVP defaults:

  • successful network emits one request_finished
  • failed network emits one request_failed
  • standard action capture emits element_clicked, form_submitted, input_committed, toggle_changed, selection_committed, file_selected, and drag_drop_completed
  • standard support capture emits only frustration signals (dead_click_detected, error_click_detected, rage_click_detected)
  • normal batching flushes when the queued payload reaches the 48KB send threshold, when no new event is added for 3 minutes, or when the page is leaving
  • event type does not change the delivery rule in MVP

Stable key precedence:

  1. data-testid
  2. data-qa
  3. safe name
  4. safe aria-label
  5. structural fallback

data-clue-id and data-clue-key are not part of the MVP stable-key contract. Captured stable keys are best-effort evidence, not authoritative business meaning.

Sampling and cost guards

  • sampling.sessionSampleRate controls whether a session emits normal capture
  • oversized events degrade in stages before final drop:
    • payload body removed
    • metadata/schema only
    • shell only
  • oversized batches stay below the configured payload hard max

Flush reliability

The SDK flushes on:

  • visibilitychange -> hidden
  • pagehide
  • beforeunload

The page-leave flush is best effort. The SDK does not persist unsent events in localStorage or IndexedDB in MVP.

Beacon contract

  • unload / hidden beacon sends only the request body
  • ingest must be able to resolve projectKey and environment from the body
  • custom auth headers cannot be assumed on the beacon path

Degraded event contract

Downstream ingest must accept these as normal input:

  • no raw payload body
  • metadata + schema only
  • shell-only event

Privacy and PII handling

The SDK applies a layered privacy model:

1. Hard-deny: PII / secrets are stripped before transport

The SDK strips a built-in set of property keys before the event leaves the browser. These keys cannot be unmasked through allowedValuePaths — even an explicit body.email allowlist does not bypass the hard-deny.

Hard-deny categories (case- and separator-insensitive — userEmail, user-email, USER_EMAIL, email_address all match):

  • Auth credentials: authorization, cookie, set-cookie, password, passwd, secret, token, access_token, refresh_token, session, session_token, api_key, apikey, private_key
  • PII categories (Phase 4 P0): email, phone, credit_card, ssn

This list is a strict superset of the server-side ingest hard-deny (@clue/shared INGEST_HARD_DENY_KEYS), enforced by CI parity tests in all three SDKs.

2. Default-masked: arbitrary values are masked unless allowlisted

Properties that pass the hard-deny gate are still masked by default. The SDK emits a fingerprint or shape-only digest, not the raw value.

To capture a specific field in plaintext, two things must both be true:

  1. The field path appears in the SDK call's allowedValuePaths (caller opt-in at SDK init time).
  2. The same property key appears in the project's server-side observationAnalysisPropertyAllowlist (ProjectEnvironment.observationAnalysisPropertyAllowlist).

If condition 1 holds but condition 2 does not, the value is stored in the raw archive only — facts_json.analysisProperties.projected will be empty and the field will not appear in Clue's analysis UI.

3. Operational consequence: configure server allowlist before launch

Customers who launch without setting observationAnalysisPropertyAllowlist on their ProjectEnvironment will see custom event names land in observation_type but no projected properties in dashboards. The canonical event still includes raw_only_keys listing which keys were seen but masked. Configure the server allowlist via the Clue admin UI or ProjectEnvironment update API after taking a privacy review of which property names you want to project for analytics.