Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions rum_salesforce_lwc/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# CHANGELOG - Salesforce

## 1.1.0

**_Added_**:

* Session Replay for Head Markup instrumentation.

## 1.0.0

**_Added_**:
Expand Down
225 changes: 145 additions & 80 deletions rum_salesforce_lwc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,17 @@ You can get those values in Datadog under **Digital Experience > Real User Monit

You should also enable [Lightning Web Security][1] in the Salesforce org.

### Installation
### Prepare your Salesforce site

All deployment paths share the first two steps. Complete them once before configuring a deployment path.
All deployment paths must allow connections to the Datadog browser intake. Lightning App Utility Bar and Experience Cloud Component deployments load the bundle from a Salesforce Static Resource. Experience Cloud Head Markup can load it from either Salesforce Static Resources or the Datadog CDN.

#### 1. Add Static Resource
#### 1. Add Salesforce Static Resources

[Download the Datadog RUM Salesforce bundle][2], then register it as the `datadog_rum` static resource. For example, download it into your project's static resources directory with:
This step is required for Lightning App Utility Bar and Experience Cloud Component deployments. For Experience Cloud Head Markup, follow it only if you want to host the SDK in Salesforce; skip it when using the Datadog CDN.

Download the bundle, then register it as the `datadog_rum` static resource. To support Session Replay and profiling in Head Markup, also upload its matching `chunks/` directory as a ZIP static resource named `chunks`, preserving the chunk filenames.
Comment thread
BeltranBulbarellaDD marked this conversation as resolved.

For example, download the bundle into your project's static resources directory with:

```shell
curl -o staticresources/datadog_rum.js https://www.datadoghq-browser-agent.com/us1/v7/datadog-rum-salesforce.js
Expand All @@ -49,6 +53,18 @@ Use this option when your Salesforce project is managed from source control. Com
</StaticResource>
```

For Head Markup with Session Replay or profiling, also add the `chunks` ZIP and its metadata:

`staticresources/chunks.resource-meta.xml`

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
<cacheControl>Public</cacheControl>
<contentType>application/zip</contentType>
</StaticResource>
```

<!-- xxz tab xxx -->
<!-- xxx tab "Salesforce UI" xxx -->

Expand All @@ -62,6 +78,8 @@ Use this option when you configure the static resource directly in Salesforce Se
4. Upload the downloaded RUM JavaScript bundle.
5. Set **Cache Control** to **Public**, then save.

For Head Markup with Session Replay or profiling, repeat these steps to upload the matching chunks ZIP with **Name** set to `chunks`.

<!-- xxz tab xxx -->
<!-- xxz tabs xxx -->

Expand Down Expand Up @@ -135,7 +153,7 @@ File location: `lwc/datadogInit/datadogInit.html`
Create the component JavaScript at `lwc/datadogInit/datadogInit.js`:

```javascript
import { LightningElement, api, wire } from 'lwc'
import { LightningElement, wire } from 'lwc'
import { NavigationMixin, CurrentPageReference } from 'lightning/navigation'
import datadogRum from '@salesforce/resourceUrl/datadog_rum'
import { loadScript } from 'lightning/platformResourceLoader'
Expand All @@ -144,12 +162,6 @@ let datadogInitialization
let lastStartedUrl

