Advanced

beforeSend

A synchronous hook that runs on every event before it leaves the browser. Return null to drop, or a mutated copy to rewrite.

Signature#

typescript
beforeSend(event: Record<string, unknown>): Record<string, unknown> | null;

beforeSend runs synchronously on every event right before transport. The event object is the full payload — message, stack trace, breadcrumbs, tags, browser state, the lot. You can:

  • Return the event unchanged → it ships.
  • Return a mutated event → the mutated version ships.
  • Return null → the event is dropped silently.

Filtering noisy errors#

typescript
init({
  publicKey: 'pk_live_rl_...',
  beforeSend(event) {
    // Drop a noisy third-party error we can't fix
    if (typeof event.message === 'string' &&
        event.message.includes('ResizeObserver loop')) {
      return null;
    }

    // Drop errors from a specific URL
    if (typeof event.url === 'string' &&
        event.url.includes('chromewebdata://')) {
      return null;
    }

    return event;
  },
});

Runtime PII redaction#

Reliable already scrubs common PII shapes (emails, credit cards, sensitive cookie keys), but if your data has app-specific patterns to mask, do it here:

typescript
beforeSend(event) {
  // Strip query params we know contain customer IDs
  if (typeof event.url === 'string') {
    event.url = event.url.replace(/customer_id=[^&]+/g, 'customer_id=REDACTED');
  }

  // Mask emails in the message body
  if (typeof event.message === 'string') {
    event.message = event.message.replace(
      /[\w.+-]+@[\w.-]+\.\w+/g,
      '[email]'
    );
  }

  return event;
}

Enriching events#

Add tags or context that's only available at send-time:

typescript
beforeSend(event) {
  // Tag with the build SHA so you can correlate with deploys
  event.tags = {
    ...(event.tags as object),
    build_sha: process.env.NEXT_PUBLIC_BUILD_SHA,
    git_branch: process.env.NEXT_PUBLIC_GIT_BRANCH,
  };

  return event;
}

Filtering by event type#

The path field on the event tells you which endpoint it's headed to (/errors, /vitals, /requests, etc.). Use it to scope filters:

typescript
beforeSend(event) {
  // Drop telemetry pings to our own analytics endpoint
  if (event.path === '/requests' &&
      typeof event.url === 'string' &&
      event.url.includes('/analytics/heartbeat')) {
    return null;
  }

  return event;
}

Performance#

beforeSend runs synchronously on the main thread for every event. Keep it fast — no network calls, no expensive parsing, no JSON.stringify of large blobs. Any throw inside beforeSend is swallowed and the event is dropped, so guard your logic if you're doing anything that might fail.

Test it locally first

A buggy beforeSend can silently drop every event in your app. Use debug: true during integration to see what gets dropped vs. shipped.