Collectors

The agent produces assertion results but doesn't decide where they go — that's the collector's job. A collector is a function that receives each assertion payload and does something with it (POST to a backend, log to the console, render in an overlay).

Two official collectors ship as separate packages:

Package Purpose Production use
@faultsense/panel-collector Shadow-DOM overlay showing real-time pass/fail + X-Ray element inspector Dev/staging
@faultsense/console-collector Logs each result as a collapsible devtools group Dev/staging

For production, point collectorURL at your collector backend URL with an apiKey. The dev collectors are for local instrumentation and debugging.

Script tag

Load the collector script before the agent script so it registers itself before the agent reads data-collector-url:

<!-- Panel collector -->
<script src="https://cdn.faultsense.com/v0/faultsense-panel.min.js" defer></script>
<script
  id="fs-agent"
  src="https://cdn.faultsense.com/v0/faultsense-agent.min.js"
  data-collector-url="panel"
  data-release-label="2.4.1"
  defer>
</script>
<!-- Console collector -->
<script src="https://cdn.faultsense.com/v0/faultsense-console.min.js" defer></script>
<script
  id="fs-agent"
  src="https://cdn.faultsense.com/v0/faultsense-agent.min.js"
  data-collector-url="console"
  data-release-label="dev"
  defer>
</script>

The collector scripts self-register under window.Faultsense.collectors using their name ("panel" or "console"). When the agent sees a non-URL value in data-collector-url, it looks up the registered collector by that name.

Production backend

Point directly at your collector endpoint — no collector package needed:

<script
  id="fs-agent"
  src="https://cdn.faultsense.com/v0/faultsense-agent.min.js"
  data-collector-url="https://collector.example.com/events"
  data-api-key="fs_secret_..."
  data-release-label="2.4.1"
  defer>
</script>

npm

Install the collector alongside the agent:

npm install @faultsense/agent @faultsense/panel-collector

or

npm install @faultsense/agent @faultsense/console-collector

Import the collector function and pass it as collectorURL:

import { init } from '@faultsense/agent';
import { panelCollector } from '@faultsense/panel-collector';

init({
  releaseLabel: '2.4.1',
  collectorURL: panelCollector,
});
import { init } from '@faultsense/agent';
import { consoleCollector } from '@faultsense/console-collector';

init({
  releaseLabel: 'dev',
  collectorURL: consoleCollector,
});

No apiKey is needed when collectorURL is a function — the collector receives payloads directly in-process.

Auto wiring

If you prefer script-tag parity inside a bundler, use the auto imports:

import '@faultsense/panel-collector/auto';
import '@faultsense/agent/auto';

The collector's auto entry self-registers under window.Faultsense.collectors, and the agent's auto entry reads data-collector-url from the <script id="fs-agent"> tag. This is the same mechanism the script-tag path uses.

Production backend (npm)

Pass the URL string directly — no collector package:

import { init } from '@faultsense/agent';

init({
  releaseLabel: '2.4.1',
  collectorURL: 'https://collector.example.com/events',
  apiKey: 'fs_secret_...',
});

Peer dependencies

Both collector packages declare @faultsense/agent as a peerDependency, not a direct dependency. This prevents your bundler from resolving two separate copies of the agent — which would silently break collector lookup because window.Faultsense.collectors is a shared registry, and two copies would set up two independent registries.

If your package manager warns about an unmet peer dependency, install @faultsense/agent directly:

npm install @faultsense/agent @faultsense/panel-collector

Custom collectors

Any function with the signature (payload: ApiPayload) => void works as a collector:

import { init } from '@faultsense/agent';
import type { ApiPayload } from '@faultsense/agent';

function myCollector(payload: ApiPayload): void {
  fetch('/my-endpoint', {
    method: 'POST',
    body: JSON.stringify(payload),
    headers: { 'Content-Type': 'application/json' },
  });
}

init({
  releaseLabel: '2.4.1',
  collectorURL: myCollector,
});

See the payload spec for the full ApiPayload shape.