Developers building hybrid applications with Capacitor often face a split-brain problem when it comes to user tracking: web applications rely on standard Google Analytics (GA4) and Google Tag Manager (GTM), while native iOS and Android applications require Firebase Analytics. To solve this fragmented tracking experience, developer Arpad Kish (@arpad1337) created analytics-web-capacitor, an open-source extension designed to unify Google Analytics across both Web and Capacitor application environments.
Here is a deep dive into how this elegant solution works under the hood.
The Core Architecture
At the heart of the extension is the analytics.ts file, which exports an Analytics class that requires both an Analytics ID and a Tag Manager ID for initialization. When loadAnalytics() is called, the script determines if the app is running in a standard web browser or within a native Capacitor environment by checking if the window.location.origin includes ://app-symbol.
Because native webviews often place strict limitations on standard script tag injections, the tool bypasses this by fetching gtm.js and tracking.js directly via XMLHttpRequest. Once successfully fetched, the tracking scripts are executed using eval() to ensure they load reliably regardless of the Capacitor routing scheme.
Intercepting the Data Layer
To make standard web tracking code work natively, the extension relies on a clever TypeScript implementation called DataLayerArray.
-
Extending the Standard Array:
DataLayerArrayextends the native JavaScriptArrayand overrides thepushmethod. -
Global Assignment: The global
window.dataLayeris then replaced with this customDataLayerArray. -
Standard Compatibility:
window.gtagcommands are mapped to simply push their arguments into this array, maintaining complete compatibility with typical web implementations.
Bridging Web Events to Native Firebase
For Capacitor apps running on native devices, the extension bridges web events to native Firebase Analytics using @capacitor-community/firebase-analytics.
It accomplishes this via the setFirebaseBridgedTrackingProxy method, which acts as a middleware for the dataLayer. Whenever an event is pushed to the dataLayer, the proxy intercepts it, appends native OS data via Capacitor.getPlatform(), and programmatically forwards the event and its parameters to FirebaseAnalytics.logEvent(). This allows developers to write web-based tracking code once and trust that it will automatically translate to native SDK calls on iOS and Android.
Handling Single Page Application (SPA) Routing
Single Page Applications often break standard pageview tracking because the browser doesn't undergo a full page refresh. analytics-web-capacitor handles this natively via the setGTMHistoryChangeEventProxy method.
-
History Change Listener: The proxy watches the data layer for Google Tag Manager's
gtm.historyChange-v2events. - Virtual URLs: Upon detecting a route change, it strips protocols to calculate the new and old "virtual" paths.
-
Manual Page Views: It then automatically triggers a custom
page_viewevent containing thevirtual_page_locationandvirtual_page_referrerparameters.
Usage and Availability
By integrating this setup, developers can rely on standard, unified tracking syntax throughout their application:
window['gtag']('event', 'custom_event', {
page_title: document.title,
page_location: document.location.href,
virtual_page_location: path,
...
});
The analytics-web-capacitor software is provided "AS IS" and is freely available under the MIT License, copyrighted by Arpad K. in 2025.
Top comments (0)