Skip to main content

Configuration options

Manually create a new session​

By default the SDK rotates the session automatically — after 15 minutes of inactivity, or once a session reaches 1 hour. Starting with version 3.19.0, you can also rotate it on demand by calling CoralogixRum.createNewSession(), for example when a user logs out, so that subsequent events are attributed to a fresh session.

import { CoralogixRum } from '@coralogix/browser';

// e.g. inside your logout handler
CoralogixRum.createNewSession();

This ends the current session and immediately starts a new one with a new session id. If session recording is active, the current recording is finalized and a new one begins for the new session.

Unique users​

Starting with version 2.9.0, the SDK calculates unique users based on the user’s fingerprint.
The fingerprint is generated and stored on each user’s machine for reuse.
In earlier versions, the SDK used user_id to calculate unique users, which is still supported for backward compatibility.

Network extra configuration​

The networkExtraConfig property is an array of configuration objects, each specifying custom rules for capturing network requests and responses. This feature collects data from Fetch and XMLHttpRequest calls, attaching specified request and response information, headers, and payloads to each network event.

CoralogixRum.init({
networkExtraConfig: [
{
url: 'http://example.com', // Capture requests to this specific URL or regex pattern
reqHeaders: ['X-Request-Id', 'Content-Type'], // Capture 'X-Request-Id' and 'Content-Type' headers in requests
resHeaders: ['Cache-Control', 'Date'], // Capture 'Cache-Control' and 'Date' headers in responses
collectReqPayload: true, // Collect request payload
collectResPayload: false, // Do not collect response payload
},
],
});
Warning

The SDK captures the headers you list exactly as they are sent. A header such as Authorization or Cookie carries a credential, so list it only if you need its value in Coralogix, and only for the URLs that need it.

Important note​

The server must explicitly permit access to specific headers by listing them in the Access-Control-Expose-Headers response header. Due to restrictions in the Fetch and XHR APIs, header retrieval operates on a best-effort basis, meaning that some headers may occasionally be unavailable in the events collected by this integration. Additionally, any large payloads exceeding the allowed size will be dropped.

Multi page application​

If your application is not a single page application (SPA), you can initialize the SDK with a configuration to retain the session ID after a reload/refresh. This will prevent multiple sessions from being created when the user navigates within the app.

CoralogixRum.init({
// ...
sessionConfig: {
// ...
keepSessionAfterReload: true,
},
});

Ignore errors​

The ignoreErrors option allows you to exclude errors that meet specific criteria. This options accepts a set of strings and regular expressions to match against the event's error message. Use regular expressions for exact matching as strings remove partial matches.

import { CoralogixRum } from '@coralogix/browser';

CoralogixRum.init({
// ...
ignoreErrors: [/Exact Match Error Message/, 'partial/match'],
});

Ignore URLs​

The ignoreUrls option allows you to exclude network requests and resources that meet specific criteria. This options accepts a set of strings and regular expressions to match against the event's network or resource url. Use regular expressions for exact matching as strings remove partial matches.

import { CoralogixRum } from '@coralogix/browser';

CoralogixRum.init({
// ...
ignoreUrls: [/.*\.svg/, /.*\.ico/], // will ignore all requests to .svg and .ico files
});

Stack trace limit​

Browsers typically capture 10 stack frames by default. If your error stack traces are being truncated and you need to see deeper into the call stack, you can increase this limit using the stackTraceLimit option.

import { CoralogixRum } from '@coralogix/browser';

CoralogixRum.init({
// ...
stackTraceLimit: 50,
});
Note

Higher values may have a performance impact, as the browser needs to capture more frames each time an error is created.

Mask elements​

User interactions capture text from clickable elements only (button, label, link, input, option). Elements text can be masked to prevent sensitive data exposure.
use maskInputTypes to specify the types of inputs to mask. defaults to: ['password']
use maskClass to specify the class name that will be used to mask any clickable element. Default masking class is cx-mask.

