@getuserfeedback/adapters 0.2.1 → 0.3.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/dist/gtm/core.d.ts +58 -0
- package/dist/gtm/core.d.ts.map +1 -0
- package/dist/gtm/core.js +163 -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 +79 -0
- package/dist/gtm/template-generation.d.ts.map +1 -0
- package/dist/gtm/template-generation.js +432 -0
- package/package.json +1 -1
|
@@ -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,EAEN,KAAK,WAAW,EAEhB,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,CA0B5C;AAED,wBAAgB,+BAA+B,CAC9C,KAAK,EAAE,gBAAgB,GACrB,WAAW,CA8Bb"}
|
package/dist/gtm/core.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS, listScopes, } 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 {
|
|
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 {
|
|
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
|
+
return uniqueScopes(grantedScopes);
|
|
133
|
+
}
|
|
134
|
+
export function buildInitOptionsFromGtmTemplate(input) {
|
|
135
|
+
const colorScheme = normalizeGtmThemeInput(input.colorScheme);
|
|
136
|
+
const defaultConsent = resolveDefaultConsentFromGtm({
|
|
137
|
+
consentState: input.consentState,
|
|
138
|
+
scopeMappings: input.scopeMappings,
|
|
139
|
+
analyticsMeasurementMode: input.analyticsMeasurementMode,
|
|
140
|
+
});
|
|
141
|
+
return {
|
|
142
|
+
apiKey: input.apiKey,
|
|
143
|
+
...(colorScheme !== undefined ? { colorScheme } : {}),
|
|
144
|
+
...(input.disableTelemetry !== undefined
|
|
145
|
+
? { disableTelemetry: input.disableTelemetry }
|
|
146
|
+
: {}),
|
|
147
|
+
...(input.enableDebug !== undefined
|
|
148
|
+
? { enableDebug: input.enableDebug }
|
|
149
|
+
: {}),
|
|
150
|
+
...(defaultConsent !== undefined ? { defaultConsent } : {}),
|
|
151
|
+
clientMeta: {
|
|
152
|
+
...(input.clientMeta ?? {}),
|
|
153
|
+
loader: "gtm",
|
|
154
|
+
transport: input.clientMeta?.transport ?? "tag-manager",
|
|
155
|
+
},
|
|
156
|
+
...(input.capabilities !== undefined
|
|
157
|
+
? { capabilities: input.capabilities }
|
|
158
|
+
: {}),
|
|
159
|
+
...(input.runtimeEndpoints !== undefined
|
|
160
|
+
? { runtimeEndpoints: input.runtimeEndpoints }
|
|
161
|
+
: {}),
|
|
162
|
+
};
|
|
163
|
+
}
|
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 { buildGtmRuntimeSource, buildGtmTemplateParameters, buildGtmTemplateParts, DEFAULT_GTM_LOADER_SCRIPT_BASE_URL, type GtmTemplateParts, 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,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"}
|
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 { buildGtmRuntimeSource, buildGtmTemplateParameters, buildGtmTemplateParts, DEFAULT_GTM_LOADER_SCRIPT_BASE_URL, } from "./template-generation.js";
|
|
@@ -0,0 +1,79 @@
|
|
|
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
|
+
export type GtmTemplateParts = {
|
|
68
|
+
parameters: TemplateParameter[];
|
|
69
|
+
runtimeSource: string;
|
|
70
|
+
};
|
|
71
|
+
export declare const DEFAULT_GTM_LOADER_SCRIPT_BASE_URL = "https://cdn.getuserfeedback.com/widget/loader/v1";
|
|
72
|
+
export declare function buildGtmTemplateParameters(): TemplateParameter[];
|
|
73
|
+
export declare function buildGtmRuntimeSource(input?: {
|
|
74
|
+
loaderScriptBaseUrl?: string;
|
|
75
|
+
}): string;
|
|
76
|
+
export declare function buildGtmTemplateParts(input?: {
|
|
77
|
+
loaderScriptBaseUrl?: string;
|
|
78
|
+
}): GtmTemplateParts;
|
|
79
|
+
//# 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,432 @@
|
|
|
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";
|
|
3
|
+
export const DEFAULT_GTM_LOADER_SCRIPT_BASE_URL = "https://cdn.getuserfeedback.com/widget/loader/v1";
|
|
4
|
+
const NON_EMPTY_VALIDATOR = { type: "NON_EMPTY" };
|
|
5
|
+
const buildScopeParameterHelp = () => GTM_TEMPLATE_SCOPE_OPTIONS.filter((option) => isHostConfigurableGtmScope(option.scope))
|
|
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
|
+
},
|
|
21
|
+
{
|
|
22
|
+
scope: "ads.storage",
|
|
23
|
+
mapping: "ad_storage",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
scope: "ads.user_data",
|
|
27
|
+
mapping: "ad_user_data",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
scope: "ads.personalization",
|
|
31
|
+
mapping: "ad_personalization",
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
const buildHostConfigurableScopeSelectItems = () => GTM_TEMPLATE_SCOPE_OPTIONS.filter((option) => isHostConfigurableGtmScope(option.scope)).map((option) => ({
|
|
35
|
+
value: option.scope,
|
|
36
|
+
displayValue: option.label,
|
|
37
|
+
}));
|
|
38
|
+
const buildGtmConsentTypeSelectItems = () => GTM_TEMPLATE_MAPPING_OPTIONS.map((option) => ({
|
|
39
|
+
value: option.consentType,
|
|
40
|
+
displayValue: `${option.label} Granted`,
|
|
41
|
+
}));
|
|
42
|
+
const trimTrailingSlash = (value) => value.endsWith("/") ? value.slice(0, -1) : value;
|
|
43
|
+
export function buildGtmTemplateParameters() {
|
|
44
|
+
const scopeHelp = buildScopeParameterHelp();
|
|
45
|
+
const scopeSelectItems = buildHostConfigurableScopeSelectItems();
|
|
46
|
+
const mappingSelectItems = buildGtmConsentTypeSelectItems();
|
|
47
|
+
return [
|
|
48
|
+
{
|
|
49
|
+
type: "TEXT",
|
|
50
|
+
name: "apiKey",
|
|
51
|
+
displayName: "API Key",
|
|
52
|
+
simpleValueType: true,
|
|
53
|
+
help: "Find your API key in getuserfeedback.com under Settings → Widget.",
|
|
54
|
+
valueValidators: [NON_EMPTY_VALIDATOR],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: "GROUP",
|
|
58
|
+
name: "themeGroup",
|
|
59
|
+
displayName: "Theme Settings",
|
|
60
|
+
groupStyle: "ZIPPY_CLOSED",
|
|
61
|
+
subParams: [
|
|
62
|
+
{
|
|
63
|
+
type: "SELECT",
|
|
64
|
+
name: "themeMode",
|
|
65
|
+
displayName: "Theme Mode",
|
|
66
|
+
macrosInSelect: false,
|
|
67
|
+
selectItems: [
|
|
68
|
+
{
|
|
69
|
+
value: "light",
|
|
70
|
+
displayValue: "Always Light",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
value: "dark",
|
|
74
|
+
displayValue: "Always Dark",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
value: "system",
|
|
78
|
+
displayValue: "Follow System Preference",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
value: "host",
|
|
82
|
+
displayValue: "Sync With Host",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
value: "variable",
|
|
86
|
+
displayValue: "Variable",
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
simpleValueType: true,
|
|
90
|
+
defaultValue: "host",
|
|
91
|
+
help: "Choose how the widget resolves `init.opts.colorScheme`.",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
type: "SELECT",
|
|
95
|
+
name: "themeModeVariable",
|
|
96
|
+
displayName: "Theme Mode Variable",
|
|
97
|
+
macrosInSelect: true,
|
|
98
|
+
selectItems: [],
|
|
99
|
+
simpleValueType: true,
|
|
100
|
+
help: "Variable must resolve to `light`, `dark`, `system`, `auto`, or a comma-separated attribute list.",
|
|
101
|
+
enablingConditions: [
|
|
102
|
+
{
|
|
103
|
+
paramName: "themeMode",
|
|
104
|
+
paramValue: "variable",
|
|
105
|
+
type: "EQUALS",
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
valueValidators: [NON_EMPTY_VALIDATOR],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
type: "TEXT",
|
|
112
|
+
name: "themeAttr",
|
|
113
|
+
displayName: "Host Theme Attributes",
|
|
114
|
+
simpleValueType: true,
|
|
115
|
+
defaultValue: DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS.join(","),
|
|
116
|
+
help: "Comma-separated attributes to inspect on `<html>` or `<body>` for host color scheme detection.",
|
|
117
|
+
enablingConditions: [
|
|
118
|
+
{
|
|
119
|
+
paramName: "themeMode",
|
|
120
|
+
paramValue: "host",
|
|
121
|
+
type: "EQUALS",
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
type: "GROUP",
|
|
129
|
+
name: "consentGroup",
|
|
130
|
+
displayName: "Consent Settings",
|
|
131
|
+
groupStyle: "ZIPPY_CLOSED",
|
|
132
|
+
subParams: [
|
|
133
|
+
{
|
|
134
|
+
type: "RADIO",
|
|
135
|
+
name: "consentMode",
|
|
136
|
+
displayName: "Consent Mode",
|
|
137
|
+
radioItems: [
|
|
138
|
+
{
|
|
139
|
+
value: "automatic",
|
|
140
|
+
displayValue: "Automatic (Use GTM Consent Mode)",
|
|
141
|
+
help: "Reads GTM Consent Mode and translates granted consent types into widget `defaultConsent`.",
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
value: "manual",
|
|
145
|
+
displayValue: "Manual (Map Public Scopes)",
|
|
146
|
+
help: "Override the public, host-configurable widget consent scopes with explicit GTM consent mappings.",
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
simpleValueType: true,
|
|
150
|
+
defaultValue: "automatic",
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
type: "SIMPLE_TABLE",
|
|
154
|
+
name: "scopeMappings",
|
|
155
|
+
displayName: "Scope Mappings",
|
|
156
|
+
simpleTableColumns: [
|
|
157
|
+
{
|
|
158
|
+
defaultValue: "analytics.storage",
|
|
159
|
+
displayName: "Widget Scope",
|
|
160
|
+
name: "scope",
|
|
161
|
+
type: "SELECT",
|
|
162
|
+
isUnique: true,
|
|
163
|
+
selectItems: scopeSelectItems,
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
defaultValue: "analytics_storage",
|
|
167
|
+
displayName: "Granted When",
|
|
168
|
+
name: "mapping",
|
|
169
|
+
type: "SELECT",
|
|
170
|
+
macrosInSelect: true,
|
|
171
|
+
selectItems: mappingSelectItems,
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
newRowButtonText: "Add Scope",
|
|
175
|
+
help: `Configure public widget consent scopes. Essential scopes are fixed by the loader and are not exposed here.\n\n${scopeHelp}`,
|
|
176
|
+
enablingConditions: [
|
|
177
|
+
{
|
|
178
|
+
paramName: "consentMode",
|
|
179
|
+
paramValue: "manual",
|
|
180
|
+
type: "EQUALS",
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
valueValidators: [NON_EMPTY_VALIDATOR],
|
|
184
|
+
defaultValue: buildDefaultTemplateScopeMappings().map((row) => ({
|
|
185
|
+
scope: row.scope,
|
|
186
|
+
mapping: row.mapping,
|
|
187
|
+
})),
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
}
|
|
193
|
+
export function buildGtmRuntimeSource(input) {
|
|
194
|
+
const loaderScriptBaseUrl = trimTrailingSlash(input?.loaderScriptBaseUrl ?? DEFAULT_GTM_LOADER_SCRIPT_BASE_URL);
|
|
195
|
+
const defaultTemplateScopeMappings = buildDefaultTemplateScopeMappings();
|
|
196
|
+
return `
|
|
197
|
+
const log = require("logToConsole");
|
|
198
|
+
const injectScript = require("injectScript");
|
|
199
|
+
const queryPermission = require("queryPermission");
|
|
200
|
+
const createQueue = require("createQueue");
|
|
201
|
+
const isConsentGranted = require("isConsentGranted");
|
|
202
|
+
|
|
203
|
+
const loaderScriptBaseUrl = ${JSON.stringify(loaderScriptBaseUrl)};
|
|
204
|
+
const gtmConsentTypes = ${JSON.stringify(GTM_CONSENT_TYPES)};
|
|
205
|
+
const defaultScopeMappings = ${JSON.stringify(defaultTemplateScopeMappings)};
|
|
206
|
+
const hostConfigurableScopes = ${JSON.stringify(buildDefaultTemplateScopeMappings().map((row) => row.scope))};
|
|
207
|
+
const defaultAutoDetectColorSchemeAttrs = ${JSON.stringify(DEFAULT_AUTO_DETECT_COLOR_SCHEME_ATTRS)};
|
|
208
|
+
|
|
209
|
+
const trimString = function(value) {
|
|
210
|
+
return typeof value === "string" ? value.trim() : "";
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const normalizeAttrList = function(value) {
|
|
214
|
+
return value
|
|
215
|
+
.split(",")
|
|
216
|
+
.map(function(entry) {
|
|
217
|
+
return entry.trim();
|
|
218
|
+
})
|
|
219
|
+
.filter(function(entry) {
|
|
220
|
+
return entry.length > 0;
|
|
221
|
+
});
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const normalizeThemeInput = function(input) {
|
|
225
|
+
if (input === undefined || input === null) {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (typeof input === "string") {
|
|
230
|
+
const normalized = input.trim().toLowerCase();
|
|
231
|
+
if (!normalized) {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
if (
|
|
235
|
+
normalized === "light" ||
|
|
236
|
+
normalized === "dark" ||
|
|
237
|
+
normalized === "system"
|
|
238
|
+
) {
|
|
239
|
+
return normalized;
|
|
240
|
+
}
|
|
241
|
+
if (normalized === "auto") {
|
|
242
|
+
return {
|
|
243
|
+
autoDetectColorScheme: defaultAutoDetectColorSchemeAttrs.slice(),
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const attrs = normalizeAttrList(input);
|
|
247
|
+
return attrs.length > 0
|
|
248
|
+
? { autoDetectColorScheme: attrs }
|
|
249
|
+
: undefined;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (!Array.isArray(input)) {
|
|
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;
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const getThemeInput = function(templateData) {
|
|
273
|
+
if (templateData.themeMode === "variable") {
|
|
274
|
+
return templateData.themeModeVariable;
|
|
275
|
+
}
|
|
276
|
+
if (templateData.themeMode === "host") {
|
|
277
|
+
return templateData.themeAttr;
|
|
278
|
+
}
|
|
279
|
+
if (
|
|
280
|
+
templateData.themeMode === "light" ||
|
|
281
|
+
templateData.themeMode === "dark" ||
|
|
282
|
+
templateData.themeMode === "system"
|
|
283
|
+
) {
|
|
284
|
+
return templateData.themeMode;
|
|
285
|
+
}
|
|
286
|
+
return undefined;
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
const getConsentState = function() {
|
|
290
|
+
const result = {};
|
|
291
|
+
for (let index = 0; index < gtmConsentTypes.length; index += 1) {
|
|
292
|
+
const consentType = gtmConsentTypes[index];
|
|
293
|
+
result[consentType] = isConsentGranted(consentType)
|
|
294
|
+
? "granted"
|
|
295
|
+
: "denied";
|
|
296
|
+
}
|
|
297
|
+
return result;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const getManualScopeMappings = function(templateData) {
|
|
301
|
+
const rawRows = Array.isArray(templateData.scopeMappings)
|
|
302
|
+
? templateData.scopeMappings
|
|
303
|
+
: [];
|
|
304
|
+
const rows = rawRows.length > 0 ? rawRows : defaultScopeMappings;
|
|
305
|
+
return rows
|
|
306
|
+
.map(function(row) {
|
|
307
|
+
if (!row || typeof row !== "object") {
|
|
308
|
+
return undefined;
|
|
309
|
+
}
|
|
310
|
+
const scope = trimString(row.scope);
|
|
311
|
+
const mapping = trimString(row.mapping);
|
|
312
|
+
if (!scope || !mapping) {
|
|
313
|
+
return undefined;
|
|
314
|
+
}
|
|
315
|
+
return { scope: scope, consentType: mapping };
|
|
316
|
+
})
|
|
317
|
+
.filter(function(row) {
|
|
318
|
+
if (!row) {
|
|
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;
|
|
337
|
+
});
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
const dedupeScopes = function(scopes) {
|
|
341
|
+
const seen = {};
|
|
342
|
+
const result = [];
|
|
343
|
+
for (let index = 0; index < scopes.length; index += 1) {
|
|
344
|
+
const scope = scopes[index];
|
|
345
|
+
if (typeof scope !== "string" || seen[scope]) {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
seen[scope] = true;
|
|
349
|
+
result.push(scope);
|
|
350
|
+
}
|
|
351
|
+
return result;
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
const buildDefaultConsent = function(templateData) {
|
|
355
|
+
const consentState = getConsentState();
|
|
356
|
+
const scopeMappings =
|
|
357
|
+
templateData.consentMode === "manual"
|
|
358
|
+
? getManualScopeMappings(templateData)
|
|
359
|
+
: defaultScopeMappings;
|
|
360
|
+
const grantedScopes = [];
|
|
361
|
+
|
|
362
|
+
for (let index = 0; index < scopeMappings.length; index += 1) {
|
|
363
|
+
const mapping = scopeMappings[index];
|
|
364
|
+
const consentType = mapping.consentType || mapping.mapping;
|
|
365
|
+
if (consentState[consentType] === "granted") {
|
|
366
|
+
grantedScopes.push(mapping.scope);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (consentState.analytics_storage === "granted") {
|
|
371
|
+
grantedScopes.push("analytics.measurement");
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const dedupedScopes = dedupeScopes(grantedScopes);
|
|
375
|
+
return dedupedScopes.length > 0 ? dedupedScopes : undefined;
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
const apiKey = trimString(data.apiKey);
|
|
379
|
+
const initOptions = {
|
|
380
|
+
apiKey: apiKey,
|
|
381
|
+
clientMeta: {
|
|
382
|
+
loader: "gtm",
|
|
383
|
+
transport: "tag-manager",
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
const colorScheme = normalizeThemeInput(getThemeInput(data));
|
|
388
|
+
if (colorScheme !== undefined) {
|
|
389
|
+
initOptions.colorScheme = colorScheme;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const defaultConsent = buildDefaultConsent(data);
|
|
393
|
+
if (defaultConsent !== undefined) {
|
|
394
|
+
initOptions.defaultConsent = defaultConsent;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const widgetUrl =
|
|
398
|
+
loaderScriptBaseUrl + "/" + encodeURIComponent(apiKey) + "/loader.js";
|
|
399
|
+
const queuePush = createQueue("__getuserfeedback_queue");
|
|
400
|
+
|
|
401
|
+
queuePush({
|
|
402
|
+
kind: "init",
|
|
403
|
+
opts: initOptions,
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
log("Loading getuserfeedback loader:", widgetUrl);
|
|
407
|
+
|
|
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
|
+
if (queryPermission("inject_script", widgetUrl)) {
|
|
421
|
+
injectScript(widgetUrl, onSuccess, onFailure, "getuserfeedback");
|
|
422
|
+
} else {
|
|
423
|
+
onFailure();
|
|
424
|
+
}
|
|
425
|
+
`.trim();
|
|
426
|
+
}
|
|
427
|
+
export function buildGtmTemplateParts(input) {
|
|
428
|
+
return {
|
|
429
|
+
parameters: buildGtmTemplateParameters(),
|
|
430
|
+
runtimeSource: buildGtmRuntimeSource(input),
|
|
431
|
+
};
|
|
432
|
+
}
|