Electron Integration
Overview
An Electron application draws its user interface in Chromium windows, so the Pyze Web SDK runs in an Electron app the same way it runs in a browser. Once the SDK is loaded in a window, Pyze automatically captures page views and user interactions, and you can track custom events and user profiles.
Prerequisites: Create a Pyze app and obtain your App Key before proceeding.
There are two ways to add Pyze. Choose by whether you can change the application’s source code.
| Option | Use when |
|---|---|
| A. Add Pyze JavaScript to your application | You build the application |
| B. Add Pyze to the packaged application | You install an application built by someone else |
Option A – Add Pyze JavaScript to Your Application
Step 1: Add the SDK
Add Pyze JavaScript to your application: paste the following between the <head> and </head> tags of every HTML page your application loads in a window, and fill in pyzeConfig:
<script type="text/javascript">
var pyzeConfig = {
"appKey": "YOUR_PYZE_APP_KEY",
"whitelistedURLs": ["https://*.example.com/*"]
};
var pyzeAppKey = pyzeConfig.appKey;
!function(e,t){var s=e.Pyze||{_q:[]},i=e.PyzeEvents||{_q:[]},n=e.PyzeCuratedEvents||{_q:[]},r=e.PyzeIdentity||{_q:[]};function p(t,e){function s(e){t[e]=function(){t._q.push([e].concat(Array.prototype.slice.call(arguments,0)))}}for(var i=0;i<e.length;i++)s(e[i])}p(s,["initialize","getTimerReference","getAppInstanceId","postWebAppVersion","postPageView","setUserOptOut","deleteUser"]),p(i,["postCustomEvent","startTimerForEvent","postCustomEventWithAttributes","postTimedEvent","postTimedEventWithAttributes","postExplicitActivation"]),p(n,["post"]),p(r,["setUserProfile","resetUserProfile","updateUserProfile"]);var o=t.createElement("script"),a=t.getElementsByTagName("script")[0];o.type="text/javascript",o.async=!0,o.src="https://cdn.pyze.com/pyze.js",a.parentNode.insertBefore(o,a),e.Pyze=s,e.PyzeEvents=i,e.PyzeCuratedEvents=n,e.PyzeIdentity=r}(window,document),Pyze.initialize(pyzeAppKey);
</script>
appKey: the App Key from your Pyze account.whitelistedURLs: address patterns of the pages Pyze runs on, for examplehttps://*.example.com/*,app://myapp/*, orfile://*for pages loaded from the application’s own files.*matches one part of an address, or the rest of it when it ends the pattern.
Step 2: Allow Pyze in your Content Security Policy
If your pages define a Content Security Policy (CSP), add the following to it:
| Directive | Add | Used for |
|---|---|---|
script-src |
'unsafe-inline' |
Running Pyze JavaScript, which is an inline script |
script-src |
https://cdn.pyze.com |
Downloading the Pyze SDK |
connect-src |
https://unifiedcollector.pyze.com |
Sending events to Pyze |
For example:
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.pyze.com; connect-src 'self' https://unifiedcollector.pyze.com"
/>
If you set the policy as a response header from the main process, make the same additions there.
If you would rather not download the SDK from the Pyze CDN, save https://cdn.pyze.com/pyze.js next to your HTML page and replace https://cdn.pyze.com/pyze.js in Pyze JavaScript with ./pyze.js. https://cdn.pyze.com is then not needed in script-src, but you have to update the saved copy yourself when Pyze releases a new SDK.
Then verify the installation.
Option B – Add Pyze to the Packaged Application
Use this option when you cannot change the application’s source code, for example when the application is supplied by another company. You add Pyze to the installed application package when you deploy it.
An Electron application keeps its code in a package, usually a single file named app.asar. You add three files to it: the Pyze SDK, a startup script that loads the SDK into the application’s pages and then starts the application as normal, and a configuration file with your App Key and the pages to cover. The application’s own files are not edited, apart from one line in its package.json.
Before you start
-
You need Node.js 22.12 or later on the computer where you prepare the package. With an older Node.js, use
@electron/fuses@1and@electron/asar@3in the commands below. -
Locate the package:
resources\app.asarin the installation folder on Windows,Contents/Resources/app.asarinside the.appbundle on macOS. Keep a copy of the original file. -
Check that the application accepts a modified package:
npx @electron/fuses read --app "/path/to/the/application"If the output shows
EnableEmbeddedAsarIntegrityValidation is Enabled, the application refuses to start with a modified package and this option cannot be used. -
If the application’s pages define a Content Security Policy, it must allow connections to
https://unifiedcollector.pyze.cominconnect-src. The SDK loads regardless of the policy, but it cannot send events to a domain the policy blocks. To check, search the extracted HTML files forContent-Security-Policyafter step 1, or look for a Content Security Policy error namingunifiedcollector.pyze.comin the Developer Tools console. If the policy blocks the domain, this option cannot be used until the application’s supplier allows it.
Steps
-
Extract the package into a folder named
app:npx @electron/asar extract app.asar app -
Open
app/package.jsonand note the value ofmain, for examplemain.js. This is the application’s startup script. -
Download the SDK from
https://cdn.pyze.com/pyze.jsand save it asapp/pyze.js. Do not edit it. -
Create
app/pyze-main.cjswith the following content. Do not change it; all settings go in the configuration file in the next step. Keep the.cjsfile extension.// Loads the Pyze SDK into the application's pages, then starts the application. // Settings are read from pyze-config.json in the same folder. const { app } = require("electron"); const fs = require("node:fs"); const path = require("node:path"); let config; try { config = JSON.parse(fs.readFileSync(path.join(__dirname, "pyze-config.json"), "utf8")); } catch (err) { throw new Error("Pyze: cannot read pyze-config.json: " + err.message); } for (const key of ["appKey", "originalMain", "whitelistedURLs"]) { if (!config[key]) throw new Error('Pyze: "' + key + '" is missing from pyze-config.json'); } // Turns a pattern such as "https://*.example.com/*" into a regular expression. // A "*" matches anything except "/"; a "*" at the end matches the rest of the address. function toRegExp(pattern) { const parts = pattern.split("*").map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")); const last = parts.pop(); return new RegExp("^" + parts.join("[^/]*") + (last === "" ? ".*" : "[^/]*" + last) + "$"); } const whitelistedURLs = config.whitelistedURLs.map(toRegExp); const pyzeSdk = fs.readFileSync(path.join(__dirname, "pyze.js"), "utf8"); // Does the same job as Pyze JavaScript in Option A, without downloading the SDK from the CDN. const pyzeSetup = ` window.pyzeAppKey = ${JSON.stringify(config.appKey)}; (function (w) { function stub(name, methods) { var api = w[name] = w[name] || { _q: [] }; methods.forEach(function (method) { api[method] = function () { api._q.push([method].concat(Array.prototype.slice.call(arguments))); }; }); } stub("Pyze", ["initialize", "getTimerReference", "getAppInstanceId", "postWebAppVersion", "postPageView", "setUserOptOut", "deleteUser"]); stub("PyzeEvents", ["postCustomEvent", "startTimerForEvent", "postCustomEventWithAttributes", "postTimedEvent", "postTimedEventWithAttributes", "postExplicitActivation"]); stub("PyzeCuratedEvents", ["post"]); stub("PyzeIdentity", ["setUserProfile", "resetUserProfile", "updateUserProfile"]); w.Pyze.initialize(w.pyzeAppKey); })(window); `; app.on("web-contents-created", (event, contents) => { contents.on("dom-ready", () => { const url = contents.getURL(); if (!whitelistedURLs.some((pattern) => pattern.test(url))) return; contents .executeJavaScript('typeof window.Pyze !== "undefined"') .then((alreadyLoaded) => { if (alreadyLoaded) return; return contents.executeJavaScript(pyzeSetup + pyzeSdk + "\n;void 0;"); }) .catch((err) => console.error("[pyze] could not load the SDK into", url, err)); }); }); require(path.join(__dirname, config.originalMain)); -
Create
app/pyze-config.jsonwith the following content:{ "appKey": "YOUR_PYZE_APP_KEY", "originalMain": "main.js", "whitelistedURLs": ["file://*"] }appKey: your Pyze App Key.originalMain: the value you noted in step 2.whitelistedURLs: address patterns of the pages Pyze is loaded into, as in Option A. Leave out other parties' pages, such as a sign-in page.
-
In
app/package.json, change the value ofmaintopyze-main.cjs. Do not change anything else in the file. -
Build the package again and replace the original
app.asarwith it:npx @electron/asar pack app app.asarIf the application has an
app.asar.unpackedfolder next toapp.asar, keep the same files unpacked with the--unpackor--unpack-diroption of@electron/asar. -
On macOS, changing the package invalidates the application’s code signature; sign the application again with your own certificate. On Windows, the executable file is not changed, so its signature is not affected.
-
Start the application, check that it works as before, then verify the installation.
-
Deploy the modified package with your software deployment tool.
Repeat these steps each time the application is updated. If the application updates itself automatically, turn that off, or the update replaces the modified package.
Note
Pyze is loaded into the main page of each window. Content that the application shows inside an<iframe> is not covered. If a page already includes Pyze, the startup script leaves it as it is.
Verify Installation
- Start the application.
- Open Developer Tools: View → Toggle Developer Tools, or press Ctrl+Shift+I (Cmd+Option+I on macOS).
- In the Console tab, type
Pyze. It should print an object, notundefined. - In the Network tab, use the application for a moment. You should see requests to
unifiedcollector.pyze.comreturning status 202.
If the application has no Developer Tools menu, check that events arrive in your Pyze account.
Tracking Events and Users
Once Pyze is loaded, all Pyze Web SDK functions are available in the application’s pages. See the Web SDK guide for custom events, user profiles, dimensions and user privacy.
Troubleshooting
| Symptom | Likely cause | Action |
|---|---|---|
Pyze is undefined |
The page’s address does not match any pattern in whitelistedURLs, or (Option A) Pyze JavaScript is not in this window’s page |
Check the page address with location.href in the Developer Tools console and add a matching pattern; check that the page contains Pyze JavaScript |
Console shows a Content Security Policy error for cdn.pyze.com, an inline script, or unifiedcollector.pyze.com |
The policy lacks one of the entries from Option A, Step 2 | Add the missing entry |
Pyze is defined but there are no requests to unifiedcollector.pyze.com |
The collector is blocked by a proxy or firewall, or the computer is offline | Allow unifiedcollector.pyze.com on the network |
| Application does not start after its package was modified | The application validates its package, or originalMain in pyze-config.json does not match the original main value |
Restore the original app.asar. Check originalMain, and check the fuses as described in Before you start |
Application shows an error that starts with Pyze: cannot read pyze-config.json or Pyze: "..." is missing |
pyze-config.json is missing, is not valid JSON, or lacks one of its three settings |
Fix the file and build the package again |
Application does not start after its package was modified, with an error that mentions ERR_REQUIRE_ESM |
The application uses ES modules on an older Electron version, which the startup script cannot load | Restore the original app.asar and contact Pyze |