CoralogixRum.init({
// ...
maskInputTypes: ['password', 'date'], // will only mask password and date inputs
maskClass: 'mask-me', // will mask any clickable element with class 'mask-me'
});

Examples of masked elements:

<button class="cx-mask">
<span>Some Text</span>
</button>

<button>
<span class="cx-mask">Some Text</span>
</button>

<my-button-component class="cx-mask">
<button>Text</button>
</my-button-component>

Custom action names​

The SDK uses various strategies to name click actions. For more control, define a data-cx-action-name attribute on clickable elements (or any of their parents) to set the action name.

<button data-cx-action-name="add-to-cart">
Add to Cart
</button>

<form data-cx-action-name="checkout-form">
<input type="text" placeholder="Card number" />
<button type="submit">Complete Purchase</button>
</form>

<nav data-cx-action-name="main-navigation">
<a href="/products">Products</a>
<a href="/pricing">Pricing</a>
</nav>
Note

The data-cx-action-name attribute is never masked, even when the element has a mask class applied. This ensures your custom action names are always captured for tracking purposes.

Use your own attribute​

Starting with version 4.4.0, you can name click actions with an attribute of your own. If your elements already carry one, such as data-analytics-id or data-testid, set actionNameAttribute to its name instead of adding data-cx-action-name across your app. The SDK reads it exactly like data-cx-action-name, on the clicked element or any of its parents, and reports its value in cx_action_name. data-cx-action-name keeps working alongside it.

CoralogixRum.init({
// ...
actionNameAttribute: 'data-analytics-id',
});

When both attributes are present, the nearest element carrying either one names the click. On a single element, data-cx-action-name wins:

{/* A click reports "add-to-cart" */}
<button data-cx-action-name="add-to-cart" data-analytics-id="cart-button">
Add to Cart
</button>

{/* A click on Pay reports "checkout", from the nearer element */}
<div data-cx-action-name="cart-panel">
<button data-analytics-id="checkout">Pay</button>
</div>

actionNameAttribute takes a single attribute name made of letters, digits, _ and -, starting with a letter or _. The SDK ignores any other value and reads only data-cx-action-name.

Note

Setting actionNameAttribute changes the element_fingerprint reported for clicks on elements that carry only your attribute, because the fingerprint is built from the action-name attribute first. Rage-click detection follows the new fingerprint.

Ignoring elements​

Add a data-cx-action-ignore attribute to a clickable element whose clicks should not be listed as actions, such as a resize handle. Its clicks are still reported but carry is_ignored: true in their interaction context, so Product Analytics leaves them out of the actions it shows. The attribute applies to the exact node that received the click: it is not inherited from a parent, and a click on a child of the element, such as an icon inside the button, is not flagged either.

<button data-cx-action-ignore class="drag-handle"></button>

Label providers​

Provide labels based on url or event

import { CoralogixRum } from '@coralogix/browser';

const featurePageUrlLabelProvider = new UrlBasedLabelProvider({
urlType: UrlType.PAGE,
urlPatterns: [
{
regexps: [/apm/],
labels: { featureGroupId: 'apm' },
},
],
defaultLabels: {
featureGroupId: 'unknown-feature-group',
},
});

const regularExpErrorLabelProvider: GenericLabelProvider = {
providerFunc: (url, event) => {
if (event.error_context?.error_message?.includes('Invalid regular expression')) {
return {
regular_expression_error: 'true',
};
}

return {};
},
};

CoralogixRum.init({
// ...
labelProviders: [featurePageUrlLabelProvider, regularExpErrorLabelProvider],
});

URL blueprinters​

Modify the event's page or network url based on custom-defined functions.

import { CoralogixRum } from '@coralogix/browser';

CoralogixRum.init({
// ...
urlBlueprinters: {
pageUrlBlueprinters: [
(url) => {
const hostnameParts = new URL(url).hostname.split('.');
hostnameParts[0] = '{team-id}';
return 'https://' + hostnameParts.join('.');
// "https://alpha.company.com" => "https://{team-id}.company.com"
},
],
networkUrlBlueprinters: [(url) => url.replace('api/v1', '{server}')],
// "https://path/api/v1/logs" => "https://path/{server}/logs"
},
});

