@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 +14 -0
- package/README.md +1 -1
- package/dist/module.json +2 -2
- package/dist/runtime/plugins/google-tag-manager.client.js +4 -2
- package/dist/types.d.mts +2 -2
- package/package.json +12 -15
- package/dist/module.d.ts +0 -22
- package/dist/transport.d.mts +0 -30
- package/dist/transport.d.ts +0 -30
- package/dist/transport.mjs +0 -97
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
|
-
|
|
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
|
@@ -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: (
|
|
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 {
|
|
7
|
+
export { type GoogleConsentState, type GoogleConsentValue, type GoogleTagManagerNuxtModuleOptions, type GoogleTagManagerNuxtRuntimeConfig, type GoogleTagManagerScriptOptions } from '../dist/runtime/types.js'
|
|
8
8
|
|
|
9
|
-
export {
|
|
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.
|
|
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
|
-
"
|
|
42
|
-
"@stackonward/analytics-
|
|
43
|
-
"@stackonward/
|
|
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 };
|
package/dist/transport.d.mts
DELETED
|
@@ -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 };
|
package/dist/transport.d.ts
DELETED
|
@@ -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 };
|
package/dist/transport.mjs
DELETED
|
@@ -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 };
|