Skip to content

Electron Application Integration Guide

Applications integrating the Windows SDK should use the native Bridge mode

This page describes the Web integration approach where Browser RUM independently manages sessions and uploads directly. If your Electron app integrates the Windows RUM SDK, please refer to Windows SDK Electron Native Bridge Integration: in that mode, Browser RUM only handles collection and serialization in the Renderer process, while the actual application ID, session, sampling, context, persistence, and upload are managed by the Windows Native Core. Do not blindly copy the applicationId, clientToken, site, or sessionPersistence configuration from this page.

An Electron application consists of a main process and renderer processes. The RUM SDK runs in a browser environment, so it should only be initialized in the renderer process to collect page visits, resources, requests, errors, and user behavior data.

This document explains how to integrate the SDK into an Electron application using the current SDK initialization parameters.

Integration Principles

  • Initialize the RUM SDK only in the renderer process, never in the main process.
  • Each BrowserWindow, BrowserView, or webview that needs monitoring requires its own RUM SDK initialization in the corresponding renderer page.
  • If the page is loaded via file://, you must use sessionPersistence: 'local-storage' to avoid relying on unavailable or unreliable cookies.
  • If the page is loaded via https://, you can continue using the default cookie session strategy; you may also use local-storage consistently, but ensure the session strategy is aligned between the RUM and Logs SDKs.
  • If the same Electron application uses both local file:// pages and remote http(s):// pages, they will be isolated by the browser's same-origin policy and typically generate different sessions.

NPM Integration

Suitable for Electron applications that build renderer code using Webpack, Vite, Rollup, etc.

npm install @cloudcare/browser-rum @cloudcare/browser-core

Initialize in the renderer entry file:

import { datafluxRum } from '@cloudcare/browser-rum'

datafluxRum.init({
  applicationId: '<application ID>',

  // Public DataWay integration
  clientToken: '<clientToken>',
  site: '<Public DataWay address>',

  // If using DataKit integration, configure datakitOrigin instead
  // datakitOrigin: '<DataKit domain or IP>',

  service: 'electron-renderer',
  env: 'production',
  version: '<application version>',
  sessionSampleRate: 100,
  trackUserInteractions: true,

  // Required for file:// pages
  sessionPersistence: 'local-storage'
})

If you need Session Replay:

datafluxRum.startSessionReplayRecording()

CDN Integration

Suitable for applications that maintain renderer HTML directly. It is recommended to bundle the SDK file as a static asset of the application to avoid relying on remote CDN when the desktop app is offline or on a weak network.

<script src="./vendor/dataflux-rum.js" type="text/javascript"></script>
<script>
  window.DATAFLUX_RUM &&
    window.DATAFLUX_RUM.init({
      applicationId: '<application ID>',
      clientToken: '<clientToken>',
      site: '<Public DataWay address>',
      service: 'electron-renderer',
      env: 'production',
      version: window.__APP_VERSION__,
      sessionSampleRate: 100,
      trackUserInteractions: true,
      sessionPersistence: 'local-storage'
    })
</script>

If the renderer page is always loaded via https:// and cookies are available, you can omit the sessionPersistence configuration.

Main Process Example

The main process is responsible for creating windows and does not need to import or initialize the RUM SDK. It is recommended to only pass necessary information such as version and channel to the renderer.

const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow() {
  const win = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false
    }
  })

  win.loadFile('index.html')
}

app.whenReady().then(createWindow)

The preload.js can expose only safe, read-only application information:

const { contextBridge } = require('electron')
const { version } = require('./package.json')

contextBridge.exposeInMainWorld('electronAppInfo', {
  version
})

In the renderer, read and pass the configuration to RUM:

datafluxRum.init({
  applicationId: '<application ID>',
  clientToken: '<clientToken>',
  site: '<Public DataWay address>',
  service: 'desktop-app',
  env: 'production',
  version: window.electronAppInfo.version,
  sessionSampleRate: 100,
  trackUserInteractions: true,
  sessionPersistence: 'local-storage'
})

Multi-Window Integration

If the application opens multiple windows simultaneously:

  • Initialize the RUM SDK in the renderer page of each window.
  • When using sessionPersistence: 'local-storage', there may be a very short delay in localStorage synchronization between windows.
  • If a large number of windows are created and initialized at the same time, very short temporary sessions may appear. It is recommended to keep at least a few tens of milliseconds between window creation and initialization, or create windows one by one according to the business order.

Local Pages and Remote Pages

Electron applications commonly have two types of page sources:

