@getuserfeedback/adapters 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,52 @@
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 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 {};
52
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gtm/index.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;AAMF,KAAK,sBAAsB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC/B,WAAW,EAAE,cAAc,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;CACd,CAAC;AAUF,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"}
@@ -0,0 +1,165 @@
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
+ 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
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@getuserfeedback/adapters",
3
+ "version": "0.2.1",
4
+ "description": "getuserfeedback integration adapters",
5
+ "keywords": [
6
+ "getuserfeedback",
7
+ "widget",
8
+ "adapters",
9
+ "gtm"
10
+ ],
11
+ "license": "MIT",
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "type": "module",
16
+ "sideEffects": false,
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "exports": {
21
+ "./gtm": {
22
+ "types": "./dist/gtm/index.d.ts",
23
+ "import": "./dist/gtm/index.js"
24
+ }
25
+ },
26
+ "scripts": {
27
+ "prepack": "node scripts/prepack.cjs",
28
+ "postpack": "node scripts/postpack.cjs",
29
+ "lint": "ultracite check .",
30
+ "build": "bun x rimraf dist tsconfig.tsbuildinfo && tsc -b tsconfig.json",
31
+ "typecheck": "tsc -b tsconfig.json",
32
+ "test": "bun test --dots",
33
+ "pack:verify": "node ../../scripts/pack-and-verify.cjs --expect-dependency @getuserfeedback/protocol:../protocol/package.json",
34
+ "publish:dry-run": "node ../../scripts/publish-package.cjs . --expect-dependency @getuserfeedback/protocol:../protocol/package.json -- --dry-run",
35
+ "publish:npm": "node ../../scripts/publish-package.cjs . --expect-dependency @getuserfeedback/protocol:../protocol/package.json"
36
+ },
37
+ "dependencies": {
38
+ "@getuserfeedback/protocol": "^0.2.0"
39
+ },
40
+ "devDependencies": {
41
+ "rimraf": "^6.0.0",
42
+ "typescript": "^5.8.3"
43
+ }
44
+ }