@stackonward/google-tag-manager-nuxt 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @stackonward/google-tag-manager-nuxt
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add provider-neutral structured analytics values, Google-owned recommended event contracts, a framework-independent Google Tag Manager adapter, and a provider-registered CLI that generates reviewed GTM container import artifacts. Keep recommended GA4 event names intact, disable duplicate automatic page views, and verify packed external consumers.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - Updated dependencies
13
+ - @stackonward/analytics-nuxt@0.1.1
14
+ - @stackonward/analytics-core@0.2.0
15
+ - @stackonward/google-tag-manager@0.1.0
16
+
3
17
  ## 0.1.0
4
18
 
5
19
  ### Minor Changes
package/README.md CHANGED
@@ -28,7 +28,7 @@ export default defineNuxtConfig({
28
28
 
29
29
  The integration starts disabled when the container ID is empty. Its default consent state denies every Google storage category. The product or CMP restores the user's decision and calls `useAnalyticsConsent().grant()` or `.deny()`.
30
30
 
31
- The remote GTM container must contain and publish the required GA4 tags, triggers and consent checks. This package does not mutate Google account configuration.
31
+ Generate the matching GTM import artifact with `stackonward analytics generate`, import it into a GTM web-container workspace, preview it, and publish the reviewed container version. This package does not mutate Google account configuration.
32
32
 
33
33
  ## License
34
34
 
package/dist/module.json CHANGED
@@ -4,9 +4,9 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.15.0"
6
6
  },
7
- "version": "0.1.0",
7
+ "version": "0.2.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.3",
10
- "unbuild": "3.6.1"
10
+ "unbuild": "unknown"
11
11
  }
12
12
  }
@@ -1,5 +1,7 @@
1
+ import {
2
+ createGoogleTagManagerTransport
3
+ } from "@stackonward/google-tag-manager";
1
4
  import { defineNuxtPlugin, useNuxtApp, useRuntimeConfig } from "nuxt/app";
2
- import { createGoogleTagManagerTransport } from "../../google-tag-manager-transport";
3
5
  import { createGoogleTagManagerLifecycleParticipant } from "../google-tag-manager-lifecycle.js";
4
6
  export default defineNuxtPlugin({
5
7
  name: "stackonward:google-tag-manager",
@@ -27,7 +29,7 @@ export default defineNuxtPlugin({
27
29
  );
28
30
  analytics.registerTransport(
29
31
  createGoogleTagManagerTransport({
30
- push: (event) => script.proxy.dataLayer.push(event)
32
+ push: (message) => script.proxy.dataLayer.push(message)
31
33
  })
32
34
  );
33
35
  }
package/dist/types.d.mts CHANGED
@@ -4,6 +4,6 @@ import type { default as Module } from './module.mjs'
4
4
 
5
5
  export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
6
6
 
7
- export { default, type normalizeGoogleTagManagerNuxtOptions } from './module.mjs'
7
+ export { type GoogleConsentState, type GoogleConsentValue, type GoogleTagManagerNuxtModuleOptions, type GoogleTagManagerNuxtRuntimeConfig, type GoogleTagManagerScriptOptions } from '../dist/runtime/types.js'
8
8
 
9
- export { type GoogleConsentState, type GoogleConsentValue, type GoogleTagManagerNuxtModuleOptions, type GoogleTagManagerNuxtRuntimeConfig, type GoogleTagManagerScriptOptions } from './module.mjs'
9
+ export { default, type normalizeGoogleTagManagerNuxtOptions } from './module.mjs'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackonward/google-tag-manager-nuxt",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Consent-aware Google Tag Manager transport and analytics composition module for Nuxt",
5
5
  "type": "module",
6
6
  "main": "./dist/module.mjs",
@@ -9,10 +9,6 @@
9
9
  ".": {
10
10
  "types": "./dist/module.d.mts",
11
11
  "import": "./dist/module.mjs"
12
- },
13
- "./transport": {
14
- "types": "./dist/transport.d.mts",
15
- "import": "./dist/transport.mjs"
16
12
  }
17
13
  },
18
14
  "files": [
@@ -22,6 +18,12 @@
22
18
  "CHANGELOG.md"
23
19
  ],
24
20
  "sideEffects": false,
21
+ "scripts": {
22
+ "build": "nuxt-module-build build",
23
+ "prepack": "pnpm build",
24
+ "typecheck": "tsc --noEmit",
25
+ "test": "vitest run"
26
+ },
25
27
  "publishConfig": {
26
28
  "access": "public"
27
29
  },
@@ -38,9 +40,10 @@
38
40
  ],
39
41
  "license": "MIT",
40
42
  "dependencies": {
41
- "zod": "^3.24.0",
42
- "@stackonward/analytics-core": "^0.1.0",
43
- "@stackonward/analytics-nuxt": "^0.1.0"
43
+ "@stackonward/analytics-core": "workspace:^",
44
+ "@stackonward/analytics-nuxt": "workspace:^",
45
+ "@stackonward/google-tag-manager": "workspace:^",
46
+ "zod": "^3.24.0"
44
47
  },