The SDK applies its own built-in blueprinting first, then your functions, in the order you list them, so your blueprinter has the final word on the URL it returns.

The built-in page blueprinting replaces UUIDs and all-digit path segments with {id}, so /orders/1234 becomes /orders/{id}. A segment that only happens to contain a digit keeps its real value, which leaves route names such as /apm-v2, /oauth2 and /v1 untouched.

URL masking​

Available from version 4.5.0.

The SDK masks secrets in the URLs it reports before they leave the page. Masking is always on and covers:

  • the page URL and the referrer (page_context.page_url, page_context.referrer)
  • network request URLs (network_request_context.url)
  • resource URLs (resource_context.name), including the URL of an iframe the page loads
  • the URLs in web-vitals data: page load time, soft navigations and the LCP element
  • the script URLs in error stack traces (error_context.original_stacktrace)
  • the URLs inside error messages (error_context.error_message); the rest of the message stays as it is
  • the script URL reported with a web worker's errors
  • session recordings: the page URL, and the src, href and srcset of the elements recorded

A masked value becomes [REDACTED]. The parameter name and the rest of the URL stay as they were, so https://app.example.com/callback?code=4%2F0AX&scope=email is reported as https://app.example.com/callback?code=[REDACTED]&scope=email.

Parameter names are compared ignoring case and punctuation such as - and _, so access_token, accessToken and Access-Token are treated the same. The SDK always masks:

  • query and fragment parameters whose name contains token, secret, password, passwd, passphrase, apikey, signature, credential, jwt, session, sessid, oauth, saml, privatekey, accesskey, nonce, csrf or xsrf. This covers names such as access_token, id_token, client_secret, X-Amz-Signature, api_key, PHPSESSID, _wpnonce and _csrf.
  • parameters whose whole name is code, state, code_verifier, assertion, client_assertion, device_code, user_code, bearer, auth, authorization, auth_code, auth_key, sig, hmac, key, pass, pwd, otp, oobCode, sid, ticket or sso
  • JWTs anywhere in the URL, the path included
  • credentials written into the URL, as in https://user:password@host, up to the last @, and also with backslashes or JSON-escaped slashes (https:\/\/user:password@host) or in a URL nested in the path
  • session ids in the path, as in /cart;jsessionid=...
  • parameters of a URL held unencoded in another parameter, as in ?next=/reset?token=abc
  • parameters percent-encoded inside another parameter, as in ?next=%2Freset%3Ftoken%3Dabc, or in a value that is itself an encoded parameter, as in ?return_to=code%3Dabc

Parameters are separated by ?, #, &, an HTML-escaped & (written as & followed by amp;) and ;, and their encoded forms one level down. data: and blob: URLs are masked the same way.

These defaults are a security baseline: you can mask more with urlMasking, but you can't remove a default or turn masking off.

import { CoralogixRum } from '@coralogix/browser';

CoralogixRum.init({
// ...
urlMasking: {
params: ['tenant_id', /^customer/], // mask these too
mode: 'mask', // the default; or 'maskAll' or 'dropQuery'
},
});
OptionTypeDefaultDescription
paramsArray<string | RegExp>noneMore parameter names to mask. A string matches the whole name, compared as above. A RegExp is tested against the decoded name.
mode'mask' | 'maskAll' | 'dropQuery''mask'How much of each URL's query and fragment to hide. See below.

mode decides how much of the query and the fragment is hidden. For https://app.com/orders?code=abc&page=2#/expenses:

modeReported as
'mask' (default)https://app.com/orders?code=[REDACTED]&page=2#/expenses
'maskAll'https://app.com/orders?code=[REDACTED]&page=[REDACTED]#/expenses
'dropQuery'https://app.com/orders

'maskAll' keeps the parameter names and the #/route, so it suits apps that route with #. 'dropQuery' removes the #/route as well, so in those apps every page reports the same URL. In every mode, JWTs in the path, user:password@ credentials and session ids in the path are masked too.

