Stape
Search
Contact salesTry for free

How GTM & gtag Use Service Workers for Analytics

Giovani Ortolani Barbosa

Giovani Ortolani Barbosa

Author
Published
Oct 10, 2025
!

⚠️ This post is based on extensive debugging and experimentation with Google Tag Manager (GTM) and the Google tag (gtag). While every detail here is accurate as of publication, note that Google's implementations may evolve, and may make some of what's detailed here out of date.

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.

What are Service Workers?

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.

How GTM and gtag use Service Workers

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.

Communication flow

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.

iframes in the DevTools Elements tab
iframes in the DevTools Elements tab

Real-world demonstration of the messages exchanged between the iframe and the Service Worker:

  • Service Worker from server-side GTM (sGTM) first-party domain
  • Service Worker from the googletagmanager.com domain

1. Service Worker loaded from sGTM first-party domain

This 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:

  • The event is not being sent directly to analytics.google.com/g/collect or www.google-analytics.com/g/collect (e.g., with the server_container_url parameter configured).
  • The page is not unloading (beforeunload event). During unload, requests like user_engagement event skip the Service Worker.
  • The browser isn't a restricted environment (such as WebView, Google App on iOS, or Facebook & Messenger In-App Browsers).

- 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"))

  • The Service Worker is alive and ready (state 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.

2. Service Worker loaded from googletagmanager.com domain

This Service Worker seems to handle events for Google Ads and Floodlight products.

Some requests pass through it, such as:

  • Google Ads User-Provided Event (requests to https://www.google.com/ccm/form-data/{Conversion ID}/... and https://www.google.com/pagead/form-data/{Conversion ID}/...)
  • Auto-captured User-data Event (requests to 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:

  • The tag is configured to send user data and the 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

  • The page is not unloading (beforeunload event).
  • The Service Worker is alive and ready (state 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.

The .delegate method

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:

StateMeaning
0initial state on page initialization
1attempting to establish communication between the main page and the Service Worker
2Service Worker is ready, and the handshake with the main page was successful
3retrying after error
4fatal error / failed / communication channel is closed

How to Check If Service Workers Are Being Used

You can verify Service Worker usage in several ways.

1. DevTools Network Tab

Filter for requests to sw.js or sw_iframe.html

i

Note:

sw.js only appears during the initial registration. It won't appear the next time you reload the page (unless you deregister the Service Worker manually.

Service Worker loaded from sGTM first-party domain.

Service Worker from sGTM first-party domain in DevTools Network tab
Service Worker from sGTM first-party domain in DevTools Network tab
Service Worker from sGTM first-party domain in DevTools Network tab
Service Worker from sGTM first-party domain in DevTools Network tab

Service Worker loaded from googletagmanager.com domain.

Service Worker from googletagmanager.com domain in DevTools Network tab
Service Worker from googletagmanager.com domain in DevTools Network tab

2. DevTools Application Tab

Open DevTools → go to Application tab → Service Workers → Click See all registrations and search for your domain.

  • If using GA4 to send data to sGTM: you'll see the Service Worker being served from your sGTM first-party domain.
Service Worker being served from the sGTM first-party domain
Service Worker being served from the sGTM first-party domain

If using any Ads products from Google: you'll see the Service Worker being served from googletagmanager.com.

Service Worker being served from googletagmanager.com
Service Worker being served from googletagmanager.com

3. DevTools Network Tab

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.

Gear icons in DevTools Network tab
Gear icons in DevTools Network tab

Why you don’t see some events in the Network Tab

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.

  1. Follow the steps outlined here.
  2. After finding the desired Service Worker, click Inspect to open its own DevTools window.
  3. Go to its Network tab, where your missing GA4 or Ads requests will appear.

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.

Conclusion

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:

  • Don't assume missing hits in the Network tab indicate tracking issues.
  • Check Service Worker activity before troubleshooting.

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.

Want to switch to the server side?Sign up now!

author

Giovani Ortolani Barbosa

Author

Giovani Ortolani Barbosa is an Integration Engineer at Stape who develops advanced Google Tag Manager templates, troubleshoots complex tracking issues, and specializes in server-side tagging.

Comments

Try Stape for all things server-side