@getuserfeedback/adapters 0.3.0 → 0.4.1
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/README.md +135 -0
- package/dist/gtm/core.d.ts.map +1 -1
- package/dist/gtm/core.js +11 -8
- package/dist/gtm/index.d.ts +1 -1
- package/dist/gtm/index.d.ts.map +1 -1
- package/dist/gtm/index.js +1 -1
- package/dist/gtm/template-generation.d.ts +57 -7
- package/dist/gtm/template-generation.d.ts.map +1 -1
- package/dist/gtm/template-generation.js +281 -128
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# `@getuserfeedback/adapters`
|
|
2
|
+
|
|
3
|
+
`@getuserfeedback/adapters` publishes external-system translation layers built on top of the public widget protocol.
|
|
4
|
+
|
|
5
|
+
## GTM
|
|
6
|
+
|
|
7
|
+
The `@getuserfeedback/adapters/gtm` entrypoint is the authoritative source for Google Tag Manager template generation. It owns:
|
|
8
|
+
|
|
9
|
+
- GTM consent mapping logic
|
|
10
|
+
- GTM theme normalization logic
|
|
11
|
+
- GTM template parameter generation
|
|
12
|
+
- GTM runtime source generation
|
|
13
|
+
- GTM permission generation
|
|
14
|
+
- GTM template defaults, help text, and option labels
|
|
15
|
+
- the canonical loader script base URL pattern
|
|
16
|
+
|
|
17
|
+
### Public exports
|
|
18
|
+
|
|
19
|
+
Core mappings:
|
|
20
|
+
|
|
21
|
+
- `GTM_CONSENT_TYPES`
|
|
22
|
+
- `ESSENTIAL_GTM_SCOPES`
|
|
23
|
+
- `DEFAULT_GTM_SCOPE_MAPPINGS`
|
|
24
|
+
- `GTM_TEMPLATE_SCOPE_OPTIONS`
|
|
25
|
+
- `GTM_TEMPLATE_MAPPING_OPTIONS`
|
|
26
|
+
- `isGtmConsentType(value)`
|
|
27
|
+
- `isHostConfigurableGtmScope(scope)`
|
|
28
|
+
- `normalizeGtmThemeInput(input)`
|
|
29
|
+
- `resolveDefaultConsentFromGtm(input)`
|
|
30
|
+
- `buildInitOptionsFromGtmTemplate(input)`
|
|
31
|
+
|
|
32
|
+
Types:
|
|
33
|
+
|
|
34
|
+
- `GtmConsentType`
|
|
35
|
+
- `GtmConsentValue`
|
|
36
|
+
- `GtmConsentState`
|
|
37
|
+
- `GtmScopeMapping`
|
|
38
|
+
- `GtmAnalyticsMeasurementMode`
|
|
39
|
+
- `GtmTemplateInput`
|
|
40
|
+
- `GtmTemplateScopeOption`
|
|
41
|
+
- `GtmTemplateMappingOption`
|
|
42
|
+
|
|
43
|
+
Template generation:
|
|
44
|
+
|
|
45
|
+
- `DEFAULT_GTM_LOADER_SCRIPT_BASE_URL`
|
|
46
|
+
- `buildGtmTemplateParameters(options?)`
|
|
47
|
+
- `buildGtmRuntimeSource(options?)`
|
|
48
|
+
- `buildGtmPermissions(options?)`
|
|
49
|
+
- `buildGtmTemplateInfo(options?)`
|
|
50
|
+
- `buildGtmTemplateParts(options?)`
|
|
51
|
+
- `buildGtmTemplateArtifact(options?)`
|
|
52
|
+
|
|
53
|
+
### Essential scope policy
|
|
54
|
+
|
|
55
|
+
`functionality.storage` and `security.storage` are essential baseline scopes.
|
|
56
|
+
|
|
57
|
+
- They remain accepted by the protocol for backward compatibility.
|
|
58
|
+
- They are not host-configurable in GTM-generated consent UI.
|
|
59
|
+
- They are not emitted in GTM-generated host-overridable default consent output.
|
|
60
|
+
- Generated help text states that they are fixed by the loader.
|
|
61
|
+
|
|
62
|
+
### Analytics measurement policy
|
|
63
|
+
|
|
64
|
+
Automatic GTM consent mode exposes an explicit analytics measurement policy:
|
|
65
|
+
|
|
66
|
+
- `inherit-analytics-storage`
|
|
67
|
+
- `granted`
|
|
68
|
+
- `denied`
|
|
69
|
+
|
|
70
|
+
Manual GTM consent mode does not apply hidden analytics measurement behavior. It only uses the generated host-configurable scope mappings.
|
|
71
|
+
|
|
72
|
+
### Theme behavior
|
|
73
|
+
|
|
74
|
+
Generated GTM theme support accepts:
|
|
75
|
+
|
|
76
|
+
- fixed `light`
|
|
77
|
+
- fixed `dark`
|
|
78
|
+
- fixed `system`
|
|
79
|
+
- host-sync via protocol auto-detect attributes
|
|
80
|
+
- GTM variable-driven values
|
|
81
|
+
- comma-separated auto-detect attribute lists
|
|
82
|
+
|
|
83
|
+
The adapter normalizes all theme inputs into protocol-valid `colorScheme`.
|
|
84
|
+
|
|
85
|
+
### Generate a GTM template artifact
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { buildGtmTemplateArtifact } from "@getuserfeedback/adapters/gtm";
|
|
89
|
+
|
|
90
|
+
const artifact = buildGtmTemplateArtifact({
|
|
91
|
+
loaderScriptBaseUrl: "https://cdn.getuserfeedback.com/widget/loader/v1",
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
artifact.info;
|
|
95
|
+
artifact.parameters;
|
|
96
|
+
artifact.runtimeSource;
|
|
97
|
+
artifact.permissions;
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The returned object is suitable for rendering into GTM `___INFO___`, `___TEMPLATE_PARAMETERS___`, `___SANDBOXED_JS_FOR_WEB_TEMPLATE___`, and `___WEB_PERMISSIONS___` sections.
|
|
101
|
+
|
|
102
|
+
### What the GTM repo should still own
|
|
103
|
+
|
|
104
|
+
After importing the published package, the GTM repo should only own:
|
|
105
|
+
|
|
106
|
+
- GTM Gallery wrapper file assembly
|
|
107
|
+
- brand thumbnail and base64 image assets
|
|
108
|
+
- `metadata.yaml`
|
|
109
|
+
- publishing and release workflow
|
|
110
|
+
|
|
111
|
+
It should not rebuild parameters, runtime source, permissions, or GTM-specific init payload translation.
|
|
112
|
+
|
|
113
|
+
### Customizing the loader base URL
|
|
114
|
+
|
|
115
|
+
Pass `loaderScriptBaseUrl` to:
|
|
116
|
+
|
|
117
|
+
- `buildGtmRuntimeSource`
|
|
118
|
+
- `buildGtmPermissions`
|
|
119
|
+
- `buildGtmTemplateParts`
|
|
120
|
+
- `buildGtmTemplateArtifact`
|
|
121
|
+
|
|
122
|
+
The same base URL is used to derive the runtime loader URL and the `inject_script` permission pattern.
|
|
123
|
+
|
|
124
|
+
### Versioning expectations
|
|
125
|
+
|
|
126
|
+
Any change that affects generated GTM output is a public package change and should be versioned accordingly. This includes:
|
|
127
|
+
|
|
128
|
+
- parameter shape or defaults
|
|
129
|
+
- runtime behavior
|
|
130
|
+
- permission generation
|
|
131
|
+
- default mappings
|
|
132
|
+
- essential-scope exposure
|
|
133
|
+
- analytics measurement behavior
|
|
134
|
+
|
|
135
|
+
Release notes should call out template-affecting changes explicitly.
|
package/dist/gtm/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/gtm/core.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/gtm/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,WAAW,EAGhB,KAAK,KAAK,EACV,MAAM,2BAA2B,CAAC;AAEnC,eAAO,MAAM,iBAAiB,EAAE,SAAS;IACxC,uBAAuB;IACvB,kBAAkB;IAClB,mBAAmB;IACnB,yBAAyB;IACzB,YAAY;IACZ,cAAc;IACd,oBAAoB;CASpB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEnD,MAAM,MAAM,2BAA2B,GACpC,2BAA2B,GAC3B,SAAS,GACT,QAAQ,CAAC;AAEZ,MAAM,MAAM,eAAe,GAAG;IAC7B,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,cAAc,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC,CAAC;AAE/E,MAAM,MAAM,gBAAgB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,aAAa,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC/C,wBAAwB,CAAC,EAAE,2BAA2B,CAAC;IACvD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;IACzC,YAAY,CAAC,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;IAC3C,gBAAgB,CAAC,EAAE,WAAW,CAAC,kBAAkB,CAAC,CAAC;IACnD,UAAU,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC;CACvC,CAAC;AAEF,KAAK,oBAAoB,GAAG,WAAW,CACtC,OAAO,CAAC,WAAW,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC,CAC9C,CAAC,MAAM,CAAC,CAAC;AAEV,MAAM,MAAM,sBAAsB,GAAG;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACtC,WAAW,EAAE,cAAc,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,SAAS;IAC3C,uBAAuB;IACvB,kBAAkB;CAC8B,CAAC;AAIlD,eAAO,MAAM,0BAA0B,GACtC,OAAO,KAAK,KACV,KAAK,IAAI,oBAAmD,CAAC;AAEhE,eAAO,MAAM,0BAA0B,EAAE,aAAa,CAAC,eAAe,CA6BrE,CAAC;AA4BF,eAAO,MAAM,0BAA0B,EAAE,aAAa,CAAC,sBAAsB,CAKzE,CAAC;AAEL,eAAO,MAAM,4BAA4B,EAAE,aAAa,CAAC,wBAAwB,CAI7E,CAAC;AAEL,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAKxE;AAED,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,OAAO,GACZ,WAAW,CAAC,aAAa,CAAC,GAAG,SAAS,CA2CxC;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IACnD,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,aAAa,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC/C,wBAAwB,CAAC,EAAE,2BAA2B,CAAC;CACvD,GAAG,WAAW,CAAC,gBAAgB,CAAC,GAAG,SAAS,CA6B5C;AAED,wBAAgB,+BAA+B,CAC9C,KAAK,EAAE,gBAAgB,GACrB,WAAW,CA8Bb"}
|
package/dist/gtm/core.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS, listScopes, } from "@getuserfeedback/protocol";
|
|
1
|
+
import { colorSchemeConfigInputSchema, consentConfigInputSchema, DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS, listScopes, parseInitOptions, } from "@getuserfeedback/protocol";
|
|
2
2
|
export const GTM_CONSENT_TYPES = [
|
|
3
3
|
"functionality_storage",
|
|
4
4
|
"security_storage",
|
|
@@ -102,17 +102,17 @@ export function normalizeGtmThemeInput(input) {
|
|
|
102
102
|
return normalized;
|
|
103
103
|
}
|
|
104
104
|
if (normalized === "auto") {
|
|
105
|
-
return {
|
|
105
|
+
return colorSchemeConfigInputSchema.parse({
|
|
106
106
|
autoDetectColorScheme: [...DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS],
|
|
107
|
-
};
|
|
107
|
+
});
|
|
108
108
|
}
|
|
109
109
|
const attrs = normalizeAttrList(input);
|
|
110
110
|
if (attrs.length === 0) {
|
|
111
111
|
return undefined;
|
|
112
112
|
}
|
|
113
|
-
return {
|
|
113
|
+
return colorSchemeConfigInputSchema.parse({
|
|
114
114
|
autoDetectColorScheme: attrs,
|
|
115
|
-
};
|
|
115
|
+
});
|
|
116
116
|
}
|
|
117
117
|
export function resolveDefaultConsentFromGtm(input) {
|
|
118
118
|
const consentState = input.consentState;
|
|
@@ -129,7 +129,10 @@ export function resolveDefaultConsentFromGtm(input) {
|
|
|
129
129
|
consentState.analytics_storage === "granted") {
|
|
130
130
|
grantedScopes.push("analytics.measurement");
|
|
131
131
|
}
|
|
132
|
-
|
|
132
|
+
const normalizedGrantedScopes = uniqueScopes(grantedScopes);
|
|
133
|
+
return normalizedGrantedScopes.length > 0
|
|
134
|
+
? consentConfigInputSchema.parse(normalizedGrantedScopes)
|
|
135
|
+
: undefined;
|
|
133
136
|
}
|
|
134
137
|
export function buildInitOptionsFromGtmTemplate(input) {
|
|
135
138
|
const colorScheme = normalizeGtmThemeInput(input.colorScheme);
|
|
@@ -138,7 +141,7 @@ export function buildInitOptionsFromGtmTemplate(input) {
|
|
|
138
141
|
scopeMappings: input.scopeMappings,
|
|
139
142
|
analyticsMeasurementMode: input.analyticsMeasurementMode,
|
|
140
143
|
});
|
|
141
|
-
return {
|
|
144
|
+
return parseInitOptions({
|
|
142
145
|
apiKey: input.apiKey,
|
|
143
146
|
...(colorScheme !== undefined ? { colorScheme } : {}),
|
|
144
147
|
...(input.disableTelemetry !== undefined
|
|
@@ -159,5 +162,5 @@ export function buildInitOptionsFromGtmTemplate(input) {
|
|
|
159
162
|
...(input.runtimeEndpoints !== undefined
|
|
160
163
|
? { runtimeEndpoints: input.runtimeEndpoints }
|
|
161
164
|
: {}),
|
|
162
|
-
};
|
|
165
|
+
});
|
|
163
166
|
}
|
package/dist/gtm/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { buildInitOptionsFromGtmTemplate, DEFAULT_GTM_SCOPE_MAPPINGS, ESSENTIAL_GTM_SCOPES, GTM_CONSENT_TYPES, GTM_TEMPLATE_MAPPING_OPTIONS, GTM_TEMPLATE_SCOPE_OPTIONS, type GtmAnalyticsMeasurementMode, type GtmConsentState, type GtmConsentType, type GtmConsentValue, type GtmScopeMapping, type GtmTemplateInput, type GtmTemplateMappingOption, type GtmTemplateScopeOption, isGtmConsentType, isHostConfigurableGtmScope, normalizeGtmThemeInput, resolveDefaultConsentFromGtm, } from "./core.js";
|
|
2
|
-
export { buildGtmRuntimeSource, buildGtmTemplateParameters, buildGtmTemplateParts, DEFAULT_GTM_LOADER_SCRIPT_BASE_URL, type GtmTemplateParts, type TemplateCondition, type TemplateParameter, type TemplateSelectItem, type TemplateValueValidator, } from "./template-generation.js";
|
|
2
|
+
export { buildGtmPermissions, buildGtmRuntimeSource, buildGtmTemplateArtifact, buildGtmTemplateInfo, buildGtmTemplateParameters, buildGtmTemplateParts, DEFAULT_GTM_LOADER_SCRIPT_BASE_URL, type GtmTemplateArtifact, type GtmTemplateGenerationOptions, type GtmTemplateInfo, type GtmTemplateParts, type GtmTemplatePermission, type TemplateCondition, type TemplateParameter, type TemplateSelectItem, type TemplateValueValidator, } from "./template-generation.js";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/gtm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gtm/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,+BAA+B,EAC/B,0BAA0B,EAC1B,oBAAoB,EACpB,iBAAiB,EACjB,4BAA4B,EAC5B,0BAA0B,EAC1B,KAAK,2BAA2B,EAChC,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,gBAAgB,EAChB,0BAA0B,EAC1B,sBAAsB,EACtB,4BAA4B,GAC5B,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,kCAAkC,EAClC,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,GAC3B,MAAM,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gtm/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,+BAA+B,EAC/B,0BAA0B,EAC1B,oBAAoB,EACpB,iBAAiB,EACjB,4BAA4B,EAC5B,0BAA0B,EAC1B,KAAK,2BAA2B,EAChC,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,gBAAgB,EAChB,0BAA0B,EAC1B,sBAAsB,EACtB,4BAA4B,GAC5B,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACpB,0BAA0B,EAC1B,qBAAqB,EACrB,kCAAkC,EAClC,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,EACjC,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,GAC3B,MAAM,0BAA0B,CAAC"}
|
package/dist/gtm/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { buildInitOptionsFromGtmTemplate, DEFAULT_GTM_SCOPE_MAPPINGS, ESSENTIAL_GTM_SCOPES, GTM_CONSENT_TYPES, GTM_TEMPLATE_MAPPING_OPTIONS, GTM_TEMPLATE_SCOPE_OPTIONS, isGtmConsentType, isHostConfigurableGtmScope, normalizeGtmThemeInput, resolveDefaultConsentFromGtm, } from "./core.js";
|
|
2
|
-
export { buildGtmRuntimeSource, buildGtmTemplateParameters, buildGtmTemplateParts, DEFAULT_GTM_LOADER_SCRIPT_BASE_URL, } from "./template-generation.js";
|
|
2
|
+
export { buildGtmPermissions, buildGtmRuntimeSource, buildGtmTemplateArtifact, buildGtmTemplateInfo, buildGtmTemplateParameters, buildGtmTemplateParts, DEFAULT_GTM_LOADER_SCRIPT_BASE_URL, } from "./template-generation.js";
|
|
@@ -64,16 +64,66 @@ export type TemplateParameter = {
|
|
|
64
64
|
groupStyle: "ZIPPY_CLOSED";
|
|
65
65
|
subParams: TemplateParameter[];
|
|
66
66
|
};
|
|
67
|
+
type GtmPermissionStringValue = {
|
|
68
|
+
type: 1;
|
|
69
|
+
string: string;
|
|
70
|
+
};
|
|
71
|
+
type GtmPermissionBooleanValue = {
|
|
72
|
+
type: 8;
|
|
73
|
+
boolean: boolean;
|
|
74
|
+
};
|
|
75
|
+
type GtmPermissionMapValue = {
|
|
76
|
+
type: 3;
|
|
77
|
+
mapKey: GtmPermissionStringValue[];
|
|
78
|
+
mapValue: Array<GtmPermissionStringValue | GtmPermissionBooleanValue | GtmPermissionListValue | GtmPermissionMapValue>;
|
|
79
|
+
};
|
|
80
|
+
type GtmPermissionListValue = {
|
|
81
|
+
type: 2;
|
|
82
|
+
listItem: Array<GtmPermissionStringValue | GtmPermissionBooleanValue | GtmPermissionMapValue>;
|
|
83
|
+
};
|
|
84
|
+
type GtmPermissionParam = {
|
|
85
|
+
key: string;
|
|
86
|
+
value: GtmPermissionStringValue | GtmPermissionBooleanValue | GtmPermissionListValue | GtmPermissionMapValue;
|
|
87
|
+
};
|
|
88
|
+
export type GtmTemplatePermission = {
|
|
89
|
+
instance: {
|
|
90
|
+
key: {
|
|
91
|
+
publicId: string;
|
|
92
|
+
versionId: "1";
|
|
93
|
+
};
|
|
94
|
+
param: GtmPermissionParam[];
|
|
95
|
+
};
|
|
96
|
+
clientAnnotations?: {
|
|
97
|
+
isEditedByUser: true;
|
|
98
|
+
};
|
|
99
|
+
isRequired: true;
|
|
100
|
+
};
|
|
101
|
+
export type GtmTemplateInfo = {
|
|
102
|
+
type: "TAG";
|
|
103
|
+
version: 1;
|
|
104
|
+
displayName: string;
|
|
105
|
+
description: string;
|
|
106
|
+
categories: readonly ["SURVEY", "PERSONALIZATION", "UTILITY"];
|
|
107
|
+
containerContexts: readonly ["WEB"];
|
|
108
|
+
};
|
|
67
109
|
export type GtmTemplateParts = {
|
|
110
|
+
info: GtmTemplateInfo;
|
|
68
111
|
parameters: TemplateParameter[];
|
|
69
112
|
runtimeSource: string;
|
|
113
|
+
permissions: GtmTemplatePermission[];
|
|
70
114
|
};
|
|
71
|
-
export
|
|
72
|
-
export
|
|
73
|
-
export declare function buildGtmRuntimeSource(input?: {
|
|
115
|
+
export type GtmTemplateArtifact = GtmTemplateParts;
|
|
116
|
+
export type GtmTemplateGenerationOptions = {
|
|
74
117
|
loaderScriptBaseUrl?: string;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
118
|
+
displayName?: string;
|
|
119
|
+
description?: string;
|
|
120
|
+
};
|
|
121
|
+
export declare const DEFAULT_GTM_LOADER_SCRIPT_BASE_URL = "https://cdn.getuserfeedback.com/widget/loader/v1";
|
|
122
|
+
export declare function buildGtmTemplateParameters(_options?: GtmTemplateGenerationOptions): TemplateParameter[];
|
|
123
|
+
export declare function buildGtmRuntimeSource(input?: GtmTemplateGenerationOptions): string;
|
|
124
|
+
export declare function buildGtmPermissions(input?: GtmTemplateGenerationOptions): GtmTemplatePermission[];
|
|
125
|
+
export declare function buildGtmTemplateInfo(input?: GtmTemplateGenerationOptions): GtmTemplateInfo;
|
|
126
|
+
export declare function buildGtmTemplateParts(input?: GtmTemplateGenerationOptions): GtmTemplateParts;
|
|
127
|
+
export declare function buildGtmTemplateArtifact(input?: GtmTemplateGenerationOptions): GtmTemplateArtifact;
|
|
128
|
+
export {};
|
|
79
129
|
//# sourceMappingURL=template-generation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-generation.d.ts","sourceRoot":"","sources":["../../src/gtm/template-generation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"template-generation.d.ts","sourceRoot":"","sources":["../../src/gtm/template-generation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,36 +1,47 @@
|
|
|
1
1
|
import { DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS, } from "@getuserfeedback/protocol";
|
|
2
|
-
import { GTM_CONSENT_TYPES, GTM_TEMPLATE_MAPPING_OPTIONS, GTM_TEMPLATE_SCOPE_OPTIONS, isHostConfigurableGtmScope, } from "./core.js";
|
|
2
|
+
import { DEFAULT_GTM_SCOPE_MAPPINGS, ESSENTIAL_GTM_SCOPES, GTM_CONSENT_TYPES, GTM_TEMPLATE_MAPPING_OPTIONS, GTM_TEMPLATE_SCOPE_OPTIONS, isHostConfigurableGtmScope, } from "./core.js";
|
|
3
3
|
export const DEFAULT_GTM_LOADER_SCRIPT_BASE_URL = "https://cdn.getuserfeedback.com/widget/loader/v1";
|
|
4
|
+
const GTM_TEMPLATE_VERSION = 1;
|
|
5
|
+
const GTM_TEMPLATE_DEFAULT_DISPLAY_NAME = "getuserfeedback Widget";
|
|
6
|
+
const GTM_TEMPLATE_DEFAULT_DESCRIPTION = "Load the getuserfeedback widget with modern loader, theme, and GTM Consent Mode defaults derived from the public protocol contract.";
|
|
7
|
+
const GTM_TEMPLATE_CATEGORIES = [
|
|
8
|
+
"SURVEY",
|
|
9
|
+
"PERSONALIZATION",
|
|
10
|
+
"UTILITY",
|
|
11
|
+
];
|
|
12
|
+
const GTM_TEMPLATE_CONTAINER_CONTEXTS = ["WEB"];
|
|
13
|
+
const GTM_QUEUE_KEY = "__getuserfeedback_queue";
|
|
4
14
|
const NON_EMPTY_VALIDATOR = { type: "NON_EMPTY" };
|
|
5
|
-
const
|
|
6
|
-
.map((option) => `${option.label}: ${option.description}`)
|
|
7
|
-
.join("\n");
|
|
8
|
-
const buildDefaultTemplateScopeMappings = () => [
|
|
9
|
-
{
|
|
10
|
-
scope: "analytics.storage",
|
|
11
|
-
mapping: "analytics_storage",
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
scope: "analytics.measurement",
|
|
15
|
-
mapping: "analytics_storage",
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
scope: "personalization.storage",
|
|
19
|
-
mapping: "personalization_storage",
|
|
20
|
-
},
|
|
15
|
+
const MANUAL_CONSENT_MODE_CONDITION = [
|
|
21
16
|
{
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
paramName: "consentMode",
|
|
18
|
+
paramValue: "manual",
|
|
19
|
+
type: "EQUALS",
|
|
24
20
|
},
|
|
21
|
+
];
|
|
22
|
+
const AUTOMATIC_CONSENT_MODE_CONDITION = [
|
|
25
23
|
{
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
paramName: "consentMode",
|
|
25
|
+
paramValue: "automatic",
|
|
26
|
+
type: "EQUALS",
|
|
28
27
|
},
|
|
28
|
+
];
|
|
29
|
+
const buildHostConfigurableDefaultScopeMappings = () => [
|
|
30
|
+
...DEFAULT_GTM_SCOPE_MAPPINGS.filter((mapping) => isHostConfigurableGtmScope(mapping.scope)).map((mapping) => ({
|
|
31
|
+
scope: mapping.scope,
|
|
32
|
+
mapping: mapping.consentType,
|
|
33
|
+
})),
|
|
29
34
|
{
|
|
30
|
-
scope: "
|
|
31
|
-
mapping: "
|
|
35
|
+
scope: "analytics.measurement",
|
|
36
|
+
mapping: "analytics_storage",
|
|
32
37
|
},
|
|
33
38
|
];
|
|
39
|
+
const buildScopeParameterHelp = () => [
|
|
40
|
+
"Essential scopes are fixed by the loader and are not exposed for GTM override.",
|
|
41
|
+
`${ESSENTIAL_GTM_SCOPES[0]} and ${ESSENTIAL_GTM_SCOPES[1]} always remain baseline scopes outside the GTM template UI.`,
|
|
42
|
+
"",
|
|
43
|
+
...GTM_TEMPLATE_SCOPE_OPTIONS.filter((option) => isHostConfigurableGtmScope(option.scope)).map((option) => `${option.label}: ${option.description}`),
|
|
44
|
+
].join("\n");
|
|
34
45
|
const buildHostConfigurableScopeSelectItems = () => GTM_TEMPLATE_SCOPE_OPTIONS.filter((option) => isHostConfigurableGtmScope(option.scope)).map((option) => ({
|
|
35
46
|
value: option.scope,
|
|
36
47
|
displayValue: option.label,
|
|
@@ -40,7 +51,45 @@ const buildGtmConsentTypeSelectItems = () => GTM_TEMPLATE_MAPPING_OPTIONS.map((o
|
|
|
40
51
|
displayValue: `${option.label} Granted`,
|
|
41
52
|
}));
|
|
42
53
|
const trimTrailingSlash = (value) => value.endsWith("/") ? value.slice(0, -1) : value;
|
|
43
|
-
|
|
54
|
+
const stringValue = (value) => ({
|
|
55
|
+
type: 1,
|
|
56
|
+
string: value,
|
|
57
|
+
});
|
|
58
|
+
const booleanValue = (value) => ({
|
|
59
|
+
type: 8,
|
|
60
|
+
boolean: value,
|
|
61
|
+
});
|
|
62
|
+
const listValue = (items) => ({
|
|
63
|
+
type: 2,
|
|
64
|
+
listItem: items,
|
|
65
|
+
});
|
|
66
|
+
const mapValue = (entries) => ({
|
|
67
|
+
type: 3,
|
|
68
|
+
mapKey: entries.map(([key]) => stringValue(key)),
|
|
69
|
+
mapValue: entries.map(([, value]) => {
|
|
70
|
+
if (typeof value === "string") {
|
|
71
|
+
return stringValue(value);
|
|
72
|
+
}
|
|
73
|
+
if (typeof value === "boolean") {
|
|
74
|
+
return booleanValue(value);
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
}),
|
|
78
|
+
});
|
|
79
|
+
const buildPermission = (publicId, params) => ({
|
|
80
|
+
instance: {
|
|
81
|
+
key: {
|
|
82
|
+
publicId,
|
|
83
|
+
versionId: "1",
|
|
84
|
+
},
|
|
85
|
+
param: params,
|
|
86
|
+
},
|
|
87
|
+
clientAnnotations: {
|
|
88
|
+
isEditedByUser: true,
|
|
89
|
+
},
|
|
90
|
+
isRequired: true,
|
|
91
|
+
});
|
|
92
|
+
export function buildGtmTemplateParameters(_options) {
|
|
44
93
|
const scopeHelp = buildScopeParameterHelp();
|
|
45
94
|
const scopeSelectItems = buildHostConfigurableScopeSelectItems();
|
|
46
95
|
const mappingSelectItems = buildGtmConsentTypeSelectItems();
|
|
@@ -50,7 +99,7 @@ export function buildGtmTemplateParameters() {
|
|
|
50
99
|
name: "apiKey",
|
|
51
100
|
displayName: "API Key",
|
|
52
101
|
simpleValueType: true,
|
|
53
|
-
help: "Find your API key in getuserfeedback.com under Settings
|
|
102
|
+
help: "Find your API key in getuserfeedback.com under Settings -> Widget.",
|
|
54
103
|
valueValidators: [NON_EMPTY_VALIDATOR],
|
|
55
104
|
},
|
|
56
105
|
{
|
|
@@ -79,16 +128,16 @@ export function buildGtmTemplateParameters() {
|
|
|
79
128
|
},
|
|
80
129
|
{
|
|
81
130
|
value: "host",
|
|
82
|
-
displayValue: "Sync With Host",
|
|
131
|
+
displayValue: "Sync With Host Attributes",
|
|
83
132
|
},
|
|
84
133
|
{
|
|
85
134
|
value: "variable",
|
|
86
|
-
displayValue: "Variable",
|
|
135
|
+
displayValue: "Resolve From GTM Variable",
|
|
87
136
|
},
|
|
88
137
|
],
|
|
89
138
|
simpleValueType: true,
|
|
90
139
|
defaultValue: "host",
|
|
91
|
-
help: "
|
|
140
|
+
help: "Generate protocol-valid `init.opts.colorScheme` using fixed modes, host auto-detect attributes, or a GTM variable.",
|
|
92
141
|
},
|
|
93
142
|
{
|
|
94
143
|
type: "SELECT",
|
|
@@ -113,7 +162,7 @@ export function buildGtmTemplateParameters() {
|
|
|
113
162
|
displayName: "Host Theme Attributes",
|
|
114
163
|
simpleValueType: true,
|
|
115
164
|
defaultValue: DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS.join(","),
|
|
116
|
-
help: "Comma-separated attributes to inspect on `<html>` or `<body>`
|
|
165
|
+
help: "Comma-separated attributes to inspect on `<html>` or `<body>` when syncing the widget to host theme state.",
|
|
117
166
|
enablingConditions: [
|
|
118
167
|
{
|
|
119
168
|
paramName: "themeMode",
|
|
@@ -138,17 +187,41 @@ export function buildGtmTemplateParameters() {
|
|
|
138
187
|
{
|
|
139
188
|
value: "automatic",
|
|
140
189
|
displayValue: "Automatic (Use GTM Consent Mode)",
|
|
141
|
-
help: "
|
|
190
|
+
help: "Read GTM consent mode via `isConsentGranted`, translate granted consent types into widget `defaultConsent`, and apply the explicit analytics measurement policy.",
|
|
142
191
|
},
|
|
143
192
|
{
|
|
144
193
|
value: "manual",
|
|
145
194
|
displayValue: "Manual (Map Public Scopes)",
|
|
146
|
-
help: "Override
|
|
195
|
+
help: "Override host-configurable widget consent scopes with explicit GTM consent mappings. Essential scopes remain fixed by the loader and are never configurable here.",
|
|
147
196
|
},
|
|
148
197
|
],
|
|
149
198
|
simpleValueType: true,
|
|
150
199
|
defaultValue: "automatic",
|
|
151
200
|
},
|
|
201
|
+
{
|
|
202
|
+
type: "SELECT",
|
|
203
|
+
name: "analyticsMeasurementMode",
|
|
204
|
+
displayName: "Analytics Measurement Policy",
|
|
205
|
+
macrosInSelect: false,
|
|
206
|
+
selectItems: [
|
|
207
|
+
{
|
|
208
|
+
value: "inherit-analytics-storage",
|
|
209
|
+
displayValue: "Inherit analytics_storage",
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
value: "granted",
|
|
213
|
+
displayValue: "Always granted",
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
value: "denied",
|
|
217
|
+
displayValue: "Always denied",
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
simpleValueType: true,
|
|
221
|
+
defaultValue: "inherit-analytics-storage",
|
|
222
|
+
help: "Controls whether `analytics.measurement` follows GTM `analytics_storage` or is forced on/off in automatic mode.",
|
|
223
|
+
enablingConditions: [...AUTOMATIC_CONSENT_MODE_CONDITION],
|
|
224
|
+
},
|
|
152
225
|
{
|
|
153
226
|
type: "SIMPLE_TABLE",
|
|
154
227
|
name: "scopeMappings",
|
|
@@ -172,16 +245,10 @@ export function buildGtmTemplateParameters() {
|
|
|
172
245
|
},
|
|
173
246
|
],
|
|
174
247
|
newRowButtonText: "Add Scope",
|
|
175
|
-
help:
|
|
176
|
-
enablingConditions: [
|
|
177
|
-
{
|
|
178
|
-
paramName: "consentMode",
|
|
179
|
-
paramValue: "manual",
|
|
180
|
-
type: "EQUALS",
|
|
181
|
-
},
|
|
182
|
-
],
|
|
248
|
+
help: scopeHelp,
|
|
249
|
+
enablingConditions: [...MANUAL_CONSENT_MODE_CONDITION],
|
|
183
250
|
valueValidators: [NON_EMPTY_VALIDATOR],
|
|
184
|
-
defaultValue:
|
|
251
|
+
defaultValue: buildHostConfigurableDefaultScopeMappings().map((row) => ({
|
|
185
252
|
scope: row.scope,
|
|
186
253
|
mapping: row.mapping,
|
|
187
254
|
})),
|
|
@@ -192,19 +259,21 @@ export function buildGtmTemplateParameters() {
|
|
|
192
259
|
}
|
|
193
260
|
export function buildGtmRuntimeSource(input) {
|
|
194
261
|
const loaderScriptBaseUrl = trimTrailingSlash(input?.loaderScriptBaseUrl ?? DEFAULT_GTM_LOADER_SCRIPT_BASE_URL);
|
|
195
|
-
const defaultTemplateScopeMappings =
|
|
262
|
+
const defaultTemplateScopeMappings = buildHostConfigurableDefaultScopeMappings();
|
|
196
263
|
return `
|
|
197
264
|
const log = require("logToConsole");
|
|
198
265
|
const injectScript = require("injectScript");
|
|
199
266
|
const queryPermission = require("queryPermission");
|
|
200
267
|
const createQueue = require("createQueue");
|
|
201
268
|
const isConsentGranted = require("isConsentGranted");
|
|
269
|
+
const encodeUriComponent = require("encodeUriComponent");
|
|
202
270
|
|
|
203
271
|
const loaderScriptBaseUrl = ${JSON.stringify(loaderScriptBaseUrl)};
|
|
204
272
|
const gtmConsentTypes = ${JSON.stringify(GTM_CONSENT_TYPES)};
|
|
205
273
|
const defaultScopeMappings = ${JSON.stringify(defaultTemplateScopeMappings)};
|
|
206
|
-
const hostConfigurableScopes = ${JSON.stringify(
|
|
274
|
+
const hostConfigurableScopes = ${JSON.stringify(defaultTemplateScopeMappings.map((row) => row.scope))};
|
|
207
275
|
const defaultAutoDetectColorSchemeAttrs = ${JSON.stringify(DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS)};
|
|
276
|
+
const queueKey = ${JSON.stringify(GTM_QUEUE_KEY)};
|
|
208
277
|
|
|
209
278
|
const trimString = function(value) {
|
|
210
279
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -221,13 +290,13 @@ const normalizeAttrList = function(value) {
|
|
|
221
290
|
});
|
|
222
291
|
};
|
|
223
292
|
|
|
224
|
-
const normalizeThemeInput = function(
|
|
225
|
-
if (
|
|
293
|
+
const normalizeThemeInput = function(inputValue) {
|
|
294
|
+
if (inputValue === undefined || inputValue === null) {
|
|
226
295
|
return undefined;
|
|
227
296
|
}
|
|
228
297
|
|
|
229
|
-
if (typeof
|
|
230
|
-
const normalized =
|
|
298
|
+
if (typeof inputValue === "string") {
|
|
299
|
+
const normalized = inputValue.trim().toLowerCase();
|
|
231
300
|
if (!normalized) {
|
|
232
301
|
return undefined;
|
|
233
302
|
}
|
|
@@ -243,30 +312,13 @@ const normalizeThemeInput = function(input) {
|
|
|
243
312
|
autoDetectColorScheme: defaultAutoDetectColorSchemeAttrs.slice(),
|
|
244
313
|
};
|
|
245
314
|
}
|
|
246
|
-
const attrs = normalizeAttrList(
|
|
315
|
+
const attrs = normalizeAttrList(inputValue);
|
|
247
316
|
return attrs.length > 0
|
|
248
317
|
? { autoDetectColorScheme: attrs }
|
|
249
318
|
: undefined;
|
|
250
319
|
}
|
|
251
320
|
|
|
252
|
-
|
|
253
|
-
return undefined;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const attrs = input
|
|
257
|
-
.filter(function(value) {
|
|
258
|
-
return typeof value === "string";
|
|
259
|
-
})
|
|
260
|
-
.map(function(value) {
|
|
261
|
-
return value.trim();
|
|
262
|
-
})
|
|
263
|
-
.filter(function(value) {
|
|
264
|
-
return value.length > 0;
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
return attrs.length > 0
|
|
268
|
-
? { autoDetectColorScheme: attrs }
|
|
269
|
-
: undefined;
|
|
321
|
+
return undefined;
|
|
270
322
|
};
|
|
271
323
|
|
|
272
324
|
const getThemeInput = function(templateData) {
|
|
@@ -297,8 +349,48 @@ const getConsentState = function() {
|
|
|
297
349
|
return result;
|
|
298
350
|
};
|
|
299
351
|
|
|
352
|
+
const dedupeScopes = function(scopes) {
|
|
353
|
+
const seen = {};
|
|
354
|
+
const result = [];
|
|
355
|
+
for (let index = 0; index < scopes.length; index += 1) {
|
|
356
|
+
const scope = scopes[index];
|
|
357
|
+
if (typeof scope !== "string" || seen[scope]) {
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
seen[scope] = true;
|
|
361
|
+
result.push(scope);
|
|
362
|
+
}
|
|
363
|
+
return result;
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
const isKnownConsentType = function(consentType) {
|
|
367
|
+
for (let index = 0; index < gtmConsentTypes.length; index += 1) {
|
|
368
|
+
if (gtmConsentTypes[index] === consentType) {
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return false;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
const isHostConfigurableScope = function(scope) {
|
|
376
|
+
for (let index = 0; index < hostConfigurableScopes.length; index += 1) {
|
|
377
|
+
if (hostConfigurableScopes[index] === scope) {
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return false;
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
const isListLike = function(value) {
|
|
385
|
+
return (
|
|
386
|
+
!!value &&
|
|
387
|
+
typeof value.length === "number" &&
|
|
388
|
+
typeof value.map === "function"
|
|
389
|
+
);
|
|
390
|
+
};
|
|
391
|
+
|
|
300
392
|
const getManualScopeMappings = function(templateData) {
|
|
301
|
-
const rawRows =
|
|
393
|
+
const rawRows = isListLike(templateData.scopeMappings)
|
|
302
394
|
? templateData.scopeMappings
|
|
303
395
|
: [];
|
|
304
396
|
const rows = rawRows.length > 0 ? rawRows : defaultScopeMappings;
|
|
@@ -308,74 +400,95 @@ const getManualScopeMappings = function(templateData) {
|
|
|
308
400
|
return undefined;
|
|
309
401
|
}
|
|
310
402
|
const scope = trimString(row.scope);
|
|
311
|
-
const
|
|
312
|
-
if (!scope || !
|
|
403
|
+
const consentType = trimString(row.mapping);
|
|
404
|
+
if (!scope || !consentType) {
|
|
313
405
|
return undefined;
|
|
314
406
|
}
|
|
315
|
-
|
|
407
|
+
if (!isHostConfigurableScope(scope) || !isKnownConsentType(consentType)) {
|
|
408
|
+
return undefined;
|
|
409
|
+
}
|
|
410
|
+
return {
|
|
411
|
+
scope: scope,
|
|
412
|
+
consentType: consentType,
|
|
413
|
+
};
|
|
316
414
|
})
|
|
317
415
|
.filter(function(row) {
|
|
318
|
-
|
|
319
|
-
return false;
|
|
320
|
-
}
|
|
321
|
-
let isHostConfigurableScope = false;
|
|
322
|
-
for (let scopeIndex = 0; scopeIndex < hostConfigurableScopes.length; scopeIndex += 1) {
|
|
323
|
-
if (hostConfigurableScopes[scopeIndex] === row.scope) {
|
|
324
|
-
isHostConfigurableScope = true;
|
|
325
|
-
break;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
if (!isHostConfigurableScope) {
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
|
-
for (let index = 0; index < gtmConsentTypes.length; index += 1) {
|
|
332
|
-
if (gtmConsentTypes[index] === row.consentType) {
|
|
333
|
-
return true;
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
return false;
|
|
416
|
+
return row !== undefined;
|
|
337
417
|
});
|
|
338
418
|
};
|
|
339
419
|
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
continue;
|
|
347
|
-
}
|
|
348
|
-
seen[scope] = true;
|
|
349
|
-
result.push(scope);
|
|
420
|
+
const getAnalyticsMeasurementMode = function(templateData) {
|
|
421
|
+
if (
|
|
422
|
+
templateData.analyticsMeasurementMode === "granted" ||
|
|
423
|
+
templateData.analyticsMeasurementMode === "denied"
|
|
424
|
+
) {
|
|
425
|
+
return templateData.analyticsMeasurementMode;
|
|
350
426
|
}
|
|
351
|
-
return
|
|
427
|
+
return "inherit-analytics-storage";
|
|
352
428
|
};
|
|
353
429
|
|
|
354
430
|
const buildDefaultConsent = function(templateData) {
|
|
355
431
|
const consentState = getConsentState();
|
|
356
|
-
const scopeMappings =
|
|
357
|
-
templateData.consentMode === "manual"
|
|
358
|
-
? getManualScopeMappings(templateData)
|
|
359
|
-
: defaultScopeMappings;
|
|
360
432
|
const grantedScopes = [];
|
|
361
433
|
|
|
362
|
-
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
434
|
+
if (templateData.consentMode === "manual") {
|
|
435
|
+
const scopeMappings = getManualScopeMappings(templateData);
|
|
436
|
+
for (let index = 0; index < scopeMappings.length; index += 1) {
|
|
437
|
+
const mapping = scopeMappings[index];
|
|
438
|
+
if (consentState[mapping.consentType] === "granted") {
|
|
439
|
+
grantedScopes.push(mapping.scope);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
} else {
|
|
443
|
+
for (let index = 0; index < defaultScopeMappings.length; index += 1) {
|
|
444
|
+
const mapping = defaultScopeMappings[index];
|
|
445
|
+
if (consentState[mapping.mapping] === "granted") {
|
|
446
|
+
grantedScopes.push(mapping.scope);
|
|
447
|
+
}
|
|
367
448
|
}
|
|
368
|
-
}
|
|
369
449
|
|
|
370
|
-
|
|
371
|
-
|
|
450
|
+
const analyticsMeasurementMode = getAnalyticsMeasurementMode(templateData);
|
|
451
|
+
if (analyticsMeasurementMode === "granted") {
|
|
452
|
+
grantedScopes.push("analytics.measurement");
|
|
453
|
+
}
|
|
454
|
+
if (
|
|
455
|
+
analyticsMeasurementMode === "inherit-analytics-storage" &&
|
|
456
|
+
consentState.analytics_storage === "granted"
|
|
457
|
+
) {
|
|
458
|
+
grantedScopes.push("analytics.measurement");
|
|
459
|
+
}
|
|
372
460
|
}
|
|
373
461
|
|
|
374
462
|
const dedupedScopes = dedupeScopes(grantedScopes);
|
|
375
463
|
return dedupedScopes.length > 0 ? dedupedScopes : undefined;
|
|
376
464
|
};
|
|
377
465
|
|
|
466
|
+
const onSuccess = function() {
|
|
467
|
+
if (typeof data.gtmOnSuccess === "function") {
|
|
468
|
+
data.gtmOnSuccess();
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
const onFailure = function() {
|
|
473
|
+
if (typeof data.gtmOnFailure === "function") {
|
|
474
|
+
data.gtmOnFailure();
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
|
|
378
478
|
const apiKey = trimString(data.apiKey);
|
|
479
|
+
if (!apiKey) {
|
|
480
|
+
onFailure();
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
const encodedApiKey = encodeUriComponent(apiKey);
|
|
485
|
+
if (!encodedApiKey) {
|
|
486
|
+
onFailure();
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const widgetUrl = loaderScriptBaseUrl + "/" + encodedApiKey + "/loader.js";
|
|
491
|
+
const queuePush = createQueue(queueKey);
|
|
379
492
|
const initOptions = {
|
|
380
493
|
apiKey: apiKey,
|
|
381
494
|
clientMeta: {
|
|
@@ -394,10 +507,6 @@ if (defaultConsent !== undefined) {
|
|
|
394
507
|
initOptions.defaultConsent = defaultConsent;
|
|
395
508
|
}
|
|
396
509
|
|
|
397
|
-
const widgetUrl =
|
|
398
|
-
loaderScriptBaseUrl + "/" + encodeURIComponent(apiKey) + "/loader.js";
|
|
399
|
-
const queuePush = createQueue("__getuserfeedback_queue");
|
|
400
|
-
|
|
401
510
|
queuePush({
|
|
402
511
|
kind: "init",
|
|
403
512
|
opts: initOptions,
|
|
@@ -405,18 +514,6 @@ queuePush({
|
|
|
405
514
|
|
|
406
515
|
log("Loading getuserfeedback loader:", widgetUrl);
|
|
407
516
|
|
|
408
|
-
const onSuccess = function() {
|
|
409
|
-
if (typeof data.gtmOnSuccess === "function") {
|
|
410
|
-
data.gtmOnSuccess();
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
|
-
|
|
414
|
-
const onFailure = function() {
|
|
415
|
-
if (typeof data.gtmOnFailure === "function") {
|
|
416
|
-
data.gtmOnFailure();
|
|
417
|
-
}
|
|
418
|
-
};
|
|
419
|
-
|
|
420
517
|
if (queryPermission("inject_script", widgetUrl)) {
|
|
421
518
|
injectScript(widgetUrl, onSuccess, onFailure, "getuserfeedback");
|
|
422
519
|
} else {
|
|
@@ -424,9 +521,65 @@ if (queryPermission("inject_script", widgetUrl)) {
|
|
|
424
521
|
}
|
|
425
522
|
`.trim();
|
|
426
523
|
}
|
|
524
|
+
export function buildGtmPermissions(input) {
|
|
525
|
+
const loaderScriptBaseUrl = trimTrailingSlash(input?.loaderScriptBaseUrl ?? DEFAULT_GTM_LOADER_SCRIPT_BASE_URL);
|
|
526
|
+
const loaderUrlPattern = `${loaderScriptBaseUrl}/*/loader.js`;
|
|
527
|
+
return [
|
|
528
|
+
buildPermission("inject_script", [
|
|
529
|
+
{
|
|
530
|
+
key: "urls",
|
|
531
|
+
value: listValue([stringValue(loaderUrlPattern)]),
|
|
532
|
+
},
|
|
533
|
+
]),
|
|
534
|
+
buildPermission("logging", [
|
|
535
|
+
{
|
|
536
|
+
key: "environments",
|
|
537
|
+
value: stringValue("debug"),
|
|
538
|
+
},
|
|
539
|
+
]),
|
|
540
|
+
buildPermission("access_globals", [
|
|
541
|
+
{
|
|
542
|
+
key: "keys",
|
|
543
|
+
value: listValue([
|
|
544
|
+
mapValue([
|
|
545
|
+
["key", GTM_QUEUE_KEY],
|
|
546
|
+
["read", true],
|
|
547
|
+
["write", true],
|
|
548
|
+
["execute", false],
|
|
549
|
+
]),
|
|
550
|
+
]),
|
|
551
|
+
},
|
|
552
|
+
]),
|
|
553
|
+
buildPermission("access_consent", [
|
|
554
|
+
{
|
|
555
|
+
key: "consentTypes",
|
|
556
|
+
value: listValue(GTM_CONSENT_TYPES.map((consentType) => mapValue([
|
|
557
|
+
["consentType", consentType],
|
|
558
|
+
["read", true],
|
|
559
|
+
["write", false],
|
|
560
|
+
]))),
|
|
561
|
+
},
|
|
562
|
+
]),
|
|
563
|
+
];
|
|
564
|
+
}
|
|
565
|
+
export function buildGtmTemplateInfo(input) {
|
|
566
|
+
return {
|
|
567
|
+
type: "TAG",
|
|
568
|
+
version: GTM_TEMPLATE_VERSION,
|
|
569
|
+
displayName: input?.displayName ?? GTM_TEMPLATE_DEFAULT_DISPLAY_NAME,
|
|
570
|
+
description: input?.description ?? GTM_TEMPLATE_DEFAULT_DESCRIPTION,
|
|
571
|
+
categories: GTM_TEMPLATE_CATEGORIES,
|
|
572
|
+
containerContexts: GTM_TEMPLATE_CONTAINER_CONTEXTS,
|
|
573
|
+
};
|
|
574
|
+
}
|
|
427
575
|
export function buildGtmTemplateParts(input) {
|
|
428
576
|
return {
|
|
429
|
-
|
|
577
|
+
info: buildGtmTemplateInfo(input),
|
|
578
|
+
parameters: buildGtmTemplateParameters(input),
|
|
430
579
|
runtimeSource: buildGtmRuntimeSource(input),
|
|
580
|
+
permissions: buildGtmPermissions(input),
|
|
431
581
|
};
|
|
432
582
|
}
|
|
583
|
+
export function buildGtmTemplateArtifact(input) {
|
|
584
|
+
return buildGtmTemplateParts(input);
|
|
585
|
+
}
|