Note

Masking runs before urlBlueprinters and beforeSend, so both receive the masked URL. The original value is not available to them. What a blueprinter returns is masked again, so a blueprinter cannot add a secret back.

Note

In an error message, a URL is found by its scheme (https://) or by a leading //. A relative URL in a message, such as /api/login?token=abc, is not masked.

Note

In session recordings, URLs inside an inline style attribute are not masked. When you replay a recording, an image whose URL had a masked value, such as a signed image URL, does not load.

Traces​

Add trace context propagation in headers across service boundaries

CoralogixRum.init({
// ...
traceParentInHeader: {
enabled: true,
},
});
Note

Trace headers are added by the fetch and xhr instrumentations, so this feature depends on them. If you set both instrumentations.fetch and instrumentations.xhr to false, no trace headers are sent even with enabled: true.

propagateTraceHeaderCorsUrls​

When the backend domain is different from the app domain, specifying backend domains is necessary.
For example, if the app is hosted on https://app.com and the backend is hosted on https://webapi.com, you should specify the backend domain.

CoralogixRum.init({
// ...
traceParentInHeader: {
enabled: true,
options: {
propagateTraceHeaderCorsUrls: [new RegExp('https://webapi.*')],
},
},
});

allowedTracingUrls​

Specify the allowed URLs to propagate the trace header.
Note that if allowedTracingUrls is not specified, the trace header will be propagated to all URLs.
allowedTracingUrls works only on 1st party URLs. (see propagateTraceHeaderCorsUrls for 3d party URLs)

For example if you want to propagate the trace header only for URLs that contain the word alpha:

CoralogixRum.init({
// ...
traceParentInHeader: {
enabled: true,
options: {
allowedTracingUrls: [new RegExp('alpha')],
},
},
});

Extra propagators​

B3 / AWS X-Ray propagation​

CoralogixRum.init({
// ...
traceParentInHeader: {
enabled: true,
options: {
// ...
/* for B3 propagation */
propagateB3TraceHeader: {
singleHeader: true,
multiHeader: true,
},
/* for Aws propagation */
propagateAwsXrayTraceHeader: true,
},
},
});

Custom propagation​

CoralogixRum.init({
// ...
traceParentInHeader: {
enabled: true,
options: {
// ...
/* for Custom propagation */
propagateCustomTraceHeader: new CustomPropagator()
},
},
});

// Example of CustomPropagator, Converts the 128-bit OpenTelemetry trace/span IDs into 64-bit decimal IDs

import {
TextMapGetter,
TextMapSetter,
TextMapPropagator,
Context,
trace,
} from '@opentelemetry/api';

export class CustomPropagator implements TextMapPropagator {
inject(context: Context, carrier: any, setter: TextMapSetter) {
const span = trace.getSpan(context);
if (!span) return;

const spanContext = span.spanContext();
if (!spanContext) return;

// Custom trace ID = last 64 bits of OTel trace ID
const customTraceId = BigInt(
'0x' + spanContext.traceId.slice(16)
).toString();
const customParentId = BigInt('0x' + spanContext.spanId).toString();

setter.set(carrier, 'my-custom-trace-id', customTraceId);
setter.set(carrier, 'my-custom-parent-id', customParentId);
}

extract(context: Context, carrier: any, getter: TextMapGetter): Context {
const traceIdHeader = getter.get(carrier, 'my-custom-trace-id');
const parentIdHeader = getter.get(carrier, 'my-custom-parent-id');

if (!traceIdHeader || !parentIdHeader) return context;

const traceId = BigInt(traceIdHeader as string)
.toString(16)
.padStart(32, '0');

const spanId = BigInt(parentIdHeader as string)
.toString(16)
.padStart(16, '0');

return trace.setSpan(
context,
trace.wrapSpanContext({
traceId,
spanId,
traceFlags: 1,
isRemote: true,
})
);
}

fields(): string[] {
return ['my-custom-trace-id', 'my-custom-parent-id'];
}
}



Last updated on