Page Source Recommended Configuration Description
file:// local pages sessionPersistence: 'local-storage' Cookies are unreliable; localStorage must be used to store the session.
https:// remote pages Default cookie or local-storage If using default cookies, ensure that the page domain and security policy allow cookies to be written.
Mixed file:// and https:// Integrate separately, analyze separately Due to the same-origin policy, local pages and remote pages typically do not share the same session.

If the application navigates from a local landing page to a remote site, expect them to appear as two different sessions in RUM. It is recommended to use consistent user.id, service, env, and version fields for correlation analysis.

datafluxRum.setUser({
  id: currentUserId,
  name: currentUserName
})

API Requests and Distributed Tracing

fetch and XMLHttpRequest in the renderer are automatically collected by the browser SDK logic. To inject Trace Headers into backend API requests, configure allowedTracingUrls:

For NPM + TypeScript integration, use the TraceType enum imported from the browser-core package for traceType:

import { TraceType } from '@cloudcare/browser-core'
import { datafluxRum } from '@cloudcare/browser-rum'

datafluxRum.init({
  applicationId: '<application ID>',
  clientToken: '<clientToken>',
  site: '<Public DataWay address>',
  service: 'desktop-app',
  env: 'production',
  version: window.electronAppInfo.version,
  sessionPersistence: 'local-storage',
  allowedTracingUrls: [
    'https://api.example.com',
    /https:\/\/.*\.internal-api\.example\.com/
  ],
  traceType: TraceType.DDTRACE
})

For CDN integration without module imports, use the runtime value 'ddtrace' when specifying the type explicitly; if not configured, it also defaults to 'ddtrace'.

Do not include file:// page addresses in allowedTracingUrls. This configuration is used to match backend API requests, not the renderer page itself.

Errors and Source Maps

Error stacks from local Electron pages often start with file://, which the server may not be able to match with Source Maps as easily as public URLs. We recommend:

  • Keep service, env, version consistent with the build artifacts.
  • Generate Source Maps for renderer artifacts and save them per release version.
  • If you need to rewrite local file paths, you can add business context in beforeSend to facilitate later retrieval.
datafluxRum.init({
  // ...
  beforeSend: (event) => {
    if (event.type === 'error') {
      event.context = {
        ...event.context,
        electron: true,
        rendererUrl: window.location.href
      }
    }
    return true
  }
})

CSP and Workers

If you enable Session Replay, compressIntakeRequests, or canvas recording, the SDK may use Workers. If the Electron application has a strict Content Security Policy, you need to allow the corresponding Worker source.

Default inline Workers usually require:

worker-src blob:;

If blob: is not allowed, bundle the worker file as a static asset of the application and configure the same-origin URL:

datafluxRum.init({
  // ...
  workerUrl: './worker.js',
  replayCanvasWorkerUrl: './canvas-worker.js'
})

If you use @cloudcare/browser-rum-slim, this package does not include Session Replay or compressIntakeRequests compression capabilities, so you generally do not need to configure workers for these two features.

Security Recommendations

  • Do not expose RUM tokens or other sensitive configuration write interfaces in the main process.
  • preload should only expose necessary read-only information, such as application version, channel, and build number.
  • Keep contextIsolation: true and nodeIntegration: false.
  • Do not report absolute local file paths, user directories, or other sensitive information in beforeSend.
  • Sanitize user input, file names, paths, and other fields before adding them to custom context.

Verification

After integration, verify in the following order:

  1. Open the target window of the Electron application.
  2. In DevTools Network, confirm that RUM upload requests are present.
  3. Trigger a page visit, button click, API request, and frontend error.
  4. Confirm that view, action, resource, and error data is ingested into Guance.
  5. Check that the session behaves as expected when the same user switches between multiple windows or local/remote pages.

During local debugging, you can temporarily enable beforeSend to print event types:

datafluxRum.init({
  // ...
  beforeSend: (event) => {
    console.log('[RUM]', event.type, event)
    return true
  }
})

Frequently Asked Questions

Why is there no data from the main process?

The RUM SDK is a browser-side SDK that only collects page behavior in the renderer process. Crashes, IPC, file system, or native module errors in the main process need to be handled by the application's own logging or crash collection mechanisms.

Why does the file:// page have no session?

This is usually because sessionPersistence: 'local-storage' is not configured, or the renderer page environment has disabled localStorage. First confirm that the configuration is present and localStorage is available.

Why does the session change when navigating from a local page to a remote page?

file:// and https:// are different origins, so the browser will not share the same cookie or localStorage. It is recommended to use setUser() to set a stable user ID and correlate by user during analysis.

Why do short sessions appear in multi-window setups?

When multiple windows are initialized simultaneously, there may be a very short delay in localStorage synchronization between windows. It is recommended not to create and initialize a large number of windows at the exact same moment; keep a brief interval between window creations.

References

Feedback

Is this page helpful?