In September 2024, Google introduced the use of Service Workers in Google Tag Manager (GTM) to improve performance and measurement reliability:
"Google Tag Manager may use a service worker to improve performance and measurement reliability. To ensure that the service worker loads correctly, consult the Content Security Policy guidelines." |
Then, in March 2025, Google announced an expansion of this feature:
"Google tag now uses service workers, when available, to send data to server-side Tag Manager, improving performance and measurement reliability." |
This article breaks down how GTM and gtag handle Service Workers, what a Service Worker is, how communication between them happens, and why your analytics requests might not appear in the DevTools Network tab.
Service Workers are background scripts that run separately from a website's main thread. They allow operations like caching, offline support, and background network requests, without blocking the user interface.
In the context of GTM and gtag, Service Workers are used to offload the task of sending measurement data from the web page (for example, GA4 or Ads hits), making tracking faster and more reliable, even during page unload events or on slow networks. Note that, in this context, it doesn't store the events to be sent later.
Two types of Service Workers can be registered, depending on your setup:
1. Service Worker from your server-side GTM (sGTM) first-party domain
Used for GA4 requests sent to server-side containers.
2. Service Worker from the googletagmanager.com
domain
Used mainly by Ads products (Google Ads and Floodlight) for form-data and user-data requests.
Both versions follow a similar communication model involving several browser entities.
When gtag or GTM runs, it creates an invisible iframe (src=”about:blank”
), which in turn loads another iframe, sw_iframe.html
. This second iframe is responsible for installing the Service Worker script (sw.js
).
These elements communicate through the browser’s postMessage()
API (to send the information) and the message
listener to receive it, forming this flow:
gtag/GTM ↔ iframe (about:blank) ↔ iframe (sw_iframe.html) ↔ sw.js (Service Worker)
This bridge allows gtag or GTM running on the main page to pass event data to the Service Worker, which then decides how and when to send it.
If you inspect the website page using the DevTools Elements tab, you'll be able to see the iframes.
Real-world demonstration of the messages exchanged between the iframe and the Service Worker:
googletagmanager.com
domainThis Service Worker is used for GA4 requests that are sent to a server-side GTM container.
The GA4 gtag
(G-{Measurement ID}
etc.) script is responsible for forwarding the events to the Service Worker.
It checks whether an event should be sent through the Service Worker based on several conditions:
analytics.google.com/g/collect
or www.google-analytics.com/g/collect
(e.g., with the server_container_url
parameter configured). beforeunload
event). During unload, requests like user_engagement
event skip the Service Worker. - More specifically, it checks if the Browser User Agent DOES NOT contain any of the following strings: "; wv"
OR "FBAN"
OR "FBAV"
OR (("GSA"
OR "GoogleApp"
) AND ("iPhone"
OR "iPad"
))
2
). - This check is done by the .delegate()
method, which can be seen here.
If all conditions are met, the event is sent through the Service Worker. Otherwise, it is sent directly using fetch
, XHR
, sendBeacon
, or Image
(in this order) from the main page.
And, if the first 2 conditions are met, the richsstsse
parameter is added to the event URL (learn more about it). This parameter enables the browser to process the response, such as sending requests instructed by the sGTM for 3rd party cookies synchronization.
This Service Worker seems to handle events for Google Ads and Floodlight products.
Some requests pass through it, such as:
https://www.google.com/ccm/form-data/{Conversion ID}/...
and https://www.google.com/pagead/form-data/{Conversion ID}/...
)https://www.google.com/ccm/form-data/{Conversion ID}/...
only).The Ads product gtag
script loaded in the page (AW-{Conversion ID}
, DC-{Floodlight Config ID}
, etc.) is responsible for forwarding the events to the Service Worker.
The conditions for using this Service Worker are similar:
send_user_data_hit
internal parameter is one of the following: - user_data_web
: used by the Auto-captured User-data Event
- user_data_lead
: used by the Google Ads User-Provided Event
beforeunload
event). 2
). - This check is done by the .delegate()
method, which can be seen here.
If any of these conditions are not met, the hit is sent from the main page as usual.
Both gtag and GTM include a method called .delegate
, which performs the final check before deciding whether to send the event through a Service Worker or the main page.
The logic is straightforward:
k.delegate = function (a, b, c) {
this.getState() !== 2
? (this.H.C( // Path 1: Not Ready - Sends event from main page.
this.C,
{
state: this.getState(),
hg: this.initTime,
ng: Math.round(Ab()) - this.initTime
},
void 0,
a.commandType
),
c({ // Call the failure callback
failureType: this.C
}))
: this.N.wo(a, b, c); // Path 2: Ready - Sends events from Service Worker.
};
Whenever the state
is 2
, the request is sent through the Service Worker. And through the main page, otherwise.
The Service Worker and the main page exchange heartbeat messages every X amount of time (currently, 5 seconds) to keep this state
updated. The state
variable represents the Service Worker’s readiness:
State | Meaning |
---|---|
0 | initial state on page initialization |
1 | attempting to establish communication between the main page and the Service Worker |
2 | Service Worker is ready, and the handshake with the main page was successful |
3 | retrying after error |
4 | fatal error / failed / communication channel is closed |
You can verify Service Worker usage in several ways.
Filter for requests to sw.js
or sw_iframe.html
.
Note:
Service Worker loaded from sGTM first-party domain.
Service Worker loaded from googletagmanager.com domain.
Open DevTools → go to Application tab → Service Workers → Click See all registrations and search for your domain.
If using any Ads products from Google: you'll see the Service Worker being served from googletagmanager.com.
Requests handled by a Service Worker show a gear icon next to the URL. These represent hits sent from the background process rather than the main page.
If your GA4 or Ads events aren't appearing in the main page Network tab, they are likely being sent by the Service Worker instead. They will, however, still show up in the GTM Preview Mode window, and you can inspect them there.
You may see up to two Service Workers: one for your sGTM domain and another for Google's domain. Each handles different types of events, as described above.
Google's gradual integration of Service Workers into GTM and gtag marks a shift towards a more robust form of delivering and handling the events. By offloading event delivery to background scripts, Google improves performance, reliability, and data capture accuracy, especially in edge cases like quick bounces or flaky connections, but it also means some requests will not appear in the traditional Network tab.
For digital analytics specialists, this means:
As this feature continues to evolve, staying aware of how gtag and GTM leverage Service Workers will be crucial for accurate debugging and data reliability.
Comments