🔋

How to Forward Events from the Main Thread to GTM Running Inside Partytown

When GTM runs inside a Web Worker via Partytown, direct calls to gtag or dataLayer.push on the main thread won’t work by default. To forward custom events correctly, use the forward option in astro.config.mjs to proxy these function calls from the main thread to the Worker, ensuring your tracking events are delivered while improving performance.

Background

Many websites use Google Tag Manager (GTM) to inject third-party tracking scripts such as GA4 or Microsoft Clarity. However, when t11hese scripts run on the main thread, they often slow down page performance—especially on mobile—causing LCP delays and lower PageSpeed scores.

Partytown solves this by moving heavy third-party scripts into a Web Worker, effectively freeing the main thread. The performance gain is clear, but it introduces a common issue:

  • The main thread no longer has dataLayer or gtag, which means custom events cannot be sent.

Even if you manually call:

Js
gtag('event', 'login', { id: 'abc' });
window.dataLayer.push({ event: 'login', id: 'abc' });

no event will be dispatched, simply because the main thread does not provide these functions or variables anymore.

What Is Partytown?

Partytown is a library that offloads resource-intensive scripts to a Web Worker, improving page rendering performance.

Integrating it into an Astro project is straightforward:

Bash
npm install @astrojs/partytown

Once enabled, Astro automatically injects Partytown’s runtime into the <head>. To run third-party scripts inside the Worker, mark them as:

HTML
<script
  type="text/partytown"
  src="https://example.com/third-party.js"
></script>

This works well when you only rely on GA4’s default events (e.g., page_view, session_start). In many cases, this alone can improve your mobile PageSpeed score by around 20 points.

But custom events require an additional step.

Enabling Custom Event Forwarding

To make calls like dataLayer.push() or gtag() work on the main thread, you need to explicitly enable event forwarding in Astro.

Update astro.config.mjs

Js
import partytown from '@astrojs/partytown';

export default {
  integrations: [
    partytown({
      config: {
        forward: ['dataLayer.push', 'gtag'], // Declare functions that should be forwarded to the worker
      },
    }),
  ],
};

How It Works

Partytown’s forward mechanism listens for specified function calls on the main thread and forwards them to the Web Worker where GTM is running. For example:

Js
gtag('event', 'login', { id: 'abc' });
window.dataLayer.push({ event: 'login' });

Both invocations will be intercepted and delivered to GTM inside the Worker, allowing events to be processed and reported as expected.

Related Tips

Subscribe to Fatbobman

Weekly Swift & SwiftUI highlights. Join developers.

Subscribe Now