@getuserfeedback/adapters 0.2.1 → 0.4.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/README.md +135 -0
- package/dist/gtm/core.d.ts +58 -0
- package/dist/gtm/core.d.ts.map +1 -0
- package/dist/gtm/core.js +166 -0
- package/dist/gtm/index.d.ts +2 -51
- package/dist/gtm/index.d.ts.map +1 -1
- package/dist/gtm/index.js +2 -165
- package/dist/gtm/template-generation.d.ts +129 -0
- package/dist/gtm/template-generation.d.ts.map +1 -0
- package/dist/gtm/template-generation.js +571 -0
- 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.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type InitOptions, type Scope } from "@getuserfeedback/protocol";
|
|
2
|
+
export declare const GTM_CONSENT_TYPES: readonly [
|
|
3
|
+
"functionality_storage",
|
|
4
|
+
"security_storage",
|
|
5
|
+
"analytics_storage",
|
|
6
|
+
"personalization_storage",
|
|
7
|
+
"ad_storage",
|
|
8
|
+
"ad_user_data",
|
|
9
|
+
"ad_personalization"
|
|
10
|
+
];
|
|
11
|
+
export type GtmConsentType = (typeof GTM_CONSENT_TYPES)[number];
|
|
12
|
+
export type GtmConsentValue = "granted" | "denied";
|
|
13
|
+
export type GtmAnalyticsMeasurementMode = "inherit-analytics-storage" | "granted" | "denied";
|
|
14
|
+
export type GtmScopeMapping = {
|
|
15
|
+
scope: Scope;
|
|
16
|
+
consentType: GtmConsentType;
|
|
17
|
+
};
|
|
18
|
+
export type GtmConsentState = Partial<Record<GtmConsentType, GtmConsentValue>>;
|
|
19
|
+
export type GtmTemplateInput = {
|
|
20
|
+
apiKey: string;
|
|
21
|
+
consentState?: GtmConsentState;
|
|
22
|
+
scopeMappings?: ReadonlyArray<GtmScopeMapping>;
|
|
23
|
+
analyticsMeasurementMode?: GtmAnalyticsMeasurementMode;
|
|
24
|
+
colorScheme?: unknown;
|
|
25
|
+
disableTelemetry?: boolean;
|
|
26
|
+
enableDebug?: InitOptions["enableDebug"];
|
|
27
|
+
capabilities?: InitOptions["capabilities"];
|
|
28
|
+
runtimeEndpoints?: InitOptions["runtimeEndpoints"];
|
|
29
|
+
clientMeta?: InitOptions["clientMeta"];
|
|
30
|
+
};
|
|
31
|
+
type ProtocolConsentScope = NonNullable<Exclude<InitOptions["defaultConsent"], string>>[number];
|
|
32
|
+
export type GtmTemplateScopeOption = {
|
|
33
|
+
label: string;
|
|
34
|
+
scope: Scope;
|
|
35
|
+
description: string;
|
|
36
|
+
};
|
|
37
|
+
export type GtmTemplateMappingOption = {
|
|
38
|
+
consentType: GtmConsentType;
|
|
39
|
+
label: string;
|
|
40
|
+
};
|
|
41
|
+
export declare const ESSENTIAL_GTM_SCOPES: readonly [
|
|
42
|
+
"functionality.storage",
|
|
43
|
+
"security.storage"
|
|
44
|
+
];
|
|
45
|
+
export declare const isHostConfigurableGtmScope: (scope: Scope) => scope is ProtocolConsentScope;
|
|
46
|
+
export declare const DEFAULT_GTM_SCOPE_MAPPINGS: ReadonlyArray<GtmScopeMapping>;
|
|
47
|
+
export declare const GTM_TEMPLATE_SCOPE_OPTIONS: ReadonlyArray<GtmTemplateScopeOption>;
|
|
48
|
+
export declare const GTM_TEMPLATE_MAPPING_OPTIONS: ReadonlyArray<GtmTemplateMappingOption>;
|
|
49
|
+
export declare function isGtmConsentType(value: unknown): value is GtmConsentType;
|
|
50
|
+
export declare function normalizeGtmThemeInput(input: unknown): InitOptions["colorScheme"] | undefined;
|
|
51
|
+
export declare function resolveDefaultConsentFromGtm(input: {
|
|
52
|
+
consentState?: GtmConsentState;
|
|
53
|
+
scopeMappings?: ReadonlyArray<GtmScopeMapping>;
|
|
54
|
+
analyticsMeasurementMode?: GtmAnalyticsMeasurementMode;
|
|
55
|
+
}): InitOptions["defaultConsent"] | undefined;
|
|
56
|
+
export declare function buildInitOptionsFromGtmTemplate(input: GtmTemplateInput): InitOptions;
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { colorSchemeConfigInputSchema, consentConfigInputSchema, DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS, listScopes, parseInitOptions, } from "@getuserfeedback/protocol";
|
|
2
|
+
export const GTM_CONSENT_TYPES = [
|
|
3
|
+
"functionality_storage",
|
|
4
|
+
"security_storage",
|
|
5
|
+
"analytics_storage",
|
|
6
|
+
"personalization_storage",
|
|
7
|
+
"ad_storage",
|
|
8
|
+
"ad_user_data",
|
|
9
|
+
"ad_personalization",
|
|
10
|
+
];
|
|
11
|
+
export const ESSENTIAL_GTM_SCOPES = ["functionality.storage", "security.storage"];
|
|
12
|
+
const essentialScopes = new Set(ESSENTIAL_GTM_SCOPES);
|
|
13
|
+
export const isHostConfigurableGtmScope = (scope) => !essentialScopes.has(scope);
|
|
14
|
+
export const DEFAULT_GTM_SCOPE_MAPPINGS = [
|
|
15
|
+
{
|
|
16
|
+
scope: "functionality.storage",
|
|
17
|
+
consentType: "functionality_storage",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
scope: "security.storage",
|
|
21
|
+
consentType: "security_storage",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
scope: "analytics.storage",
|
|
25
|
+
consentType: "analytics_storage",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
scope: "personalization.storage",
|
|
29
|
+
consentType: "personalization_storage",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
scope: "ads.storage",
|
|
33
|
+
consentType: "ad_storage",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
scope: "ads.user_data",
|
|
37
|
+
consentType: "ad_user_data",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
scope: "ads.personalization",
|
|
41
|
+
consentType: "ad_personalization",
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
const toTitleCase = (value) => value
|
|
45
|
+
.split(/[_\-.]/g)
|
|
46
|
+
.filter((part) => part.length > 0)
|
|
47
|
+
.map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`)
|
|
48
|
+
.join(" ");
|
|
49
|
+
const uniqueScopes = (scopes) => {
|
|
50
|
+
const deduped = new Set();
|
|
51
|
+
for (const scope of scopes) {
|
|
52
|
+
if (!isHostConfigurableGtmScope(scope)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
deduped.add(scope);
|
|
56
|
+
}
|
|
57
|
+
return [...deduped];
|
|
58
|
+
};
|
|
59
|
+
const normalizeAttrList = (value) => value
|
|
60
|
+
.split(",")
|
|
61
|
+
.map((entry) => entry.trim())
|
|
62
|
+
.filter((entry) => entry.length > 0);
|
|
63
|
+
export const GTM_TEMPLATE_SCOPE_OPTIONS = listScopes().map((scopeMeta) => ({
|
|
64
|
+
label: toTitleCase(scopeMeta.id),
|
|
65
|
+
scope: scopeMeta.id,
|
|
66
|
+
description: scopeMeta.description,
|
|
67
|
+
}));
|
|
68
|
+
export const GTM_TEMPLATE_MAPPING_OPTIONS = GTM_CONSENT_TYPES.map((consentType) => ({
|
|
69
|
+
consentType,
|
|
70
|
+
label: toTitleCase(consentType),
|
|
71
|
+
}));
|
|
72
|
+
export function isGtmConsentType(value) {
|
|
73
|
+
if (typeof value !== "string") {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return GTM_CONSENT_TYPES.some((consentType) => consentType === value);
|
|
77
|
+
}
|
|
78
|
+
export function normalizeGtmThemeInput(input) {
|
|
79
|
+
if (input === undefined || input === null) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
if (Array.isArray(input)) {
|
|
83
|
+
const attrs = input
|
|
84
|
+
.filter((value) => typeof value === "string")
|
|
85
|
+
.map((value) => value.trim())
|
|
86
|
+
.filter((value) => value.length > 0);
|
|
87
|
+
if (attrs.length === 0) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
return { autoDetectColorScheme: attrs };
|
|
91
|
+
}
|
|
92
|
+
if (typeof input !== "string") {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
const normalized = input.trim().toLowerCase();
|
|
96
|
+
if (normalized.length === 0) {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
if (normalized === "light" ||
|
|
100
|
+
normalized === "dark" ||
|
|
101
|
+
normalized === "system") {
|
|
102
|
+
return normalized;
|
|
103
|
+
}
|
|
104
|
+
if (normalized === "auto") {
|
|
105
|
+
return colorSchemeConfigInputSchema.parse({
|
|
106
|
+
autoDetectColorScheme: [...DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS],
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
const attrs = normalizeAttrList(input);
|
|
110
|
+
if (attrs.length === 0) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
return colorSchemeConfigInputSchema.parse({
|
|
114
|
+
autoDetectColorScheme: attrs,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
export function resolveDefaultConsentFromGtm(input) {
|
|
118
|
+
const consentState = input.consentState;
|
|
119
|
+
if (!consentState) {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
const mappings = input.scopeMappings ?? DEFAULT_GTM_SCOPE_MAPPINGS;
|
|
123
|
+
const grantedScopes = uniqueScopes(mappings.flatMap((mapping) => consentState[mapping.consentType] === "granted" ? [mapping.scope] : []));
|
|
124
|
+
const analyticsMeasurementMode = input.analyticsMeasurementMode ?? "inherit-analytics-storage";
|
|
125
|
+
if (analyticsMeasurementMode === "granted") {
|
|
126
|
+
grantedScopes.push("analytics.measurement");
|
|
127
|
+
}
|
|
128
|
+
if (analyticsMeasurementMode === "inherit-analytics-storage" &&
|
|
129
|
+
consentState.analytics_storage === "granted") {
|
|
130
|
+
grantedScopes.push("analytics.measurement");
|
|
131
|
+
}
|
|
132
|
+
const normalizedGrantedScopes = uniqueScopes(grantedScopes);
|
|
133
|
+
return normalizedGrantedScopes.length > 0
|
|
134
|
+
? consentConfigInputSchema.parse(normalizedGrantedScopes)
|
|
135
|
+
: undefined;
|
|
136
|
+
}
|
|
137
|
+
export function buildInitOptionsFromGtmTemplate(input) {
|
|
138
|
+
const colorScheme = normalizeGtmThemeInput(input.colorScheme);
|
|
139
|
+
const defaultConsent = resolveDefaultConsentFromGtm({
|
|
140
|
+
consentState: input.consentState,
|
|
141
|
+
scopeMappings: input.scopeMappings,
|
|
142
|
+
analyticsMeasurementMode: input.analyticsMeasurementMode,
|
|
143
|
+
});
|
|
144
|
+
return parseInitOptions({
|
|
145
|
+
apiKey: input.apiKey,
|
|
146
|
+
...(colorScheme !== undefined ? { colorScheme } : {}),
|
|
147
|
+
...(input.disableTelemetry !== undefined
|
|
148
|
+
? { disableTelemetry: input.disableTelemetry }
|
|
149
|
+
: {}),
|
|
150
|
+
...(input.enableDebug !== undefined
|
|
151
|
+
? { enableDebug: input.enableDebug }
|
|
152
|
+
: {}),
|
|
153
|
+
...(defaultConsent !== undefined ? { defaultConsent } : {}),
|
|
154
|
+
clientMeta: {
|
|
155
|
+
...(input.clientMeta ?? {}),
|
|
156
|
+
loader: "gtm",
|
|
157
|
+
transport: input.clientMeta?.transport ?? "tag-manager",
|
|
158
|
+
},
|
|
159
|
+
...(input.capabilities !== undefined
|
|
160
|
+
? { capabilities: input.capabilities }
|
|
161
|
+
: {}),
|
|
162
|
+
...(input.runtimeEndpoints !== undefined
|
|
163
|
+
? { runtimeEndpoints: input.runtimeEndpoints }
|
|
164
|
+
: {}),
|
|
165
|
+
});
|
|
166
|
+
}
|
package/dist/gtm/index.d.ts
CHANGED
|
@@ -1,52 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
"functionality_storage",
|
|
4
|
-
"security_storage",
|
|
5
|
-
"analytics_storage",
|
|
6
|
-
"personalization_storage",
|
|
7
|
-
"ad_storage",
|
|
8
|
-
"ad_user_data",
|
|
9
|
-
"ad_personalization"
|
|
10
|
-
];
|
|
11
|
-
export type GtmConsentType = (typeof GTM_CONSENT_TYPES)[number];
|
|
12
|
-
export type GtmConsentValue = "granted" | "denied";
|
|
13
|
-
export type GtmAnalyticsMeasurementMode = "inherit-analytics-storage" | "granted" | "denied";
|
|
14
|
-
export type GtmScopeMapping = {
|
|
15
|
-
scope: Scope;
|
|
16
|
-
consentType: GtmConsentType;
|
|
17
|
-
};
|
|
18
|
-
export type GtmConsentState = Partial<Record<GtmConsentType, GtmConsentValue>>;
|
|
19
|
-
export type GtmTemplateInput = {
|
|
20
|
-
apiKey: string;
|
|
21
|
-
consentState?: GtmConsentState;
|
|
22
|
-
scopeMappings?: ReadonlyArray<GtmScopeMapping>;
|
|
23
|
-
analyticsMeasurementMode?: GtmAnalyticsMeasurementMode;
|
|
24
|
-
colorScheme?: unknown;
|
|
25
|
-
disableTelemetry?: boolean;
|
|
26
|
-
enableDebug?: InitOptions["enableDebug"];
|
|
27
|
-
capabilities?: InitOptions["capabilities"];
|
|
28
|
-
runtimeEndpoints?: InitOptions["runtimeEndpoints"];
|
|
29
|
-
clientMeta?: InitOptions["clientMeta"];
|
|
30
|
-
};
|
|
31
|
-
type GtmTemplateScopeOption = {
|
|
32
|
-
label: string;
|
|
33
|
-
scope: Scope;
|
|
34
|
-
description: string;
|
|
35
|
-
};
|
|
36
|
-
type GtmTemplateMappingOption = {
|
|
37
|
-
consentType: GtmConsentType;
|
|
38
|
-
label: string;
|
|
39
|
-
};
|
|
40
|
-
export declare const DEFAULT_GTM_SCOPE_MAPPINGS: ReadonlyArray<GtmScopeMapping>;
|
|
41
|
-
export declare const GTM_TEMPLATE_SCOPE_OPTIONS: ReadonlyArray<GtmTemplateScopeOption>;
|
|
42
|
-
export declare const GTM_TEMPLATE_MAPPING_OPTIONS: ReadonlyArray<GtmTemplateMappingOption>;
|
|
43
|
-
export declare function isGtmConsentType(value: unknown): value is GtmConsentType;
|
|
44
|
-
export declare function normalizeGtmThemeInput(input: unknown): InitOptions["colorScheme"] | undefined;
|
|
45
|
-
export declare function resolveDefaultConsentFromGtm(input: {
|
|
46
|
-
consentState?: GtmConsentState;
|
|
47
|
-
scopeMappings?: ReadonlyArray<GtmScopeMapping>;
|
|
48
|
-
analyticsMeasurementMode?: GtmAnalyticsMeasurementMode;
|
|
49
|
-
}): InitOptions["defaultConsent"] | undefined;
|
|
50
|
-
export declare function buildInitOptionsFromGtmTemplate(input: GtmTemplateInput): InitOptions;
|
|
51
|
-
export {};
|
|
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 { 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";
|
|
52
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,
|
|
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,165 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
"functionality_storage",
|
|
4
|
-
"security_storage",
|
|
5
|
-
"analytics_storage",
|
|
6
|
-
"personalization_storage",
|
|
7
|
-
"ad_storage",
|
|
8
|
-
"ad_user_data",
|
|
9
|
-
"ad_personalization",
|
|
10
|
-
];
|
|
11
|
-
const essentialScopes = new Set([
|
|
12
|
-
"functionality.storage",
|
|
13
|
-
"security.storage",
|
|
14
|
-
]);
|
|
15
|
-
const isProtocolConsentScope = (scope) => !essentialScopes.has(scope);
|
|
16
|
-
export const DEFAULT_GTM_SCOPE_MAPPINGS = [
|
|
17
|
-
{
|
|
18
|
-
scope: "functionality.storage",
|
|
19
|
-
consentType: "functionality_storage",
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
scope: "security.storage",
|
|
23
|
-
consentType: "security_storage",
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
scope: "analytics.storage",
|
|
27
|
-
consentType: "analytics_storage",
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
scope: "personalization.storage",
|
|
31
|
-
consentType: "personalization_storage",
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
scope: "ads.storage",
|
|
35
|
-
consentType: "ad_storage",
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
scope: "ads.user_data",
|
|
39
|
-
consentType: "ad_user_data",
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
scope: "ads.personalization",
|
|
43
|
-
consentType: "ad_personalization",
|
|
44
|
-
},
|
|
45
|
-
];
|
|
46
|
-
const toTitleCase = (value) => value
|
|
47
|
-
.split(/[_\-.]/g)
|
|
48
|
-
.filter((part) => part.length > 0)
|
|
49
|
-
.map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`)
|
|
50
|
-
.join(" ");
|
|
51
|
-
const uniqueScopes = (scopes) => {
|
|
52
|
-
const deduped = new Set();
|
|
53
|
-
for (const scope of scopes) {
|
|
54
|
-
if (!isProtocolConsentScope(scope)) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
deduped.add(scope);
|
|
58
|
-
}
|
|
59
|
-
return [...deduped];
|
|
60
|
-
};
|
|
61
|
-
const normalizeAttrList = (value) => value
|
|
62
|
-
.split(",")
|
|
63
|
-
.map((entry) => entry.trim())
|
|
64
|
-
.filter((entry) => entry.length > 0);
|
|
65
|
-
export const GTM_TEMPLATE_SCOPE_OPTIONS = listScopes().map((scopeMeta) => ({
|
|
66
|
-
label: toTitleCase(scopeMeta.id),
|
|
67
|
-
scope: scopeMeta.id,
|
|
68
|
-
description: scopeMeta.description,
|
|
69
|
-
}));
|
|
70
|
-
export const GTM_TEMPLATE_MAPPING_OPTIONS = GTM_CONSENT_TYPES.map((consentType) => ({
|
|
71
|
-
consentType,
|
|
72
|
-
label: toTitleCase(consentType),
|
|
73
|
-
}));
|
|
74
|
-
export function isGtmConsentType(value) {
|
|
75
|
-
if (typeof value !== "string") {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
return GTM_CONSENT_TYPES.some((consentType) => consentType === value);
|
|
79
|
-
}
|
|
80
|
-
export function normalizeGtmThemeInput(input) {
|
|
81
|
-
if (input === undefined || input === null) {
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
|
-
if (Array.isArray(input)) {
|
|
85
|
-
const attrs = input
|
|
86
|
-
.filter((value) => typeof value === "string")
|
|
87
|
-
.map((value) => value.trim())
|
|
88
|
-
.filter((value) => value.length > 0);
|
|
89
|
-
if (attrs.length === 0) {
|
|
90
|
-
return undefined;
|
|
91
|
-
}
|
|
92
|
-
return { autoDetectColorScheme: attrs };
|
|
93
|
-
}
|
|
94
|
-
if (typeof input !== "string") {
|
|
95
|
-
return undefined;
|
|
96
|
-
}
|
|
97
|
-
const normalized = input.trim().toLowerCase();
|
|
98
|
-
if (normalized.length === 0) {
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
if (normalized === "light" ||
|
|
102
|
-
normalized === "dark" ||
|
|
103
|
-
normalized === "system") {
|
|
104
|
-
return normalized;
|
|
105
|
-
}
|
|
106
|
-
if (normalized === "auto") {
|
|
107
|
-
return {
|
|
108
|
-
autoDetectColorScheme: [...DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS],
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
const attrs = normalizeAttrList(input);
|
|
112
|
-
if (attrs.length === 0) {
|
|
113
|
-
return undefined;
|
|
114
|
-
}
|
|
115
|
-
return {
|
|
116
|
-
autoDetectColorScheme: attrs,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
export function resolveDefaultConsentFromGtm(input) {
|
|
120
|
-
const consentState = input.consentState;
|
|
121
|
-
if (!consentState) {
|
|
122
|
-
return undefined;
|
|
123
|
-
}
|
|
124
|
-
const mappings = input.scopeMappings ?? DEFAULT_GTM_SCOPE_MAPPINGS;
|
|
125
|
-
const grantedScopes = uniqueScopes(mappings.flatMap((mapping) => consentState[mapping.consentType] === "granted" ? [mapping.scope] : []));
|
|
126
|
-
const analyticsMeasurementMode = input.analyticsMeasurementMode ?? "inherit-analytics-storage";
|
|
127
|
-
if (analyticsMeasurementMode === "granted") {
|
|
128
|
-
grantedScopes.push("analytics.measurement");
|
|
129
|
-
}
|
|
130
|
-
if (analyticsMeasurementMode === "inherit-analytics-storage" &&
|
|
131
|
-
consentState.analytics_storage === "granted") {
|
|
132
|
-
grantedScopes.push("analytics.measurement");
|
|
133
|
-
}
|
|
134
|
-
return uniqueScopes(grantedScopes);
|
|
135
|
-
}
|
|
136
|
-
export function buildInitOptionsFromGtmTemplate(input) {
|
|
137
|
-
const colorScheme = normalizeGtmThemeInput(input.colorScheme);
|
|
138
|
-
const defaultConsent = resolveDefaultConsentFromGtm({
|
|
139
|
-
consentState: input.consentState,
|
|
140
|
-
scopeMappings: input.scopeMappings,
|
|
141
|
-
analyticsMeasurementMode: input.analyticsMeasurementMode,
|
|
142
|
-
});
|
|
143
|
-
return {
|
|
144
|
-
apiKey: input.apiKey,
|
|
145
|
-
...(colorScheme !== undefined ? { colorScheme } : {}),
|
|
146
|
-
...(input.disableTelemetry !== undefined
|
|
147
|
-
? { disableTelemetry: input.disableTelemetry }
|
|
148
|
-
: {}),
|
|
149
|
-
...(input.enableDebug !== undefined
|
|
150
|
-
? { enableDebug: input.enableDebug }
|
|
151
|
-
: {}),
|
|
152
|
-
...(defaultConsent !== undefined ? { defaultConsent } : {}),
|
|
153
|
-
clientMeta: {
|
|
154
|
-
...(input.clientMeta ?? {}),
|
|
155
|
-
loader: "gtm",
|
|
156
|
-
transport: input.clientMeta?.transport ?? "tag-manager",
|
|
157
|
-
},
|
|
158
|
-
...(input.capabilities !== undefined
|
|
159
|
-
? { capabilities: input.capabilities }
|
|
160
|
-
: {}),
|
|
161
|
-
...(input.runtimeEndpoints !== undefined
|
|
162
|
-
? { runtimeEndpoints: input.runtimeEndpoints }
|
|
163
|
-
: {}),
|
|
164
|
-
};
|
|
165
|
-
}
|
|
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 { buildGtmPermissions, buildGtmRuntimeSource, buildGtmTemplateArtifact, buildGtmTemplateInfo, buildGtmTemplateParameters, buildGtmTemplateParts, DEFAULT_GTM_LOADER_SCRIPT_BASE_URL, } from "./template-generation.js";
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
export type TemplateSelectItem = {
|
|
2
|
+
value: string;
|
|
3
|
+
displayValue: string;
|
|
4
|
+
};
|
|
5
|
+
export type TemplateCondition = {
|
|
6
|
+
paramName: string;
|
|
7
|
+
paramValue: string;
|
|
8
|
+
type: "EQUALS";
|
|
9
|
+
};
|
|
10
|
+
export type TemplateValueValidator = {
|
|
11
|
+
type: "NON_EMPTY";
|
|
12
|
+
};
|
|
13
|
+
export type TemplateParameter = {
|
|
14
|
+
type: "TEXT";
|
|
15
|
+
name: string;
|
|
16
|
+
displayName: string;
|
|
17
|
+
simpleValueType: true;
|
|
18
|
+
help?: string;
|
|
19
|
+
defaultValue?: string;
|
|
20
|
+
valueValidators?: TemplateValueValidator[];
|
|
21
|
+
enablingConditions?: TemplateCondition[];
|
|
22
|
+
} | {
|
|
23
|
+
type: "SELECT";
|
|
24
|
+
name: string;
|
|
25
|
+
displayName: string;
|
|
26
|
+
simpleValueType: true;
|
|
27
|
+
help?: string;
|
|
28
|
+
defaultValue?: string;
|
|
29
|
+
macrosInSelect: boolean;
|
|
30
|
+
selectItems: TemplateSelectItem[];
|
|
31
|
+
valueValidators?: TemplateValueValidator[];
|
|
32
|
+
enablingConditions?: TemplateCondition[];
|
|
33
|
+
} | {
|
|
34
|
+
type: "RADIO";
|
|
35
|
+
name: string;
|
|
36
|
+
displayName: string;
|
|
37
|
+
simpleValueType: true;
|
|
38
|
+
defaultValue: string;
|
|
39
|
+
radioItems: Array<TemplateSelectItem & {
|
|
40
|
+
help?: string;
|
|
41
|
+
}>;
|
|
42
|
+
} | {
|
|
43
|
+
type: "SIMPLE_TABLE";
|
|
44
|
+
name: string;
|
|
45
|
+
displayName: string;
|
|
46
|
+
help?: string;
|
|
47
|
+
defaultValue?: Array<Record<string, string>>;
|
|
48
|
+
newRowButtonText: string;
|
|
49
|
+
simpleTableColumns: Array<{
|
|
50
|
+
defaultValue?: string;
|
|
51
|
+
displayName: string;
|
|
52
|
+
name: string;
|
|
53
|
+
type: "SELECT";
|
|
54
|
+
isUnique?: boolean;
|
|
55
|
+
macrosInSelect?: boolean;
|
|
56
|
+
selectItems: TemplateSelectItem[];
|
|
57
|
+
}>;
|
|
58
|
+
valueValidators?: TemplateValueValidator[];
|
|
59
|
+
enablingConditions?: TemplateCondition[];
|
|
60
|
+
} | {
|
|
61
|
+
type: "GROUP";
|
|
62
|
+
name: string;
|
|
63
|
+
displayName: string;
|
|
64
|
+
groupStyle: "ZIPPY_CLOSED";
|
|
65
|
+
subParams: TemplateParameter[];
|
|
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
|
+
};
|
|
109
|
+
export type GtmTemplateParts = {
|
|
110
|
+
info: GtmTemplateInfo;
|
|
111
|
+
parameters: TemplateParameter[];
|
|
112
|
+
runtimeSource: string;
|
|
113
|
+
permissions: GtmTemplatePermission[];
|
|
114
|
+
};
|
|
115
|
+
export type GtmTemplateArtifact = GtmTemplateParts;
|
|
116
|
+
export type GtmTemplateGenerationOptions = {
|
|
117
|
+
loaderScriptBaseUrl?: string;
|
|
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 {};
|
|
129
|
+
//# sourceMappingURL=template-generation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-generation.d.ts","sourceRoot":"","sources":["../../src/gtm/template-generation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
import { DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS, } from "@getuserfeedback/protocol";
|
|
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
|
+
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";
|
|
14
|
+
const NON_EMPTY_VALIDATOR = { type: "NON_EMPTY" };
|
|
15
|
+
const MANUAL_CONSENT_MODE_CONDITION = [
|
|
16
|
+
{
|
|
17
|
+
paramName: "consentMode",
|
|
18
|
+
paramValue: "manual",
|
|
19
|
+
type: "EQUALS",
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
const AUTOMATIC_CONSENT_MODE_CONDITION = [
|
|
23
|
+
{
|
|
24
|
+
paramName: "consentMode",
|
|
25
|
+
paramValue: "automatic",
|
|
26
|
+
type: "EQUALS",
|
|
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
|
+
})),
|
|
34
|
+
{
|
|
35
|
+
scope: "analytics.measurement",
|
|
36
|
+
mapping: "analytics_storage",
|
|
37
|
+
},
|
|
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");
|
|
45
|
+
const buildHostConfigurableScopeSelectItems = () => GTM_TEMPLATE_SCOPE_OPTIONS.filter((option) => isHostConfigurableGtmScope(option.scope)).map((option) => ({
|
|
46
|
+
value: option.scope,
|
|
47
|
+
displayValue: option.label,
|
|
48
|
+
}));
|
|
49
|
+
const buildGtmConsentTypeSelectItems = () => GTM_TEMPLATE_MAPPING_OPTIONS.map((option) => ({
|
|
50
|
+
value: option.consentType,
|
|
51
|
+
displayValue: `${option.label} Granted`,
|
|
52
|
+
}));
|
|
53
|
+
const trimTrailingSlash = (value) => value.endsWith("/") ? value.slice(0, -1) : value;
|
|
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) {
|
|
93
|
+
const scopeHelp = buildScopeParameterHelp();
|
|
94
|
+
const scopeSelectItems = buildHostConfigurableScopeSelectItems();
|
|
95
|
+
const mappingSelectItems = buildGtmConsentTypeSelectItems();
|
|
96
|
+
return [
|
|
97
|
+
{
|
|
98
|
+
type: "TEXT",
|
|
99
|
+
name: "apiKey",
|
|
100
|
+
displayName: "API Key",
|
|
101
|
+
simpleValueType: true,
|
|
102
|
+
help: "Find your API key in getuserfeedback.com under Settings -> Widget.",
|
|
103
|
+
valueValidators: [NON_EMPTY_VALIDATOR],
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
type: "GROUP",
|
|
107
|
+
name: "themeGroup",
|
|
108
|
+
displayName: "Theme Settings",
|
|
109
|
+
groupStyle: "ZIPPY_CLOSED",
|
|
110
|
+
subParams: [
|
|
111
|
+
{
|
|
112
|
+
type: "SELECT",
|
|
113
|
+
name: "themeMode",
|
|
114
|
+
displayName: "Theme Mode",
|
|
115
|
+
macrosInSelect: false,
|
|
116
|
+
selectItems: [
|
|
117
|
+
{
|
|
118
|
+
value: "light",
|
|
119
|
+
displayValue: "Always Light",
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
value: "dark",
|
|
123
|
+
displayValue: "Always Dark",
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
value: "system",
|
|
127
|
+
displayValue: "Follow System Preference",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
value: "host",
|
|
131
|
+
displayValue: "Sync With Host Attributes",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
value: "variable",
|
|
135
|
+
displayValue: "Resolve From GTM Variable",
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
simpleValueType: true,
|
|
139
|
+
defaultValue: "host",
|
|
140
|
+
help: "Generate protocol-valid `init.opts.colorScheme` using fixed modes, host auto-detect attributes, or a GTM variable.",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: "SELECT",
|
|
144
|
+
name: "themeModeVariable",
|
|
145
|
+
displayName: "Theme Mode Variable",
|
|
146
|
+
macrosInSelect: true,
|
|
147
|
+
selectItems: [],
|
|
148
|
+
simpleValueType: true,
|
|
149
|
+
help: "Variable must resolve to `light`, `dark`, `system`, `auto`, or a comma-separated attribute list.",
|
|
150
|
+
enablingConditions: [
|
|
151
|
+
{
|
|
152
|
+
paramName: "themeMode",
|
|
153
|
+
paramValue: "variable",
|
|
154
|
+
type: "EQUALS",
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
valueValidators: [NON_EMPTY_VALIDATOR],
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
type: "TEXT",
|
|
161
|
+
name: "themeAttr",
|
|
162
|
+
displayName: "Host Theme Attributes",
|
|
163
|
+
simpleValueType: true,
|
|
164
|
+
defaultValue: DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS.join(","),
|
|
165
|
+
help: "Comma-separated attributes to inspect on `<html>` or `<body>` when syncing the widget to host theme state.",
|
|
166
|
+
enablingConditions: [
|
|
167
|
+
{
|
|
168
|
+
paramName: "themeMode",
|
|
169
|
+
paramValue: "host",
|
|
170
|
+
type: "EQUALS",
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
type: "GROUP",
|
|
178
|
+
name: "consentGroup",
|
|
179
|
+
displayName: "Consent Settings",
|
|
180
|
+
groupStyle: "ZIPPY_CLOSED",
|
|
181
|
+
subParams: [
|
|
182
|
+
{
|
|
183
|
+
type: "RADIO",
|
|
184
|
+
name: "consentMode",
|
|
185
|
+
displayName: "Consent Mode",
|
|
186
|
+
radioItems: [
|
|
187
|
+
{
|
|
188
|
+
value: "automatic",
|
|
189
|
+
displayValue: "Automatic (Use GTM Consent Mode)",
|
|
190
|
+
help: "Read GTM consent mode via `isConsentGranted`, translate granted consent types into widget `defaultConsent`, and apply the explicit analytics measurement policy.",
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
value: "manual",
|
|
194
|
+
displayValue: "Manual (Map Public Scopes)",
|
|
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.",
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
simpleValueType: true,
|
|
199
|
+
defaultValue: "automatic",
|
|
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
|
+
},
|
|
225
|
+
{
|
|
226
|
+
type: "SIMPLE_TABLE",
|
|
227
|
+
name: "scopeMappings",
|
|
228
|
+
displayName: "Scope Mappings",
|
|
229
|
+
simpleTableColumns: [
|
|
230
|
+
{
|
|
231
|
+
defaultValue: "analytics.storage",
|
|
232
|
+
displayName: "Widget Scope",
|
|
233
|
+
name: "scope",
|
|
234
|
+
type: "SELECT",
|
|
235
|
+
isUnique: true,
|
|
236
|
+
selectItems: scopeSelectItems,
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
defaultValue: "analytics_storage",
|
|
240
|
+
displayName: "Granted When",
|
|
241
|
+
name: "mapping",
|
|
242
|
+
type: "SELECT",
|
|
243
|
+
macrosInSelect: true,
|
|
244
|
+
selectItems: mappingSelectItems,
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
newRowButtonText: "Add Scope",
|
|
248
|
+
help: scopeHelp,
|
|
249
|
+
enablingConditions: [...MANUAL_CONSENT_MODE_CONDITION],
|
|
250
|
+
valueValidators: [NON_EMPTY_VALIDATOR],
|
|
251
|
+
defaultValue: buildHostConfigurableDefaultScopeMappings().map((row) => ({
|
|
252
|
+
scope: row.scope,
|
|
253
|
+
mapping: row.mapping,
|
|
254
|
+
})),
|
|
255
|
+
},
|
|
256
|
+
],
|
|
257
|
+
},
|
|
258
|
+
];
|
|
259
|
+
}
|
|
260
|
+
export function buildGtmRuntimeSource(input) {
|
|
261
|
+
const loaderScriptBaseUrl = trimTrailingSlash(input?.loaderScriptBaseUrl ?? DEFAULT_GTM_LOADER_SCRIPT_BASE_URL);
|
|
262
|
+
const defaultTemplateScopeMappings = buildHostConfigurableDefaultScopeMappings();
|
|
263
|
+
return `
|
|
264
|
+
const log = require("logToConsole");
|
|
265
|
+
const injectScript = require("injectScript");
|
|
266
|
+
const queryPermission = require("queryPermission");
|
|
267
|
+
const createQueue = require("createQueue");
|
|
268
|
+
const isConsentGranted = require("isConsentGranted");
|
|
269
|
+
|
|
270
|
+
const loaderScriptBaseUrl = ${JSON.stringify(loaderScriptBaseUrl)};
|
|
271
|
+
const gtmConsentTypes = ${JSON.stringify(GTM_CONSENT_TYPES)};
|
|
272
|
+
const defaultScopeMappings = ${JSON.stringify(defaultTemplateScopeMappings)};
|
|
273
|
+
const hostConfigurableScopes = ${JSON.stringify(defaultTemplateScopeMappings.map((row) => row.scope))};
|
|
274
|
+
const defaultAutoDetectColorSchemeAttrs = ${JSON.stringify(DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS)};
|
|
275
|
+
const queueKey = ${JSON.stringify(GTM_QUEUE_KEY)};
|
|
276
|
+
|
|
277
|
+
const trimString = function(value) {
|
|
278
|
+
return typeof value === "string" ? value.trim() : "";
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const normalizeAttrList = function(value) {
|
|
282
|
+
return value
|
|
283
|
+
.split(",")
|
|
284
|
+
.map(function(entry) {
|
|
285
|
+
return entry.trim();
|
|
286
|
+
})
|
|
287
|
+
.filter(function(entry) {
|
|
288
|
+
return entry.length > 0;
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
const normalizeThemeInput = function(inputValue) {
|
|
293
|
+
if (inputValue === undefined || inputValue === null) {
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (typeof inputValue === "string") {
|
|
298
|
+
const normalized = inputValue.trim().toLowerCase();
|
|
299
|
+
if (!normalized) {
|
|
300
|
+
return undefined;
|
|
301
|
+
}
|
|
302
|
+
if (
|
|
303
|
+
normalized === "light" ||
|
|
304
|
+
normalized === "dark" ||
|
|
305
|
+
normalized === "system"
|
|
306
|
+
) {
|
|
307
|
+
return normalized;
|
|
308
|
+
}
|
|
309
|
+
if (normalized === "auto") {
|
|
310
|
+
return {
|
|
311
|
+
autoDetectColorScheme: defaultAutoDetectColorSchemeAttrs.slice(),
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
const attrs = normalizeAttrList(inputValue);
|
|
315
|
+
return attrs.length > 0
|
|
316
|
+
? { autoDetectColorScheme: attrs }
|
|
317
|
+
: undefined;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return undefined;
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const getThemeInput = function(templateData) {
|
|
324
|
+
if (templateData.themeMode === "variable") {
|
|
325
|
+
return templateData.themeModeVariable;
|
|
326
|
+
}
|
|
327
|
+
if (templateData.themeMode === "host") {
|
|
328
|
+
return templateData.themeAttr;
|
|
329
|
+
}
|
|
330
|
+
if (
|
|
331
|
+
templateData.themeMode === "light" ||
|
|
332
|
+
templateData.themeMode === "dark" ||
|
|
333
|
+
templateData.themeMode === "system"
|
|
334
|
+
) {
|
|
335
|
+
return templateData.themeMode;
|
|
336
|
+
}
|
|
337
|
+
return undefined;
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
const getConsentState = function() {
|
|
341
|
+
const result = {};
|
|
342
|
+
for (let index = 0; index < gtmConsentTypes.length; index += 1) {
|
|
343
|
+
const consentType = gtmConsentTypes[index];
|
|
344
|
+
result[consentType] = isConsentGranted(consentType)
|
|
345
|
+
? "granted"
|
|
346
|
+
: "denied";
|
|
347
|
+
}
|
|
348
|
+
return result;
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
const dedupeScopes = function(scopes) {
|
|
352
|
+
const seen = {};
|
|
353
|
+
const result = [];
|
|
354
|
+
for (let index = 0; index < scopes.length; index += 1) {
|
|
355
|
+
const scope = scopes[index];
|
|
356
|
+
if (typeof scope !== "string" || seen[scope]) {
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
seen[scope] = true;
|
|
360
|
+
result.push(scope);
|
|
361
|
+
}
|
|
362
|
+
return result;
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
const isKnownConsentType = function(consentType) {
|
|
366
|
+
for (let index = 0; index < gtmConsentTypes.length; index += 1) {
|
|
367
|
+
if (gtmConsentTypes[index] === consentType) {
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return false;
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
const isHostConfigurableScope = function(scope) {
|
|
375
|
+
for (let index = 0; index < hostConfigurableScopes.length; index += 1) {
|
|
376
|
+
if (hostConfigurableScopes[index] === scope) {
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return false;
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
const getManualScopeMappings = function(templateData) {
|
|
384
|
+
const rawRows = Array.isArray(templateData.scopeMappings)
|
|
385
|
+
? templateData.scopeMappings
|
|
386
|
+
: [];
|
|
387
|
+
const rows = rawRows.length > 0 ? rawRows : defaultScopeMappings;
|
|
388
|
+
return rows
|
|
389
|
+
.map(function(row) {
|
|
390
|
+
if (!row || typeof row !== "object") {
|
|
391
|
+
return undefined;
|
|
392
|
+
}
|
|
393
|
+
const scope = trimString(row.scope);
|
|
394
|
+
const consentType = trimString(row.mapping);
|
|
395
|
+
if (!scope || !consentType) {
|
|
396
|
+
return undefined;
|
|
397
|
+
}
|
|
398
|
+
if (!isHostConfigurableScope(scope) || !isKnownConsentType(consentType)) {
|
|
399
|
+
return undefined;
|
|
400
|
+
}
|
|
401
|
+
return {
|
|
402
|
+
scope: scope,
|
|
403
|
+
consentType: consentType,
|
|
404
|
+
};
|
|
405
|
+
})
|
|
406
|
+
.filter(function(row) {
|
|
407
|
+
return row !== undefined;
|
|
408
|
+
});
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
const getAnalyticsMeasurementMode = function(templateData) {
|
|
412
|
+
if (
|
|
413
|
+
templateData.analyticsMeasurementMode === "granted" ||
|
|
414
|
+
templateData.analyticsMeasurementMode === "denied"
|
|
415
|
+
) {
|
|
416
|
+
return templateData.analyticsMeasurementMode;
|
|
417
|
+
}
|
|
418
|
+
return "inherit-analytics-storage";
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
const buildDefaultConsent = function(templateData) {
|
|
422
|
+
const consentState = getConsentState();
|
|
423
|
+
const grantedScopes = [];
|
|
424
|
+
|
|
425
|
+
if (templateData.consentMode === "manual") {
|
|
426
|
+
const scopeMappings = getManualScopeMappings(templateData);
|
|
427
|
+
for (let index = 0; index < scopeMappings.length; index += 1) {
|
|
428
|
+
const mapping = scopeMappings[index];
|
|
429
|
+
if (consentState[mapping.consentType] === "granted") {
|
|
430
|
+
grantedScopes.push(mapping.scope);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
} else {
|
|
434
|
+
for (let index = 0; index < defaultScopeMappings.length; index += 1) {
|
|
435
|
+
const mapping = defaultScopeMappings[index];
|
|
436
|
+
if (consentState[mapping.mapping] === "granted") {
|
|
437
|
+
grantedScopes.push(mapping.scope);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const analyticsMeasurementMode = getAnalyticsMeasurementMode(templateData);
|
|
442
|
+
if (analyticsMeasurementMode === "granted") {
|
|
443
|
+
grantedScopes.push("analytics.measurement");
|
|
444
|
+
}
|
|
445
|
+
if (
|
|
446
|
+
analyticsMeasurementMode === "inherit-analytics-storage" &&
|
|
447
|
+
consentState.analytics_storage === "granted"
|
|
448
|
+
) {
|
|
449
|
+
grantedScopes.push("analytics.measurement");
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const dedupedScopes = dedupeScopes(grantedScopes);
|
|
454
|
+
return dedupedScopes.length > 0 ? dedupedScopes : undefined;
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
const onSuccess = function() {
|
|
458
|
+
if (typeof data.gtmOnSuccess === "function") {
|
|
459
|
+
data.gtmOnSuccess();
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const onFailure = function() {
|
|
464
|
+
if (typeof data.gtmOnFailure === "function") {
|
|
465
|
+
data.gtmOnFailure();
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
const apiKey = trimString(data.apiKey);
|
|
470
|
+
if (!apiKey) {
|
|
471
|
+
onFailure();
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const widgetUrl =
|
|
476
|
+
loaderScriptBaseUrl + "/" + encodeURIComponent(apiKey) + "/loader.js";
|
|
477
|
+
const queuePush = createQueue(queueKey);
|
|
478
|
+
const initOptions = {
|
|
479
|
+
apiKey: apiKey,
|
|
480
|
+
clientMeta: {
|
|
481
|
+
loader: "gtm",
|
|
482
|
+
transport: "tag-manager",
|
|
483
|
+
},
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
const colorScheme = normalizeThemeInput(getThemeInput(data));
|
|
487
|
+
if (colorScheme !== undefined) {
|
|
488
|
+
initOptions.colorScheme = colorScheme;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const defaultConsent = buildDefaultConsent(data);
|
|
492
|
+
if (defaultConsent !== undefined) {
|
|
493
|
+
initOptions.defaultConsent = defaultConsent;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
queuePush({
|
|
497
|
+
kind: "init",
|
|
498
|
+
opts: initOptions,
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
log("Loading getuserfeedback loader:", widgetUrl);
|
|
502
|
+
|
|
503
|
+
if (queryPermission("inject_script", widgetUrl)) {
|
|
504
|
+
injectScript(widgetUrl, onSuccess, onFailure, "getuserfeedback");
|
|
505
|
+
} else {
|
|
506
|
+
onFailure();
|
|
507
|
+
}
|
|
508
|
+
`.trim();
|
|
509
|
+
}
|
|
510
|
+
export function buildGtmPermissions(input) {
|
|
511
|
+
const loaderScriptBaseUrl = trimTrailingSlash(input?.loaderScriptBaseUrl ?? DEFAULT_GTM_LOADER_SCRIPT_BASE_URL);
|
|
512
|
+
const loaderUrlPattern = `${loaderScriptBaseUrl}/*/loader.js`;
|
|
513
|
+
return [
|
|
514
|
+
buildPermission("inject_script", [
|
|
515
|
+
{
|
|
516
|
+
key: "urls",
|
|
517
|
+
value: listValue([stringValue(loaderUrlPattern)]),
|
|
518
|
+
},
|
|
519
|
+
]),
|
|
520
|
+
buildPermission("logging", [
|
|
521
|
+
{
|
|
522
|
+
key: "environments",
|
|
523
|
+
value: stringValue("debug"),
|
|
524
|
+
},
|
|
525
|
+
]),
|
|
526
|
+
buildPermission("access_globals", [
|
|
527
|
+
{
|
|
528
|
+
key: "keys",
|
|
529
|
+
value: listValue([
|
|
530
|
+
mapValue([
|
|
531
|
+
["key", GTM_QUEUE_KEY],
|
|
532
|
+
["read", true],
|
|
533
|
+
["write", true],
|
|
534
|
+
["execute", false],
|
|
535
|
+
]),
|
|
536
|
+
]),
|
|
537
|
+
},
|
|
538
|
+
]),
|
|
539
|
+
buildPermission("access_consent", [
|
|
540
|
+
{
|
|
541
|
+
key: "consentTypes",
|
|
542
|
+
value: listValue(GTM_CONSENT_TYPES.map((consentType) => mapValue([
|
|
543
|
+
["consentType", consentType],
|
|
544
|
+
["read", true],
|
|
545
|
+
["write", false],
|
|
546
|
+
]))),
|
|
547
|
+
},
|
|
548
|
+
]),
|
|
549
|
+
];
|
|
550
|
+
}
|
|
551
|
+
export function buildGtmTemplateInfo(input) {
|
|
552
|
+
return {
|
|
553
|
+
type: "TAG",
|
|
554
|
+
version: GTM_TEMPLATE_VERSION,
|
|
555
|
+
displayName: input?.displayName ?? GTM_TEMPLATE_DEFAULT_DISPLAY_NAME,
|
|
556
|
+
description: input?.description ?? GTM_TEMPLATE_DEFAULT_DESCRIPTION,
|
|
557
|
+
categories: GTM_TEMPLATE_CATEGORIES,
|
|
558
|
+
containerContexts: GTM_TEMPLATE_CONTAINER_CONTEXTS,
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
export function buildGtmTemplateParts(input) {
|
|
562
|
+
return {
|
|
563
|
+
info: buildGtmTemplateInfo(input),
|
|
564
|
+
parameters: buildGtmTemplateParameters(input),
|
|
565
|
+
runtimeSource: buildGtmRuntimeSource(input),
|
|
566
|
+
permissions: buildGtmPermissions(input),
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
export function buildGtmTemplateArtifact(input) {
|
|
570
|
+
return buildGtmTemplateParts(input);
|
|
571
|
+
}
|