Appearance
Data transform
Data transformation allows you to redact, mask, or omit network and console signals before they are recorded.
Data transformation happens client-side so any data removed in this way is never uploaded.
Transform function
Use a custom transform function to redact, mask or omit signals before they are captured.
js
window.captureOptions = {
captureKey: "YOUR_CAPTURE_KEY",
transform: (signal) => {
if (signal.type === "request" && signal.url.includes("/api/payments")) {
return null;
}
return signal;
},
};Within the function you can:
- Alter the signal by replacing the value of a field, for example to mask part of a URL or remove a key from a logged object.
- Redact a field by setting it to
null. The field appears in the report with a "redacted" badge so your team knows it was intentionally removed. - Omit the signal entirely by returning
null. It does not appear in the report at all.
Every signal has a type field. Check it first, since the other fields depend on which kind of signal you have been given.
Request signals
A network signal has type: "request" and includes these fields:
| Field | Type | Editable |
|---|---|---|
url | string | Yes |
requestHeaders | Record<string, string> | Yes |
requestBody | unknown | Yes |
responseHeaders | Record<string, string> | Yes |
responseBody | unknown | Yes |
method | string | No |
status | number | No |
initiator | "fetch" | "xhr" | No |
startTime | number | No |
endTime | number | No |
Request and response bodies are the raw values your application sent or received, so a body may be a string, FormData, URLSearchParams, Blob, or another body type. Check the type before working with it.
Console signals
A console signal has type: "console" and includes these fields:
| Field | Type | Editable |
|---|---|---|
args | unknown[] | Yes |
method | "log" | "info" | "warn" | "error" | "debug" | No |
initiator | "error" | "unhandledrejection" | "securitypolicyviolation" | No |
args holds the values passed to the console method, exactly as your code passed them.
Changes to fields that are not editable are ignored for both signal types.
Examples
Omitting signals
Return null for signals that should never appear in a report, such as traffic to a payment provider or logs from a noisy third-party script.
js
window.captureOptions = {
captureKey: "YOUR_CAPTURE_KEY",
transform: (signal) => {
if (signal.type === "request") {
const { hostname } = new URL(signal.url);
if (hostname.endsWith("payments.example.com")) return null;
}
if (signal.type === "console") {
const [first] = signal.args;
if (typeof first === "string" && first.startsWith("[analytics]")) {
return null;
}
}
return signal;
},
};Redacting fields in a request
Set a field to null when you want the request to appear in the report, but without the sensitive value.
js
window.captureOptions = {
captureKey: "YOUR_CAPTURE_KEY",
transform: (signal) => {
if (signal.type !== "request") return signal;
if (signal.url.includes("/api/auth")) {
signal.requestBody = null;
signal.responseBody = null;
}
if ("x-api-key" in signal.requestHeaders) {
signal.requestHeaders["x-api-key"] = null;
}
return signal;
},
};Masking values in a request
Replace a value when you want to keep most of it and hide only part.
js
window.captureOptions = {
captureKey: "YOUR_CAPTURE_KEY",
transform: (signal) => {
if (signal.type !== "request") return signal;
// Hide a token passed in the query string
const url = new URL(signal.url);
if (url.searchParams.has("token")) {
url.searchParams.set("token", "[hidden]");
signal.url = url.toString();
}
// Remove a single field from a JSON response
if (
signal.url.includes("/api/profile") &&
typeof signal.responseBody === "string"
) {
try {
const { ssn, ...rest } = JSON.parse(signal.responseBody);
signal.responseBody = JSON.stringify(rest);
} catch {
signal.responseBody = null;
}
}
return signal;
},
};Masking values in console output
Replace entries in args to hide sensitive values while keeping the rest of the message.
js
const EMAIL = /[\w.+-]+@[\w-]+\.[\w.]+/g;
window.captureOptions = {
captureKey: "YOUR_CAPTURE_KEY",
transform: (signal) => {
if (signal.type !== "console") return signal;
signal.args = signal.args.map((arg) => {
if (typeof arg === "string") return arg.replace(EMAIL, "[email]");
if (arg && typeof arg === "object" && "password" in arg) {
return { ...arg, password: "[hidden]" };
}
return arg;
});
return signal;
},
};How Capture handles the return value
- Returning the signal, with or without changes, records it, as does returning
undefined. - Returning
nullomits the signal from the report. - If your function returns something that is not a signal, throws an error, or sets an editable field to an invalid value, the signal is omitted.
Keeping the transform function fast
Your transform function runs for every network request your application makes and every message it logs, so keep it lightweight. Check cheap conditions such as the signal type and URL first, and only do heavier work, like parsing a JSON body or walking a logged object, for the signals that need it.
js
window.captureOptions = {
captureKey: "YOUR_CAPTURE_KEY",
transform: (signal) => {
if (signal.type !== "request") return signal;
if (!signal.url.includes("/api/orders")) return signal;
// Only requests to /api/orders reach this point
// ...
return signal;
},
};Next steps
Data transform keeps sensitive data out of recorded network requests and console logs. To keep it out of screenshots and screen recordings as well, see auto-blur.
For an overview of everything a report contains and what Capture never records, see data and privacy.
Want to attach application state to help with debugging? See custom context.