m Moritz Bauer — writing on digital data
◦ Essay ·

Google Analytics in Electron Apps

Integrating Google Analytics 4 and Universal Analytics into an Electron desktop app — the obstacles and the workarounds.

The Electron framework is used to build cross-platform desktop apps with JavaScript, HTML, and CSS. Apps like MS Teams or MS Visual Studio Code are well-known examples.

At first glance, the inside of an Electron app looks very similar to a traditional website. So my expectation was that integrating Google Analytics would be straightforward. Sadly, that’s only partly the case. The following is about instrumenting my Electron app with Google Analytics 4 and Universal Analytics.

Method 1: Google Tag Manager

The Google Tag Manager is my preferred way of integrating Google Analytics 3 and 4 — and other marketing platforms like Meta or Google Ads — into traditional websites.

As expected, the integration of Google Tag Manager via the classic code snippet in the HTML works fine. For testing purposes I implemented a GA4 config including a pageview event, as well as a Universal Analytics pageview.

What you quickly notice is that no hits are sent at all, even though gtag.js and analytics.js load.

Protocol Checking

By default, both gtag.js and analytics.js check the protocol in use. Because the application runs locally and uses the file:// protocol, the dispatching of hits is blocked before they go out.

This behavior can be turned off using a field. Setting checkProtocolTask = null disables the protocol check.

Google Tag Manager — Fields to Set

Important caveat: there is currently no way to disable this check for Google Analytics 4. Tracking via the standard tags is therefore not possible. There has been an open issue on this for several months:

Google Issue Tracker

Missing cookies & broken URLs

The protocol check isn’t the only hurdle, though. There is no way to store cookies in Electron. So both the use of storage and a manually managed clientId are required, since cookies like _ga can’t be used to persist a clientId. With storage = none you can prevent GA3 from setting cookies. For GA4 unfortunately the only option (again) is via Consent Mode.

Finally, the page_location parameter has to be set manually, otherwise the file path of the HTML file is automatically used.

Payload of a Universal Analytics pageview hit with the file path

If page_location is not overwritten with a syntactically valid URL, the hit will be sent but discarded at the endpoint.

So tracking an Electron app with Google Analytics 3 (Universal Analytics) is fairly simple, taking the points above into account.

It’s worth noting that the debug mode of the Google Tag Manager doesn’t work in this environment. The usual testing before publishing the workspace is therefore not possible.

Given that GA3 is being shut down next year, starting a new tracking project on Universal Analytics today doesn’t really make sense. Using GA4 is much more sensible at this point.

So which approaches are there for tracking GA4 in an Electron app?

Method 2: Measurement Protocol

For both GA3 and GA4 there is the option to send HTTP requests directly to the Google Analytics endpoint via the Measurement Protocol.

events[0].params.session_id = sessionId;

fetch(`https://www.google-analytics.com/mp/collect?measurement_id=${measurement_id}&api_secret=${api_secret}`,{
   method: "POST",
   body: JSON.stringify({
      client_id: clientId,
      events: events
   })
});

Unfortunately, the Measurement Protocol for GA4 was designed by Google as a complement rather than a complete replacement. Events do show up in the realtime view, but most of the standard information that is normally captured by the web tracking is missing.

Despite passing client and session IDs, no active user is shown in the realtime overview, although the events themselves are visible.

User data is also missing in the standard reports, e.g. in the acquisition tab.

Google Analytics 4 — Acquisition overview

This unfortunately confirms the suspicion that the new Measurement Protocol for GA4 is not suitable as the only tracking solution.

That doesn’t mean the result is unsatisfactory — but you have to make significant compromises. Marketing channel measurement using UTM parameters is not possible in the same way, and automatic events like first_visit are not tracked either.

Markus Baersch published an extensive test of the GA4 Measurement Protocol on his blog.

Conclusion

It raises the question whether a different analytics tool is better suited for this use case. Giving up fundamental features that make GA4 what it is is not a good option in my view. And if you have to fall back on a niche solution that needs a lot of effort anyway, that effort might be better invested in a more suitable analytics tool.

Too bad that Google didn’t keep the GA3 Measurement Protocol’s design here, because that would have made implementation conceivable.

Update February 2023: David Vallejo has built a Node.js library that fills this gap by manually rebuilding the hits. More information on the official developer site.