Skip to content

Conversation

endorfin
Copy link

@endorfin endorfin commented Sep 9, 2025

πŸ”— Linked issue

Followup on #392

❓ Type of change

  • πŸ“– Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

  • Fix gtag function to use arguments object instead of rest parameters for GTM compatibility
  • Add documentation example showing consent mode configuration

- Fix dataLayer initialization by moving it inside gtag function
- Add onBeforeGtmStart callback option for custom initialization
- Ensure dataLayer exists before each gtag call to prevent errors
- Add documentation example showing consent mode configuration

Fixes potential race condition where dataLayer might not be initialized
when onBeforeGtmStart callback is executed.
Copy link

vercel bot commented Sep 9, 2025

@endorfin is attempting to deploy a commit to the Nuxt Team on Vercel.

A member of the Team first needs to authorize it.

@endorfin endorfin mentioned this pull request Sep 9, 2025
6 tasks
Copy link

pkg-pr-new bot commented Sep 9, 2025

Open in StackBlitz

npm i https://pkg.pr.new/nuxt/scripts/@nuxt/scripts@494

commit: 1e2e7d0

@harlan-zw
Copy link
Collaborator

Thanks for the PR! Can you please check the failing ci. Also I'll get @huang-julien to review this (if he's available).

Copy link
Member

@huang-julien huang-julien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Can you provide a minimal reproduction ? I've been using the GTM debugger and the piece of code provided in the previous PR seems to work correctly

- Fix gtag function in onBeforeGtmStart hook to use native arguments object
- GTM DataLayer expects Arguments object, not Array for proper event processing
- Enables consent settings to be correctly processed before GTM initialization
- Add ESLint disable comment for prefer-rest-params rule
@endorfin
Copy link
Author

GTM onBeforeGtmStart Fix - Technical Analysis

Initial Hypothesis vs. Reality

My initial assumption was that the issue was related to the DataLayer not being properly initialized when the onBeforeGtmStart hook was called. However, after debugging with console logging, this proved to be incorrect.

The Real Root Cause

The problem was related to JavaScript's type system and Google Tag Manager's internal event processing:

Working External Implementation:

function gtag() { 
  dataLayer.push(arguments); 
}

Console Output: Arguments(3) ["consent", "default", {ad_storage: "denied", ...}]

Broken Internal Implementation:

function gtag(...args) { 
  dataLayer.push(args); 
}

Console Output: Array(3) ["consent", "default", {ad_storage: "denied", ...}]

Why This Difference Matters

Google Tag Manager's DataLayer specifically expects each gtag call to be pushed as an Arguments object, not a regular JavaScript Array. While both contain identical data, they have different internal types:

  1. Arguments Object: Special array-like object with properties GTM recognizes
  2. Array Object: Regular JavaScript array that GTM's parser handles differently

When using rest parameters (...args), JavaScript converts parameters into a standard Array. When using native arguments, JavaScript preserves the special Arguments type that GTM expects.

Key Takeaway

This was not a timing, initialization, or DataLayer availability issue. It was a pure type compatibility problem between JavaScript's modern rest parameters and Google Tag Manager's legacy API expectations.

The bug was difficult to diagnose because the data appeared identical in console logs, but the underlying object types were different enough to break GTM's internal consent processing.

Solution

The fix ensures that GTM receives exactly the data type it expects by using the native arguments object instead of rest parameters, allowing consent settings to be properly processed during the initialization phase.

The example code was missing the gtag parameter in the onBeforeGtmStart
callback function, which would cause a ReferenceError when trying to
use gtag() for
@endorfin endorfin changed the title fix(gtm): move dataLayer initialization into gtag function fix(gtm): fix onBeforeGtmStart gtag function using arguments object Sep 10, 2025
@endorfin endorfin changed the title fix(gtm): fix onBeforeGtmStart gtag function using arguments object fix(gtm): onBeforeGtmStart gtag function using arguments object Sep 10, 2025
Copy link
Member

@huang-julien huang-julien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks !
I'm not sure why but there was a reason I didn't move GTM to arguments for gtag. I think it didn't work at that time (but did for GA which required arguments instead of args.
Looks like an unmentionned breaking change on GTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants