fix(ga4): inject gtag.js when script tag is missing#6
Conversation
The stub gtag function is always assigned before the load check, so the previous typeof gtag === 'function' guard never skipped loading. Inject gtag/js when no matching script exists, matching the standard GA snippet. Made-with: Cursor
|
👍 @Innei |
commit: |
There was a problem hiding this comment.
Pull request overview
Fixes GA4 initialization so gtag.js is injected when the script tag is missing (previous typeof gtag guard was ineffective because a stub gtag is always assigned).
Changes:
- Remove the ineffective
typeof (window as any).gtag === 'function'load guard. - Detect existing GA script tags via
document.querySelector(...)and injectgtag/jsonly when missing. - Add clarifying comments explaining why the new approach matches the standard GA snippet behavior.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const existingScript = document.querySelector( | ||
| `script[src*="gtag/js"], script[id*="ga"], script[id*="gtag"]`, | ||
| ); | ||
|
|
||
| if (!existingScript) { | ||
| const script = document.createElement('script'); | ||
| script.async = true; | ||
| script.src = `https://www.googletagmanager.com/gtag/js?id=${this.config.measurementId}`; | ||
| document.head.append(script); |
There was a problem hiding this comment.
initialize() guards typeof window === 'undefined', but this new path unconditionally uses document.querySelector/document.head.append. In environments where window exists but document is missing (or document.head is null), this will throw and prevent initialization. Add an explicit typeof document === 'undefined' (and/or !document.head) guard with a logged error + early return.
| // decide whether to load gtag.js — that branch was never taken. Inject the script when the | ||
| // tag is missing from the document (standard GA snippet queues until the script loads). | ||
| const existingScript = document.querySelector( | ||
| `script[src*="gtag/js"], script[id*="ga"], script[id*="gtag"]`, |
There was a problem hiding this comment.
The selector script[id*="ga"] is extremely broad (e.g., it matches an unrelated <script id="tag">), which can produce false positives and skip injecting gtag/js even when GA4 isn’t present. Consider narrowing detection to GA-specific markers (e.g., script[src*="googletagmanager.com/gtag/js"] and/or stricter ids like id^="gtag"/id^="ga4").
| `script[src*="gtag/js"], script[id*="ga"], script[id*="gtag"]`, | |
| `script[src*="googletagmanager.com/gtag/js"], script[id^="gtag"], script[id^="ga4"]`, |
|
❤️ Great PR @Innei ❤️ |
|
🎉 This PR is included in version 1.6.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
The stub gtag function is always assigned before the load check, so the
previous typeof gtag === 'function' guard never skipped loading. Inject
gtag/js when no matching script exists, matching the standard GA snippet.
Made-with: Cursor