export default class DatadogInit extends NavigationMixin(LightningElement) {
@api applicationId
@api clientToken
@api site
@api service
@api env

connectedCallback() {
this.initialize()
}
Expand Down Expand Up @@ -188,12 +200,13 @@ export default class DatadogInit extends NavigationMixin(LightningElement) {
loadDatadogRum() {
return loadScript(this, datadogRum).then(() => {
const initConfig = {
applicationId: this.applicationId,
clientToken: this.clientToken,
env: this.env,
service: this.service,
site: this.site,
applicationId: '<YOUR_DATADOG_APPLICATION_ID>',
clientToken: '<YOUR_DATADOG_CLIENT_TOKEN>',
env: '<YOUR_ENV_NAME>',
service: '<YOUR_SERVICE_NAME>',
site: '<YOUR_DATADOG_SITE>',
sessionSampleRate: 100,
sessionReplaySampleRate: 0,
trackViewsManually: true,
trackLongTasks: true,
trackResources: true,
Expand Down Expand Up @@ -225,15 +238,6 @@ Expose the component to the Lightning Utility Bar, then add it to your app's Uti
<targets>
<target>lightning__UtilityBar</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__UtilityBar">
<property name="applicationId" type="String" label="Application ID" required="true" />
<property name="clientToken" type="String" label="Client Token" required="true" />
<property name="site" type="String" label="Site" />
<property name="service" type="String" label="Service" />
<property name="env" type="String" label="Env" />
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
```

Expand All @@ -246,31 +250,6 @@ Add the following `componentInstance` excerpt to your app's existing Utility Bar
<type>decorator</type>
<value>true</value>
</componentInstanceProperties>
<componentInstanceProperties>
<name>applicationId</name>
<type>String</type>
<value>YOUR_DATADOG_APPLICATION_ID</value>
</componentInstanceProperties>
<componentInstanceProperties>
<name>clientToken</name>
<type>String</type>
<value>YOUR_DATADOG_CLIENT_TOKEN</value>
</componentInstanceProperties>
<componentInstanceProperties>
<name>site</name>
<type>String</type>
<value>YOUR_DATADOG_SITE</value>
</componentInstanceProperties>
<componentInstanceProperties>
<name>service</name>
<type>String</type>
<value>YOUR_SERVICE_NAME</value>
</componentInstanceProperties>
<componentInstanceProperties>
<name>env</name>
<type>String</type>
<value>YOUR_ENV_NAME</value>
</componentInstanceProperties>
<componentName>datadogInit</componentName>
<identifier>datadogInit</identifier>
</componentInstance>
Expand All @@ -283,18 +262,77 @@ Add the following `componentInstance` excerpt to your app's existing Utility Bar

Use when you can edit Head Markup. This is the most direct Experience Cloud setup.

**Relax CSP in Experience Builder**
Head Markup runs outside LWS and is the only Salesforce deployment path that supports Session Replay. Load the `datadog-rum-salesforce.js` bundle from Salesforce Static Resources or the Datadog CDN.

All three loading methods support RUM and Session Replay:

- **Salesforce Static Resource** loads synchronously and hosts the SDK and its lazy-loaded chunks in Salesforce.
- **CDN async (recommended)** does not block page rendering, but it can miss events that occur before the SDK loads.
- **CDN sync** loads the SDK before subsequent scripts, collecting earlier events at the cost of potentially affecting page load performance.

For more information about the CDN loading methods, see [Browser Monitoring Setup][5].

##### 1. Configure CSP in Experience Builder

First, [allow Salesforce to connect to the Datadog browser intake](#2-configure-csp). When loading the SDK from the Datadog CDN, also allow the CDN host:

If you are using Salesforce Static Resources, no additional script host is required and you can continue to [Add Head Markup](#2-add-head-markup).
Comment thread
BeltranBulbarellaDD marked this conversation as resolved.

1. Open the site in Experience Builder from **Setup > Digital Experiences > All Sites > Builder**.
2. Go to **Settings > Security & Privacy**.
3. Change the security level from **Strict CSP** to **Relaxed CSP**.
4. Under **Trusted Sites for Scripts**, click **Add Trusted Site**.
5. Add `https://www.datadoghq-browser-agent.com` and make sure it is active.

For more information, see [Where to Allowlist Third-Party Hosts for Experience Builder Sites][6].

##### 1. Add Head Markup
##### 2. Add Head Markup

In Experience Builder, go to **Settings > Advanced > Edit Head Markup**, paste the following script, and replace the placeholder values with your Datadog RUM configuration. Save the change, then publish the site.
In Experience Builder, go to **Settings > Advanced > Edit Head Markup**, paste one of the following snippets, and replace the placeholder values with your Datadog RUM configuration. Set `sessionReplaySampleRate` to a value greater than `0` to enable Session Replay. Save the change, then publish the site.

###### Salesforce Static Resource

Use this after uploading the bundle and its chunks as described in [Add Salesforce Static Resources](#1-add-salesforce-static-resources).

```html
<script src="/sfsites/c/resource/datadog_rum" type="text/javascript"></script>
<script>
window.DD_RUM.onReady(function () {
window.DD_RUM.init({
applicationId: 'YOUR_DATADOG_APPLICATION_ID',
clientToken: 'YOUR_DATADOG_CLIENT_TOKEN',
site: 'YOUR_DATADOG_SITE',
service: 'YOUR_SERVICE_NAME',
env: 'YOUR_ENV_NAME',
sessionSampleRate: 100,
sessionReplaySampleRate: 100,
trackLongTasks: true,
trackResources: true,
trackUserInteractions: true,
})
})
</script>
```

###### CDN async (recommended)

```html
<script src="/sfsites/c/resource/datadog_rum"></script>
<script>
;(function (h, o, u, n, d) {
h = h[d] = h[d] || {
q: [],
onReady: function (c) {
h.q.push(c)
},
}
d = o.createElement(u)
d.async = 1
d.src = n
d.crossOrigin = 'anonymous'
n = o.getElementsByTagName(u)[0]
n.parentNode.insertBefore(d, n)
})(window, document, 'script', 'https://www.datadoghq-browser-agent.com/us1/v7/datadog-rum-salesforce.js', 'DD_RUM')
</script>
<script>
window.DD_RUM.onReady(function () {
window.DD_RUM.init({
Expand All @@ -304,6 +342,7 @@ In Experience Builder, go to **Settings > Advanced > Edit Head Markup**, paste t
service: '<YOUR_SERVICE_NAME>',
site: '<YOUR_DATADOG_SITE>',
sessionSampleRate: 100,
sessionReplaySampleRate: 100,
trackLongTasks: true,
trackResources: true,
trackUserInteractions: true,
Expand All @@ -312,6 +351,31 @@ In Experience Builder, go to **Settings > Advanced > Edit Head Markup**, paste t
</script>
```

###### CDN sync

```html
<script
src="https://www.datadoghq-browser-agent.com/us1/v7/datadog-rum-salesforce.js"
type="text/javascript"
crossorigin
></script>
<script>
window.DD_RUM &&
window.DD_RUM.init({
applicationId: '<YOUR_DATADOG_APPLICATION_ID>',
clientToken: '<YOUR_DATADOG_CLIENT_TOKEN>',
env: '<YOUR_ENV_NAME>',
service: '<YOUR_SERVICE_NAME>',
site: '<YOUR_DATADOG_SITE>',
sessionSampleRate: 100,
sessionReplaySampleRate: 100,
trackLongTasks: true,
trackResources: true,
trackUserInteractions: true,
})
</script>
```

<!-- xxz tab xxx -->
<!-- xxx tab "Experience Cloud Component" xxx -->

Expand Down Expand Up @@ -387,6 +451,7 @@ export default class DatadogInit extends NavigationMixin(LightningElement) {
service: '<YOUR_SERVICE_NAME>',
site: '<YOUR_DATADOG_SITE>',
sessionSampleRate: 100,
sessionReplaySampleRate: 0,
trackViewsManually: true,
trackLongTasks: true,
trackResources: true,
Expand Down Expand Up @@ -437,44 +502,44 @@ Expose the component to Experience Builder and place it in a shared region, page

The following table outlines SDK feature support within the Lightning Web Security (LWS) sandbox environment.

| Feature Area | Supported | Notes |
| ------------------- | ----------- | ------------------------------------------------------------------------- |
| **View Events** | | |
| Initial View | Yes | Automatic on init. |
| Manual Tracking | Yes | Supported through `startView`. |
| Navigation Timings | Yes | Collected via performance API. |
| Web Vitals | Yes | |
| **Resource Events** | | |
| Fetch / XHR | Limited (2) | Context payload inaccessible. |
| Other Resources | Yes | CSS, images, etc. |
| APM Correlation | Limited (2) | Requires header injection. |
| **Action Events** | | |
| Custom Actions | Yes | Supported through `addAction`. (5) Not supported on the Head Markup path. |
| Click Actions | Yes | (3) Shadow DOM boundaries apply. |
| Frustration Signals | Yes | |
| Loading Time | Limited (1) | Network detection may be incomplete. |
| **Error Events** | | |
| Console / Custom | Yes | Captured via instrumentation. (5) Not supported on the Head Markup path. |
| Runtime Errors | Limited (4) | Often redacted as "Script error." |
| Unhandled Rejection | No | Event not supported in LWS. |
| **Other** | | |
| Vital Events | Yes | |
| Long Task Events | Yes | |
| Session Replay | No | DOM/Worker constraints prevent support. |
| Feature Area | Supported | Notes |
| ------------------- | ---------------- | ----------------------------------------------------------------- |
| **View Events** | | |
| Initial View | Yes | Automatic on init. |
| Manual Tracking | Yes | Supported through `startView`. |
| Navigation Timings | Yes | Collected via performance API. |
| Web Vitals | Yes | |
| **Resource Events** | | |
| Fetch / XHR | Limited (2) | Context payload inaccessible. |
| Other Resources | Yes | CSS, images, etc. |
| APM Correlation | Limited (2) | Requires header injection. |
| **Action Events** | | |
| Custom Actions | Yes | Supported through `addAction`. |
| Click Actions | Yes | (3) Shadow DOM boundaries apply. |
| Frustration Signals | Yes | |
| Loading Time | Limited (1) | Network detection may be incomplete. |
| **Error Events** | | |
| Console / Custom | Yes | Captured via instrumentation. |
| Runtime Errors | Limited (4) | Often redacted as "Script error." |
| Unhandled Rejection | No | Event not supported in LWS. |
| **Other** | | |
| Vital Events | Yes | |
| Long Task Events | Yes | |
| Session Replay | Head Markup only | Unsupported inside LWS; use the Salesforce bundle in Head Markup. |

Footnotes:

1. **Loading Time**: Ends when no pending network requests are detected. LWS may hide some fetch/XHR activity.
2. **Limited Context**: Inaccessible sandbox objects mean `beforeSend` cannot access response bodies or full XHR objects.
3. **Selectors**: Due to shadow boundaries, `event.target` may reflect the component host rather than the inner element.
4. **Runtime Errors**: Errors passing through the Lightning shell may lose stack traces and original error objects.
5. **Head Markup limitation**: The Experience Cloud Head Markup path has no component context to call `addAction` or `addError`, so custom actions and custom error tracking are not supported there.

## Troubleshooting

Need help? Contact [Datadog Support][3].

[1]: https://developer.salesforce.com/docs/platform/lightning-components-security/guide/lws-enable.html
[2]: https://www.datadoghq-browser-agent.com/us1/v7/datadog-rum-salesforce.js
[3]: https://docs.datadoghq.com/help/
[4]: https://docs.datadoghq.com/getting_started/site/#access-the-datadog-site
[5]: https://docs.datadoghq.com/real_user_monitoring/application_monitoring/browser/setup/
[6]: https://help.salesforce.com/s/articleView?id=experience.networks_security_csp_allow.htm&type=5
Loading