Integration Guides

Electron

Add Rybbit analytics to your Electron app

An Electron renderer is a Chromium page, so Rybbit runs in it the same way it runs in a browser. For a renderer built with a bundler (Vite, webpack, the Electron Forge templates) install the @rybbit/js SDK and initialise it in the renderer entry file; for a plain HTML renderer put the snippet in the <head> of the HTML file the window loads. In both cases allow https://app.rybbit.io in the renderer's Content Security Policy.

Get your tracking snippet

In your Rybbit dashboard, open Site Settings → Tracking Script and copy your snippet. It looks like this:

<script src="https://app.rybbit.io/api/script.js?siteId=YOUR_SITE_ID" defer></script>

YOUR_SITE_ID is the numeric ID of your site. If you self-host Rybbit, app.rybbit.io is the domain of your own instance.

Add the snippet to Electron

The SDK is bundled with your renderer code, so nothing is loaded from a CDN at runtime and script-src 'self' stays intact.

  1. Install the package in your project:
npm install @rybbit/js
  1. Initialise it once in the renderer entry file, before any other tracking call:
src/renderer.js
import rybbit from "@rybbit/js";

await rybbit.init({
  analyticsHost: "https://app.rybbit.io/api",
  siteId: "YOUR_SITE_ID",
});
  1. Allow the analytics host in connect-src. Electron recommends a CSP for every renderer; when the renderer is loaded from a file, HTTP headers are not available, so use the meta tag:
src/index.html
<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'self'; connect-src 'self' https://app.rybbit.io"
/>

Paste the snippet into the <head> of the renderer HTML and allow the host in both script-src (the script itself) and connect-src (its requests):

src/index.html
<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'self'; script-src 'self' https://app.rybbit.io; connect-src 'self' https://app.rybbit.io"
/>
<script src="https://app.rybbit.io/api/script.js?siteId=YOUR_SITE_ID" defer></script>

If you set the CSP from the main process with session.defaultSession.webRequest.onHeadersReceived instead, add the same two sources there.

Both methods track in-app navigation without extra code: the tracker wraps history.pushState and history.replaceState and listens for popstate and hashchange, so history-mode and hash-mode routers are covered.

Verify installation

Open your live site in a new tab and click through a few pages. Within a few seconds the pageviews appear in the Rybbit dashboard.

If nothing shows up:

  • View the page source and search for script.js?siteId= to confirm the snippet is on the page.
  • Open the browser Network tab and check that script.js returns 200 and that POST requests go to /api/track.
  • Disable ad blockers, or set up a proxy so the script loads from your own domain.
  • See the script troubleshooting guide for other common causes.

Troubleshooting

  • Requests are blocked on the file:// origin: Rybbit's tracking endpoints answer CORS preflights for http:// and https:// origins only. A renderer opened with win.loadFile() runs on the file:// origin and sends Origin: null, so Chromium blocks the POST to /api/track before it leaves the app. The same applies to custom schemes registered with protocol.handle(). Load the renderer over http(s) with win.loadURL() (your dev server in development, a hosted or locally served build in production) and tracking works.
  • Console shows a CSP violation: the message names the directive that blocked the request. Add https://app.rybbit.io to that directive; connect-src covers the SDK, and the script tag also needs script-src.
  • Hostname is empty in the dashboard: pageviews report the renderer's window.location.hostname, which is empty for file:// pages. Filter by site rather than hostname.

Next steps

On this page