45
48
  "peerDependencies": {
46
49
  "@nuxt/scripts": ">=1.3.0 <2",
@@ -55,16 +58,10 @@
55
58
  "happy-dom": "^17.6.3",
56
59
  "nuxt": "^3.20.1",
57
60
  "typescript": "^5.9.3",
58
- "unbuild": "^3.5.0",
59
61
  "vitest": "^3.2.4",
60
62
  "vue": "^3.5.0"
61
63
  },
62
64
  "engines": {
63
65
  "node": ">=20"
64
- },
65
- "scripts": {
66
- "build": "nuxt-module-build build && unbuild",
67
- "typecheck": "tsc --noEmit",
68
- "test": "vitest run"
69
66
  }
70
- }
67
+ }
package/dist/module.d.ts DELETED
@@ -1,22 +0,0 @@
1
- import { NuxtModule } from '@nuxt/schema';
2
- import { GoogleTagManagerNuxtRuntimeConfig, GoogleTagManagerNuxtModuleOptions } from '../dist/runtime/types.js';
3
- export { GoogleConsentState, GoogleConsentValue, GoogleTagManagerNuxtModuleOptions, GoogleTagManagerNuxtRuntimeConfig, GoogleTagManagerScriptOptions } from '../dist/runtime/types.js';
4
- import { AnalyticsNuxtRuntimeConfig } from '@stackonward/analytics-nuxt';
5
-
6
- interface NormalizedGoogleTagManagerOptions {
7
- readonly runtime: GoogleTagManagerNuxtRuntimeConfig;
8
- readonly analytics: AnalyticsNuxtRuntimeConfig;
9
- }
10
- declare function normalizeGoogleTagManagerNuxtOptions(input?: unknown): NormalizedGoogleTagManagerOptions;
11
-
12
- declare module "@nuxt/schema" {
13
- interface NuxtConfig {
14
- googleTagManager?: GoogleTagManagerNuxtModuleOptions;
15
- }
16
- interface NuxtOptions {
17
- googleTagManager?: GoogleTagManagerNuxtModuleOptions;
18
- }
19
- }
20
- declare const module$1: NuxtModule<GoogleTagManagerNuxtModuleOptions>;
21
-
22
- export { module$1 as default, normalizeGoogleTagManagerNuxtOptions };
@@ -1,30 +0,0 @@
1
- import * as _stackonward_analytics_core from '@stackonward/analytics-core';
2
- import { AnalyticsPrimitive, AnalyticsEnvelope, AnalyticsValidationIssue, AnalyticsTransport } from '@stackonward/analytics-core';
3
-
4
- type GoogleTagManagerDataLayerEvent = Readonly<Record<string, AnalyticsPrimitive> & {
5
- event: string;
6
- }>;
7
- type GoogleEventProjectionResult = {
8
- readonly success: true;
9
- readonly data: GoogleTagManagerDataLayerEvent;
10
- } | {
11
- readonly success: false;
12
- readonly issues: readonly AnalyticsValidationIssue[];
13
- };
14
- declare function projectGoogleTagManagerEvent(envelope: AnalyticsEnvelope): GoogleEventProjectionResult;
15
-
16
- declare class GoogleTagManagerProjectionError extends Error {
17
- readonly issues: readonly _stackonward_analytics_core.AnalyticsValidationIssue[];
18
- constructor(issues: ReturnType<typeof projectGoogleTagManagerEvent> & {
19
- success: false;
20
- });
21
- }
22
- interface GoogleTagManagerTransportOptions {
23
- readonly beforeSend?: () => void | Promise<void>;
24
- readonly push: (event: GoogleTagManagerDataLayerEvent) => void;
25
- readonly dispose?: () => void | Promise<void>;
26
- }
27
- declare function createGoogleTagManagerTransport(options: GoogleTagManagerTransportOptions): AnalyticsTransport;
28
-
29
- export { GoogleTagManagerProjectionError, createGoogleTagManagerTransport, projectGoogleTagManagerEvent };
30
- export type { GoogleEventProjectionResult, GoogleTagManagerDataLayerEvent, GoogleTagManagerTransportOptions };
@@ -1,30 +0,0 @@
1
- import * as _stackonward_analytics_core from '@stackonward/analytics-core';
2
- import { AnalyticsPrimitive, AnalyticsEnvelope, AnalyticsValidationIssue, AnalyticsTransport } from '@stackonward/analytics-core';
3
-
4
- type GoogleTagManagerDataLayerEvent = Readonly<Record<string, AnalyticsPrimitive> & {
5
- event: string;
6
- }>;
7
- type GoogleEventProjectionResult = {
8
- readonly success: true;
9
- readonly data: GoogleTagManagerDataLayerEvent;
10
- } | {
11
- readonly success: false;
12
- readonly issues: readonly AnalyticsValidationIssue[];
13
- };
14
- declare function projectGoogleTagManagerEvent(envelope: AnalyticsEnvelope): GoogleEventProjectionResult;
15
-
16
- declare class GoogleTagManagerProjectionError extends Error {
17
- readonly issues: readonly _stackonward_analytics_core.AnalyticsValidationIssue[];
18
- constructor(issues: ReturnType<typeof projectGoogleTagManagerEvent> & {
19
- success: false;
20
- });
21
- }
22
- interface GoogleTagManagerTransportOptions {
23
- readonly beforeSend?: () => void | Promise<void>;
24
- readonly push: (event: GoogleTagManagerDataLayerEvent) => void;
25
- readonly dispose?: () => void | Promise<void>;
26
- }
27
- declare function createGoogleTagManagerTransport(options: GoogleTagManagerTransportOptions): AnalyticsTransport;
28
-
29
- export { GoogleTagManagerProjectionError, createGoogleTagManagerTransport, projectGoogleTagManagerEvent };
30
- export type { GoogleEventProjectionResult, GoogleTagManagerDataLayerEvent, GoogleTagManagerTransportOptions };
@@ -1,97 +0,0 @@
1
- const GOOGLE_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9_]{0,39}$/;
2
- const RESERVED_PREFIXES = ["firebase_", "google_", "ga_"];
3
- const GOOGLE_PARAMETER_LIMIT = 25;
4
- function projectGoogleTagManagerEvent(envelope) {
5
- const issues = [];
6
- validateGoogleName("name", envelope.name, issues);
7
- const contextKeys = new Set(Object.keys(envelope.context));
8
- for (const name of Object.keys(envelope.properties)) {
9
- if (contextKeys.has(name)) {
10
- issues.push({
11
- path: `properties.${name}`,
12
- code: "context_property_collision",
13
- message: "Event properties cannot overwrite analytics context"
14
- });
15
- }
16
- }
17
- const merged = { ...envelope.context, ...envelope.properties, event_source: envelope.source };
18
- const entries = Object.entries(merged);
19
- if (entries.length > GOOGLE_PARAMETER_LIMIT) {
20
- issues.push({
21
- path: "properties",
22
- code: "too_many_parameters",
23
- message: `Google events cannot exceed ${GOOGLE_PARAMETER_LIMIT} parameters`
24
- });
25
- }
26
- for (const [name, value] of entries) {
27
- validateGoogleName(`properties.${name}`, name, issues);
28
- if (Array.isArray(value)) {
29
- issues.push({
30
- path: `properties.${name}`,
31
- code: "unsupported_array",
32
- message: "Google Tag Manager event parameters must be primitive values"
33
- });
34
- }
35
- }
36
- if (issues.length > 0) {
37
- return { success: false, issues: Object.freeze(issues) };
38
- }
39
- return {
40
- success: true,
41
- data: Object.freeze({
42
- event: envelope.name,
43
- ...Object.fromEntries(entries)
44
- })
45
- };
46
- }
47
- function validateGoogleName(path, value, issues) {
48
- if (!GOOGLE_NAME_PATTERN.test(value)) {
49
- issues.push({
50
- path,
51
- code: "invalid_google_name",
52
- message: "Google names must start with a letter and contain at most 40 alphanumeric or underscore characters"
53
- });
54
- }
55
- if (RESERVED_PREFIXES.some((prefix) => value.toLowerCase().startsWith(prefix))) {
56
- issues.push({
57
- path,
58
- code: "reserved_google_prefix",
59
- message: "Google event and parameter names cannot use reserved prefixes"
60
- });
61
- }
62
- }
63
-
64
- class GoogleTagManagerProjectionError extends Error {
65
- issues;
66
- constructor(issues) {
67
- super("Analytics event is not compatible with Google Tag Manager");
68
- this.name = "GoogleTagManagerProjectionError";
69
- this.issues = issues.issues;
70
- }
71
- }
72
- function createGoogleTagManagerTransport(options) {
73
- let disposed = false;
74
- return {
75
- id: "google-tag-manager",
76
- async send(envelope) {
77
- if (disposed) {
78
- throw new Error("Google Tag Manager transport is disposed");
79
- }
80
- const projection = projectGoogleTagManagerEvent(envelope);
81
- if (!projection.success) {
82
- throw new GoogleTagManagerProjectionError(projection);
83
- }
84
- await options.beforeSend?.();
85
- options.push(projection.data);
86
- },
87
- async dispose() {
88
- if (disposed) {
89
- return;
90
- }
91
- disposed = true;
92
- await options.dispose?.();
93
- }
94
- };
95
- }
96
-
97
- export { GoogleTagManagerProjectionError, createGoogleTagManagerTransport, projectGoogleTagManagerEvent };