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

@interfere/react

v12.1.0

Published

Client-side React SDK for Interfere. Error tracking, session replay, and analytics.

Readme


Framework Guides

| Framework | Package | Guide | | --------- | --------------------------------------------------------------------------------------- | ---------------------------- | | Next.js | @interfere/next | docs/next.md | | Vite | @interfere/vite + @interfere/react | docs/vite.md |

Installation

npm install @interfere/react

Prerequisites

  • React >=19

Quick Start

import { InterfereProvider } from "@interfere/react/provider";

function App() {
  return (
    <InterfereProvider>
      <YourApp />
    </InterfereProvider>
  );
}

InterfereProvider captures render errors by default and rethrows them so your host error boundary keeps control of the fallback. Set captureRenderErrors={false} to disable this capture. The deprecated errorBoundary prop remains supported; captureRenderErrors takes precedence when both are set.

Features

  • Error tracking — automatic capture of uncaught errors and unhandled rejections
  • Session replay — full visual playback of user sessions
  • Page analytics — SPA-aware pageviews and UI interaction events
  • Rage click detection — surface frustrated user behavior
  • User identity — attach user context to sessions
  • Offline resilient — events are persisted and delivered in the background

Hooks

import { useInterfere } from "@interfere/react/provider";

function MyComponent() {
  const { identity, session } = useInterfere();

  identity.set({
    identifier: "usr_123",
    email: "[email protected]",
    name: "Jane",
    source: { type: "clerk", name: "Clerk" },
  });

  const sessionId = session.getId();
}

Session correlation

With the SDK's default browser propagator, instrumented fetch and XHR requests carry session.id in W3C baggage to the same origin and hosts in tracing.apiHosts. Cross-origin APIs must allow the baggage and traceparent request headers in their CORS configuration. Existing tracing.propagateContextUrls patterns also apply.

Explicitly denying analytics consent stops session baggage propagation while retaining trace propagation. tracing: false disables SDK instrumentation. Existing application-owned propagators are not replaced.

Privacy

Pass privacy to your framework's browser init() to mark elements whose content the SDK never records. The same selectors apply to session replay and to click, submit and rage-click records, from the first capture:

const options: KernelOptions = {
  privacy: {
    blockSelector: "[data-sensitive]",
    maskTextSelector: "[data-mask-text]",
  },
};

The interfere-block and interfere-mask classes always apply. A selector matches the target element or any ancestor. The selectors apply even when replay is disabled.

replay.blockSelector and replay.maskTextSelector on the provider apply to replay only.

Interaction records

Click, submit and rage-click records keep what the person did and which control they used, but never what a private element shows or holds. A click on a private account-number field records that the "Account number" field was clicked, not the number. Field values are never recorded.

| Target | Recorded | | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | Blocked (interfere-block, blockSelector) | Event type, timing, tag name and field label. ui.target.privacy is blocked. | | Masked (interfere-mask, maskTextSelector) | Event type, timing, tag name, role and field label. ui.target.privacy is masked. | | Public | Tag, id, name, role, aria-label, field label and up to 120 characters of text. Text inside blocked or masked descendants is skipped. |

The field label (ui.target.label) comes from developer-authored sources only:

  1. A data-interfere-label attribute on the target or an ancestor, such as <div data-sensitive data-interfere-label="Security code">. Use this when the visible label sits inside the private region.
  2. Otherwise, the text of the field's <label> elements and aria-labelledby targets, when those labels are not themselves blocked or masked.

A private element's own aria-label, placeholder, title, text and value are never recorded, because applications often put the current value there. Form fields (input, select, textarea) never contribute text, even when public.

For blocked and masked targets the SDK also replaces OpenTelemetry's id-based target_xpath with a positional path. Target URLs (href) are never recorded. An invalid selector blocks every interaction target and logs a warning.

To keep navigation, document-load and resource timing without click and submit spans, pass pageEvents: { interactions: false }. pageEvents: false still turns off all page events, and rageClick: false turns off rage clicks. Denying analytics consent stops page events and rage clicks.

