DEV Community

Cover image for How to use <webview> and Measurement Protocol with Electron
dani
dani

Posted on

How to use <webview> and Measurement Protocol with Electron

Abstract

Bonb is a browser based on Electron. It's being developed by a small international team. It's open source, and can be downloaded on github: https://github.com/danielfebrero/bonb-browser

In this article, we will use terms such as Main or Renderer process. We assume that you have at least a basic knowledge of Electron.

Also, we are looking for beta testers and cofounders of any kind.

Securing Electron Webview tag

Preload a script

Instead of setting a preload attribute in the tag from the Renderer process, we force it's value directly in the Main process. It reduces the attack vectors and facilitates the import of the preload file.

app.on('web-contents-created', (_event, contents) => {
  contents.on('will-attach-webview', (_wawevent, webPreferences, _params) => {
    webPreferences.preloadURL = `file://${__dirname}/webview-preload.js`;
  });
}); 
Enter fullscreen mode Exit fullscreen mode

Opening pop-ups

A browser needs to support pop-ups and new windows. What we did is to intercept the 'new-window' event, and use a custom method 'addBrowser', after filtering the url with an adblocker.

In the renderer:

webview.addEventListener('new-window', (e) => {
    if (!isBlockedUrl(e.url)) addBrowser({ url: e.url });
});
Enter fullscreen mode Exit fullscreen mode

Also, to prevent a new window opening from the Main process, we intercept the event and prevent default:

app.on('web-contents-created', (_event, contents) => {
  contents.on('new-window', (e) => {
    e.preventDefault();
  });
});
Enter fullscreen mode Exit fullscreen mode

Permission requests

We have not completed the permission requests (webcam, mic...) implementation yet. Meanwhile, we are rejecting all requests:

session
      .fromPartition('user-partition')
      .setPermissionRequestHandler((webContents, permission, callback) => {
        callback(false);
      });
Enter fullscreen mode Exit fullscreen mode

Implement Google Analytics in Electron

By default, Gtag is not compatible with electron, because of the file protocol used to serve the app. We won't learn how to implement Gtag in Electron, but how to use the Measurement Protocol of Google Analytics.

Measurement protocol

The measurement protocol permits collecting analytic data through https requests. It requires to create an 'api_secret' for the property.

Main or Renderer process?

Because of CORS policy, it's less secure to implement Google Analytics in the renderer. You will prefer send the request from the Main process, after receiving events from the Renderer process.

For example, in the Main process:

const sessionId = v4();

const makePayload = (eventName: string, params?: Record<string, unknown>) => {
  return {
    client_id: machineIdSync(),
    events: [
      {
        name: eventName,
        params: {
          app_is_packaged: app.isPackaged ? 'true' : 'false',
          engagement_time_msec: 1,
          app_name: 'Bonb',
          app_version: appPackageJson.default.version,
          session_id: sessionId,
          ...params,
        },
      },
    ],
  };
};

export const event = (eventName: string, params?: Record<string, unknown>) => {
  const payload = makePayload(eventName, params);
  axios
    .post(
      'https://google-analytics.com/mp/collect?api_secret=&measurement_id=G-',
      payload
    )
    .catch(console.log);
};


ipcMain.on('analytics', async (_event, args) => {
  event(args.eventName, args.params);
});
Enter fullscreen mode Exit fullscreen mode

And in the Renderer process:

window.electron.ipcRenderer.sendMessage('analytics', {
    eventName: 'browser_navigate',
 });
Enter fullscreen mode Exit fullscreen mode

Logging users

As specified in the documentation, events don't trigger a user on Google Analytics. If you want to count one user when using the Measurement Protocol, you should add two parameters in the payload: 'engagement_time_msec' and 'session_id'.

Top comments (0)