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.
- Install the package in your project:
npm install @rybbit/js- Initialise it once in the renderer entry file, before any other tracking call:
import rybbit from "@rybbit/js";
await rybbit.init({
analyticsHost: "https://app.rybbit.io/api",
siteId: "YOUR_SITE_ID",
});- 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:
<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):
<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.jsreturns200and thatPOSTrequests 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 forhttp://andhttps://origins only. A renderer opened withwin.loadFile()runs on thefile://origin and sendsOrigin: null, so Chromium blocks thePOSTto/api/trackbefore it leaves the app. The same applies to custom schemes registered withprotocol.handle(). Load the renderer over http(s) withwin.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.ioto that directive;connect-srccovers the SDK, and the script tag also needsscript-src. - Hostname is empty in the dashboard: pageviews report the renderer's
window.location.hostname, which is empty forfile://pages. Filter by site rather than hostname.
Next steps
- Track custom events such as signups, purchases and button clicks.
- Identify users to connect sessions to accounts.
- Proxy the script through your own domain to bypass ad blockers.
- Script attributes let you skip or mask URLs and tag events.