From 906ad46768607f636d982ae42bfb03a286c1b5a0 Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Fri, 16 Jan 2026 01:58:48 +1100 Subject: [PATCH 1/2] Squash commits from main Combined commits: - fix(plausible): use consistent window reference in clientInit stub --- .claude/plans/543-plausible-broken.md | 61 +++++++++++++++++++++ src/runtime/registry/plausible-analytics.ts | 14 +++-- 2 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 .claude/plans/543-plausible-broken.md diff --git a/.claude/plans/543-plausible-broken.md b/.claude/plans/543-plausible-broken.md new file mode 100644 index 00000000..ea85c8ed --- /dev/null +++ b/.claude/plans/543-plausible-broken.md @@ -0,0 +1,61 @@ +## DONE + +# Fix: Plausible Analytics new script not working (#543) + +## Problem +Users report that the new Plausible script format (with `scriptId`) loads correctly in DOM but no events are sent. + +## Analysis + +### Root Cause +The `clientInit` stub uses bare `plausible` identifier inconsistently with `window.plausible`: + +```js +// Current code (plausible-analytics.ts:187) +window.plausible = window.plausible || function () { (plausible.q = plausible.q || []).push(arguments) }, plausible.init = plausible.init || function (i) { plausible.o = i || {} } +``` + +Issues: +1. **Inconsistent window reference**: First part uses `window.plausible`, second part uses bare `plausible` +2. **Module scope**: In ES modules (strict mode), bare identifier resolution differs from non-module scripts +3. **Compare to GA**: Google Analytics uses `w` (window) consistently throughout its clientInit + +### How Plausible's new script works +The `pa-{scriptId}.js` script: +1. Checks `plausible.o && S(plausible.o)` on load to pick up pre-init options +2. The stub's `plausible.init()` stores options in `plausible.o` +3. Script has domain hardcoded, doesn't need `data-domain` attribute + +### Verification +Plausible script expected stub format: +```js +window.plausible = window.plausible || {} +plausible.o && S(plausible.o) // If .o exists, initialize with those options +``` + +Our stub needs to set `plausible.o` before script loads, which it does via: +```js +plausible.init = function(i) { plausible.o = i || {} } +window.plausible.init(initOptions) +``` + +## Fix + +Update `clientInit` to use `window.plausible` consistently (like GA does): + +```ts +clientInit() { + const w = window as any + w.plausible = w.plausible || function () { (w.plausible.q = w.plausible.q || []).push(arguments) } + w.plausible.init = w.plausible.init || function (i: PlausibleInitOptions) { w.plausible.o = i || {} } + w.plausible.init(initOptions) +} +``` + +## Files to modify +- `src/runtime/registry/plausible-analytics.ts`: Fix clientInit stub pattern + +## Test plan +1. Run existing tests +2. Test playground with plausible-analytics-v2.vue +3. Verify script loads and init options are picked up diff --git a/src/runtime/registry/plausible-analytics.ts b/src/runtime/registry/plausible-analytics.ts index 9a955032..17ac9c95 100644 --- a/src/runtime/registry/plausible-analytics.ts +++ b/src/runtime/registry/plausible-analytics.ts @@ -181,12 +181,14 @@ export function useScriptPlausibleAnalytics(_op use() { return { plausible: window.plausible } }, - clientInit() { - // @ts-expect-error untyped - // eslint-disable-next-line @typescript-eslint/no-unused-expressions,@stylistic/max-statements-per-line,prefer-rest-params - window.plausible = window.plausible || function () { (plausible.q = plausible.q || []).push(arguments) }, plausible.init = plausible.init || function (i) { plausible.o = i || {} } - window.plausible.init(initOptions) - }, + clientInit: import.meta.server + ? undefined + : () => { + const w = window as any + w.plausible = w.plausible || function () { (w.plausible.q = w.plausible.q || []).push(arguments) } + w.plausible.init = w.plausible.init || function (i: PlausibleInitOptions) { w.plausible.o = i || {} } + w.plausible.init(initOptions) + }, }, } }, _options) From 46f2e17aa1d3ad037f7db194af74a1e7b38dff23 Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Sun, 18 Jan 2026 13:00:22 +1100 Subject: [PATCH 2/2] fix(gtm): invoke onBeforeGtmStart callback when ID is in config When GTM ID is configured in nuxt.config, the plugin pre-initializes the script before user components mount. This caused onBeforeGtmStart callbacks passed to useScriptGoogleTagManager() to never be invoked. Now checks if script was already initialized (gtag exists) and invokes the callback immediately for cached/pre-initialized scripts. Closes #522 Co-Authored-By: Claude Opus 4.5 --- src/runtime/registry/google-tag-manager.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/runtime/registry/google-tag-manager.ts b/src/runtime/registry/google-tag-manager.ts index d4993ed7..8d623a04 100644 --- a/src/runtime/registry/google-tag-manager.ts +++ b/src/runtime/registry/google-tag-manager.ts @@ -125,7 +125,7 @@ export function useScriptGoogleTagManager( onBeforeGtmStart?: (gtag: DataLayerPush) => void }, ): UseScriptContext, T>> { - return useRegistryScript( + const instance = useRegistryScript( options?.key || 'googleTagManager', (opts) => { const dataLayerName = opts?.l ?? opts?.dataLayer ?? 'dataLayer' @@ -183,4 +183,17 @@ export function useScriptGoogleTagManager( }, options, ) + + // Handle callback for cached/pre-initialized scripts (e.g., when ID is in nuxt.config) + // If script was already initialized by the plugin, clientInit already ran without this callback + if (import.meta.client && options?.onBeforeGtmStart) { + const dataLayerName = options?.l ?? options?.dataLayer ?? 'dataLayer' + const gtag = (window as any).gtag + // If gtag exists, script was already initialized - invoke callback immediately + if (gtag) { + options.onBeforeGtmStart(gtag) + } + } + + return instance }