URL redaction

The SDK redacts URLs before they leave the browser. Parameter names stay, redacted values become REDACTED, and credentials in a URL (https://user:pass@host) always become REDACTED:REDACTED. Configure query and fragment redaction with privacy.urls:

| privacy.urls | Query values redacted | Fragment | | --------------------- | --------------------------------------------- | -------- | | Omitted (default) | Built-in sensitive names only | Kept | | { deny: ["email"] } | Built-in sensitive names and the listed names | Kept | | { allow: ["page"] } | Every name except the listed names | Kept | | true | Every name | Removed | | false | None | Kept |

const options: KernelOptions = {
  privacy: { urls: { allow: ["page", "sort"], fragment: true } },
};

fragment: true removes fragments, including hash-router paths. The built-in sensitive names follow the OpenTelemetry URL conventions and common credential names: AWSAccessKeyId, sig, code and key, plus any name that contains token, secret, password, passwd, auth, credential, session, signature, api_key or apikey. Names match case-insensitively after URL decoding. A name in deny is always redacted; a name in allow keeps its value, even when it is a built-in sensitive name.

A parameter without = (such as ?eyJhbGci…) is redacted whole when its name is redacted, because a bare value can be a token. The SDK splits each value at the first ? and # without parsing it, so relative paths and malformed values follow the same rule. A query inside a hash route belongs to the fragment and is kept with it. Requests, routing and trace propagation still use the original URL. Path segments are not redacted, so a token in a path such as /share/abc123 is still recorded.

| Record | Covered | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | | url.full, url.path, url.original, http.url, http.target, http.referrer and referer header attributes on SDK spans and span events, and span names such as GET /a?id=1 | Yes | | url.query and url.fragment attributes | Values redacted; fragment removed with fragment: true | | Navigation logs, including the initial page load | Yes | | Absolute URLs in exception messages, the cause chain and the span status, including SDK messages for failed requests, resource loads and CSP violations | Yes | | Session replay page URLs and href, src, srcset, action, formaction, poster, cite and data attributes | Yes | | Spans on your own OpenTelemetry provider, URLs in stack frames, relative paths in exception messages, inlined CSS in replay and console logs | No |

Replay plays images and links back from their recorded URLs, so a redacted signed URL (for example ?X-Amz-Signature=REDACTED) no longer loads in the player.

The SDK redacts each span while it ends, so onEnd in tracing.spanProcessors and the Interfere exporter receive redacted values. onStart still sees the URL the instrumentation set at span creation. The browser provider is private to the SDK, so other OpenTelemetry exporters on the page are unaffected.

Browser span processors

Framework browser init() options accept tracing.spanProcessors, an array of standard OpenTelemetry SpanProcessor instances. For example, these options remove an application attribute before export:

import type { KernelOptions } from "@interfere/react/internal/kernel";
import type { SpanProcessor } from "@opentelemetry/sdk-trace-base";

const dropTenant: SpanProcessor = {
  onStart() {},
  onEnd(span) {
    delete span.attributes["app.tenant_name"];
  },
  async forceFlush() {},
  async shutdown() {},
};

const options: KernelOptions = {
  tracing: { spanProcessors: [dropTenant] },
};

Pass options to your framework's browser init(). Processors are additive. Built-in session and device enrichment runs first, followed by your processors in array order, internal wrapper processors, and the Interfere batch exporter. Default instrumentation and export remain enabled.

Finish attribute mutations synchronously in onEnd, before it returns. OpenTelemetry does not await asynchronous work in onStart or onEnd. Ended spans cannot be changed through setAttribute; edit span.attributes as above. Use privacy.urls for query values and fragments.

The SDK calls each processor's forceFlush during flush and shutdown during disposal. Use a fresh processor instance for each SDK initialization and do not share it with another provider. tracing: false skips tracing setup, including custom processors.

Documentation

Visit interfere.com/docs for the full documentation.

License

MIT