Skip to content
You are reading the docs for Backstory 0.2 (private beta). Behavior may change before general availability; the changelog lists every change.

SDK configuration reference

Backstory.init(config) validates its input, applies defaults, and logs a single console.warn listing anything invalid. It never throws. Only projectKey is required.

OptionTypeDefaultNotes
projectKeystringrequiredPublic project key (pk_live_…). pk_dev_local in local development.
ingestUrlstringhttps://ingest.backstory.io/v1/ingestLocal: http://localhost:8080/v1/ingest.
apiUrlstringingest originBase URL for remote config (GET /v1/config). Local: http://localhost:8081.
spillbooleantrueIndexedDB write-behind for un-acknowledged chunks; survives tab crashes.
releasestring—Your release identifier, used for source maps and release health.
environmentstring—production, staging, …
endUserIdstring—Your id for the person, stored exactly as sent.
endUserNamestring—Display name shown wherever the session is listed. Same as the second argument to identify().
debugbooleanfalseMounts the debug panel (Ctrl+Shift+R toggles it).
workerUrlstringinlinedURL of dist/worker.js when you prefer a separate worker file.
OptionTypeDefaultNotes
mode"strict" | "permissive""strict"Privacy mode on or off. The project setting in the dashboard overrides it. See Privacy configuration.
maskSelectorstring""Extra selector whose subtree is masked.
blockSelectorstring""Extra selector whose subtree is removed (box kept).
allowUnmaskbooleanfalseHonor data-backstory-unmask while privacy mode is on.
OptionTypeDefaultNotes
requiredbooleanfalseWhen true, nothing is captured or buffered until consent is granted.
adapter"tcf" | "onetrust" | "cookiebot" | "osano" | "callback"—Auto-wires a consent platform.
purposeIdsnumber[][1, 7, 8, 10]TCF purposes that must all be granted.
callback(grant, revoke) => void—For adapter: "callback".
ignoreGPCbooleanfalseTreat Global Privacy Control as opt-out unless true.
OptionTypeDefaultNotes
samplingPartial<SamplingPolicy>{ mode: "always" }See Recording controls.
memoryBudgetMBnumber24Hard ceiling for in-memory buffers. Auto-lowers to 8 on low-end devices.
batchMsnumber1000Flush interval.
batchBytesnumber65536Flush when a batch reaches this size.
pointerHznumber20Pointer sampling in HEALTHY; the governor lowers it under pressure.
checkpointMinutesnumber5Full snapshot interval.
segmentHoursnumber4Segment rollover (1–24).
inactivityMinutesnumber30Ends a normal-mode session after inactivity.
OptionTypeDefaultNotes
captureMetabooleantrueMethod, path, status, duration, size, timing. Query strings and userinfo are stripped.
captureBodiesbooleanfalseBodies only for bodyAllowlistUrls, masked, capped by maxBodyBytes.
headerAllowliststring[][]Authorization, Cookie, and Set-Cookie are never captured.
bodyAllowlistUrlsstring[][]URL prefixes.
maxBodyBytesnumber65536
captureWebSocketMessagesbooleanfalseOpt in to masked text frame capture. Connection and frame metadata is already captured by default. Ignored in strict privacy mode.
webSocketMessageAllowlistUrlsstring[][]Required URL prefixes for WebSocket message text. An empty list captures no payloads.
maxWebSocketMessageBytesnumber4096Maximum captured UTF-8 bytes per text frame (128–65536).

WebSocket metadata includes the sanitized connection URL, lifecycle, close code, duration, sent/received frame counts, direction, text/binary type, and byte size. To inspect message text in Network → WebSocket, explicitly allowlist only the endpoints you need:

Backstory.init({
projectKey: "pk_live_…",
network: {
captureWebSocketMessages: true,
webSocketMessageAllowlistUrls: ["wss://realtime.example.com/support/"],
maxWebSocketMessageBytes: 4096,
},
});

Text is truncated and PII-masked in the browser. Binary frame contents are never captured.

Each defaults to true: console, network, vitals, longTasks, errors. Remote config can turn any of them off without a deploy.

Off by default. See WebRTC call quality for what is captured and the privacy rules.

OptionTypeDefaultNotes
enabledbooleanfalseLoads the lazy WebRTC module when true.
sampleIntervalSecnumber5Seconds between emitted quality samples at full health; getStats() is polled at 1 Hz internally.
captureSdpbooleanfalseRedacted session descriptions. Never honored in strict privacy mode.
emitOnThresholdCrossbooleantrueEmit immediately when a detector threshold is crossed, even while thinned.
maxPeerConnectionsnumber8Tracked at once; extras counted but not sampled.
Backstory.init(config);
Backstory.identify(id, traits?);
Backstory.track(name, props?, { severity?: "debug" | "info" | "warn" | "error" }); // see Custom events
Backstory.checkpoint(); // force a full snapshot
Backstory.setMode("normal" | "monitor");
Backstory.consent.grant(); Backstory.consent.revoke();
Backstory.optOut(); // stop, wipe local state, send a final consent=false
Backstory.forceRecord(reason); // promote a conditionally buffered session
Backstory.stop();
Backstory.getSessionId(); Backstory.getVisitId(); Backstory.getDebugState();
Backstory.webrtc.attach(pc); // instrument a connection built before init
Backstory.webrtc.list(); // tracked connections with live quality
Backstory.webrtc.report(sample); // hand us stats from a vendor SDK

Backstory.track() records application-defined diagnostic events with optional severity. They appear in the Custom events panel, not the mixed Events stream. Full reference: Custom events.

At init the SDK fetches GET {apiUrl}/v1/config?key=…&sdk=… with a 300 ms timeout and caches the result for five minutes. Server values override local ones for: recording on/off, sampling, privacy mode, canvas, memory budget, segment and checkpoint intervals, monitor mode, collectors (including WebRTC), feature flags, and a forced governor level for incident response. Every ingest acknowledgement can carry small config nudges as well.