@chordcommerce/analytics 1.17.0 → 1.18.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 +48 -0
- package/dist/cjs/client/cdp.d.ts +3 -0
- package/dist/cjs/client/cdp.js +123 -0
- package/dist/cjs/client/consent/index.d.ts +11 -0
- package/dist/cjs/client/consent/index.js +241 -0
- package/dist/cjs/client/consent/ketch.d.ts +16 -0
- package/dist/cjs/client/consent/ketch.js +53 -0
- package/dist/cjs/client/consent/onetrust.d.ts +22 -0
- package/dist/cjs/client/consent/onetrust.js +61 -0
- package/dist/cjs/client/consent/segment.d.ts +17 -0
- package/dist/cjs/client/consent/segment.js +155 -0
- package/dist/cjs/client/consent/shopify.d.ts +21 -0
- package/dist/cjs/client/consent/shopify.js +51 -0
- package/dist/cjs/client/index.d.ts +111 -0
- package/dist/cjs/client/index.js +861 -0
- package/dist/cjs/client/utils.d.ts +1 -0
- package/dist/cjs/client/utils.js +12 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.js +18 -0
- package/dist/cjs/setupTests.d.ts +1 -0
- package/dist/cjs/setupTests.js +6 -0
- package/dist/cjs/types/client.d.ts +96 -0
- package/dist/cjs/types/client.js +2 -0
- package/dist/cjs/types/consent.d.ts +11 -0
- package/dist/cjs/types/consent.js +2 -0
- package/dist/cjs/types/formatters.d.ts +114 -0
- package/dist/cjs/types/formatters.js +2 -0
- package/dist/cjs/types/index.d.ts +7 -0
- package/dist/cjs/types/index.js +22 -0
- package/dist/cjs/types/input.d.ts +396 -0
- package/dist/cjs/types/input.js +2 -0
- package/dist/cjs/types/objects.d.ts +379 -0
- package/dist/cjs/types/objects.js +2 -0
- package/dist/cjs/types/typewriter.d.ts +6502 -0
- package/dist/cjs/types/typewriter.js +5 -0
- package/dist/cjs/utils.d.ts +2 -0
- package/dist/cjs/utils.js +25 -0
- package/dist/cjs/validators/custom.d.ts +43 -0
- package/dist/cjs/validators/custom.js +18 -0
- package/dist/cjs/validators/index.d.ts +4 -0
- package/dist/cjs/validators/index.js +20 -0
- package/dist/cjs/validators/objects.d.ts +696 -0
- package/dist/cjs/validators/objects.js +128 -0
- package/dist/cjs/validators/tracking-plan-map.d.ts +6603 -0
- package/dist/cjs/validators/tracking-plan-map.js +72 -0
- package/dist/cjs/validators/tracking-plan.d.ts +9275 -0
- package/dist/cjs/validators/tracking-plan.js +1682 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -30,6 +30,14 @@ const chord = new ChordAnalytics(options) // see below for configuration options
|
|
|
30
30
|
chord.trackCartViewed({ cart }) // sends a "Cart Viewed" event to the CDP
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
### CommonJS Import
|
|
34
|
+
|
|
35
|
+
If you are using an older version of NodeJS (<v11) or Webpack, importing using the above ES6 import will probably fail. You can instead import using CommonJS:
|
|
36
|
+
|
|
37
|
+
```jsx
|
|
38
|
+
const { ChordPixel } = require('@chordcommerce/analytics/dist/cjs')
|
|
39
|
+
```
|
|
40
|
+
|
|
33
41
|
## Configuration
|
|
34
42
|
|
|
35
43
|
`@chordcommerce/analytics` can be initialized with the following options:
|
|
@@ -110,6 +118,46 @@ export const cartFormatter: CartFormatter<StorefrontCart> = (props) => {
|
|
|
110
118
|
}
|
|
111
119
|
```
|
|
112
120
|
|
|
121
|
+
addSourceMiddleware(func: AnalyticsMiddleware)
|
|
122
|
+
|
|
123
|
+
Registers a middleware function to modify event properties before they are
|
|
124
|
+
sent to analytics providers. Middleware functions are executed
|
|
125
|
+
synchronously in the order they were added during event tracking.
|
|
126
|
+
|
|
127
|
+
Parameters
|
|
128
|
+
|
|
129
|
+
- func (AnalyticsMiddleware) - A middleware function that receives event
|
|
130
|
+
data and can return additional properties to merge into the event payload.
|
|
131
|
+
|
|
132
|
+
Return Value
|
|
133
|
+
|
|
134
|
+
The middleware function can return:
|
|
135
|
+
|
|
136
|
+
- Partial<EventProperties> - Properties to merge into the event payload
|
|
137
|
+
- void - No additional properties to add
|
|
138
|
+
|
|
139
|
+
Useage Example
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
analytics.addSourceMiddleware(({ payload }) => {
|
|
143
|
+
const { searchParams } = payload.obj.context.page;
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
utm_source: searchParams.utm_source,
|
|
147
|
+
utm_medium: searchParams.utm_medium,
|
|
148
|
+
utm_campaign: searchParams.utm_campaign
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
analytics.addSourceMiddleware(({ payload }) => {
|
|
153
|
+
return {
|
|
154
|
+
session_id: getSessionId(),
|
|
155
|
+
user_agent: navigator.userAgent,
|
|
156
|
+
timestamp: Date.now()
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
113
161
|
## API Reference
|
|
114
162
|
|
|
115
163
|
See [Chord’s documentation](https://docs.chord.co/api-reference) for a full API reference.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.cdpQueue = exports.addCdpSnippet = void 0;
|
|
40
|
+
var index_js_1 = require("./consent/index.js");
|
|
41
|
+
var utils_js_1 = require("./utils.js");
|
|
42
|
+
/*
|
|
43
|
+
* Adds the Chord CDP snippet to the page.
|
|
44
|
+
*/
|
|
45
|
+
var addCdpSnippet = function (options) { return __awaiter(void 0, void 0, void 0, function () {
|
|
46
|
+
var normalizedCDPDomain, cdpReadyPromise, s;
|
|
47
|
+
return __generator(this, function (_a) {
|
|
48
|
+
switch (_a.label) {
|
|
49
|
+
case 0:
|
|
50
|
+
if (!document || typeof document.createElement === 'undefined')
|
|
51
|
+
return [2 /*return*/];
|
|
52
|
+
normalizedCDPDomain = (0, utils_js_1.normalizeCDPDomain)(options.cdpDomain);
|
|
53
|
+
cdpReadyPromise = new Promise(function (resolve) {
|
|
54
|
+
var checkCdpReady = function () {
|
|
55
|
+
var cdp = window["_".concat(options.namespace)];
|
|
56
|
+
if (cdp && typeof cdp.configure === 'function') {
|
|
57
|
+
resolve();
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
setTimeout(checkCdpReady, 50);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
checkCdpReady();
|
|
64
|
+
});
|
|
65
|
+
s = document.createElement('script');
|
|
66
|
+
s.async = true;
|
|
67
|
+
s.src = "".concat(normalizedCDPDomain, "/p.js");
|
|
68
|
+
s.setAttribute('data-debug', "".concat(!!options.debug));
|
|
69
|
+
s.setAttribute('data-init-only', 'true');
|
|
70
|
+
s.setAttribute('data-namespace', "_".concat(options.namespace));
|
|
71
|
+
s.setAttribute('data-write-key', options.cdpWriteKey);
|
|
72
|
+
document.head.appendChild(s);
|
|
73
|
+
// Wait for CDP to be ready before setting up consent
|
|
74
|
+
return [4 /*yield*/, cdpReadyPromise];
|
|
75
|
+
case 1:
|
|
76
|
+
// Wait for CDP to be ready before setting up consent
|
|
77
|
+
_a.sent();
|
|
78
|
+
if (options.consent) {
|
|
79
|
+
(0, index_js_1.addCdpConsent)(options).init();
|
|
80
|
+
}
|
|
81
|
+
return [2 /*return*/];
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}); };
|
|
85
|
+
exports.addCdpSnippet = addCdpSnippet;
|
|
86
|
+
/*
|
|
87
|
+
* Returns the CDP queue to hold events ahead of CDP initialization.
|
|
88
|
+
*/
|
|
89
|
+
var cdpQueue = function (namespace) {
|
|
90
|
+
var _a;
|
|
91
|
+
var q = window && (window[_a = "_".concat(namespace, "Q")] || (window[_a] = []));
|
|
92
|
+
return {
|
|
93
|
+
track: function () {
|
|
94
|
+
var args = [];
|
|
95
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
96
|
+
args[_i] = arguments[_i];
|
|
97
|
+
}
|
|
98
|
+
return q.push(function (cdp) { return cdp.track.apply(cdp, args); });
|
|
99
|
+
},
|
|
100
|
+
identify: function () {
|
|
101
|
+
var args = [];
|
|
102
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
103
|
+
args[_i] = arguments[_i];
|
|
104
|
+
}
|
|
105
|
+
return q.push(function (cdp) { return cdp.identify.apply(cdp, args); });
|
|
106
|
+
},
|
|
107
|
+
page: function () {
|
|
108
|
+
var args = [];
|
|
109
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
110
|
+
args[_i] = arguments[_i];
|
|
111
|
+
}
|
|
112
|
+
return q.push(function (cdp) { return cdp.page.apply(cdp, args); });
|
|
113
|
+
},
|
|
114
|
+
reset: function () {
|
|
115
|
+
var args = [];
|
|
116
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
117
|
+
args[_i] = arguments[_i];
|
|
118
|
+
}
|
|
119
|
+
return q.push(function (cdp) { return cdp.reset.apply(cdp, args); });
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
exports.cdpQueue = cdpQueue;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ChordAnalyticsOptions, ConsentConfiguration } from '../../types/index.js';
|
|
2
|
+
declare global {
|
|
3
|
+
interface Window {
|
|
4
|
+
jitsuConfig: {
|
|
5
|
+
privacy: ConsentConfiguration;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export declare const addCdpConsent: (options: ChordAnalyticsOptions) => {
|
|
10
|
+
init: () => Promise<boolean>;
|
|
11
|
+
};
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.addCdpConsent = void 0;
|
|
40
|
+
var ketch_js_1 = require("./ketch.js");
|
|
41
|
+
var onetrust_js_1 = require("./onetrust.js");
|
|
42
|
+
var shopify_js_1 = require("./shopify.js");
|
|
43
|
+
var segment_js_1 = require("./segment.js");
|
|
44
|
+
var addCdpConsent = function (options) {
|
|
45
|
+
var adapter = null;
|
|
46
|
+
var lastProcessedConsent = null;
|
|
47
|
+
var POLLING_INTERVAL_MS = 50;
|
|
48
|
+
var TIMEOUT_MS = options.awaitConsentTimeout
|
|
49
|
+
? options.awaitConsentTimeout
|
|
50
|
+
: 60000;
|
|
51
|
+
/**
|
|
52
|
+
* Returns the adapter for the specified consent management platform.
|
|
53
|
+
*/
|
|
54
|
+
var getAdapter = function () {
|
|
55
|
+
var _a;
|
|
56
|
+
switch ((_a = options.consent) === null || _a === void 0 ? void 0 : _a.toLowerCase()) {
|
|
57
|
+
case 'ketch':
|
|
58
|
+
return (0, ketch_js_1.ketchConsentAdapter)();
|
|
59
|
+
case 'onetrust':
|
|
60
|
+
return (0, onetrust_js_1.onetrustConsentAdapter)();
|
|
61
|
+
case 'shopify':
|
|
62
|
+
return (0, shopify_js_1.shopifyConsentAdapter)();
|
|
63
|
+
case 'segment':
|
|
64
|
+
return (0, segment_js_1.segmentConsentAdapter)();
|
|
65
|
+
default:
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Polls if user can be tracked based on consent
|
|
71
|
+
* @returns Promise that resolves to true if condition is met within timeout, false otherwise
|
|
72
|
+
*/
|
|
73
|
+
var checkUserCanBeTracked = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
74
|
+
return __generator(this, function (_a) {
|
|
75
|
+
return [2 /*return*/, new Promise(function (resolve) {
|
|
76
|
+
// Checking immediately first
|
|
77
|
+
if (adapter === null || adapter === void 0 ? void 0 : adapter.userCanBeTracked()) {
|
|
78
|
+
resolve(true);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
var interval = setInterval(function () {
|
|
82
|
+
if (adapter === null || adapter === void 0 ? void 0 : adapter.userCanBeTracked()) {
|
|
83
|
+
clearInterval(interval);
|
|
84
|
+
resolve(true);
|
|
85
|
+
}
|
|
86
|
+
}, POLLING_INTERVAL_MS);
|
|
87
|
+
setTimeout(function () {
|
|
88
|
+
clearInterval(interval);
|
|
89
|
+
resolve(false);
|
|
90
|
+
}, TIMEOUT_MS);
|
|
91
|
+
})];
|
|
92
|
+
});
|
|
93
|
+
}); };
|
|
94
|
+
/**
|
|
95
|
+
* Attempts to configure CDP with retry logic.
|
|
96
|
+
*/
|
|
97
|
+
var configureCdpWithRetry = function (updatedConsent, maxRetries, baseDelay) {
|
|
98
|
+
if (maxRetries === void 0) { maxRetries = 5; }
|
|
99
|
+
if (baseDelay === void 0) { baseDelay = 100; }
|
|
100
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
101
|
+
var attempt, tryConfigure;
|
|
102
|
+
return __generator(this, function (_a) {
|
|
103
|
+
attempt = 0;
|
|
104
|
+
tryConfigure = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
105
|
+
var cdp, delay_1;
|
|
106
|
+
return __generator(this, function (_a) {
|
|
107
|
+
switch (_a.label) {
|
|
108
|
+
case 0:
|
|
109
|
+
cdp = window["_".concat(options.namespace)];
|
|
110
|
+
if (cdp && typeof cdp.configure === 'function') {
|
|
111
|
+
try {
|
|
112
|
+
if (Object.keys(updatedConsent).length > 0) {
|
|
113
|
+
cdp.configure({ privacy: updatedConsent });
|
|
114
|
+
}
|
|
115
|
+
return [2 /*return*/, true];
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
// Continue to retry on error
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (!(attempt < maxRetries)) return [3 /*break*/, 2];
|
|
122
|
+
delay_1 = baseDelay * Math.pow(2, attempt) // Exponential backoff
|
|
123
|
+
;
|
|
124
|
+
return [4 /*yield*/, new Promise(function (resolve) {
|
|
125
|
+
setTimeout(resolve, delay_1);
|
|
126
|
+
})];
|
|
127
|
+
case 1:
|
|
128
|
+
_a.sent();
|
|
129
|
+
attempt++;
|
|
130
|
+
return [2 /*return*/, tryConfigure()];
|
|
131
|
+
case 2:
|
|
132
|
+
console.warn('CDP configuration failed after all retries, falling back to jitsuConfig');
|
|
133
|
+
return [2 /*return*/, false];
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}); };
|
|
137
|
+
return [2 /*return*/, tryConfigure()];
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Updates consent for all future events.
|
|
143
|
+
*/
|
|
144
|
+
var updateCdpConsent = function (updatedConsent) { return __awaiter(void 0, void 0, void 0, function () {
|
|
145
|
+
var chordAnalytics, shouldTrackConsentUpdate, cdpConfigured;
|
|
146
|
+
return __generator(this, function (_a) {
|
|
147
|
+
switch (_a.label) {
|
|
148
|
+
case 0:
|
|
149
|
+
if (lastProcessedConsent &&
|
|
150
|
+
JSON.stringify(lastProcessedConsent) === JSON.stringify(updatedConsent)) {
|
|
151
|
+
return [2 /*return*/];
|
|
152
|
+
}
|
|
153
|
+
lastProcessedConsent = updatedConsent;
|
|
154
|
+
chordAnalytics = window[options.namespace];
|
|
155
|
+
shouldTrackConsentUpdate = chordAnalytics &&
|
|
156
|
+
typeof chordAnalytics.track === 'function' &&
|
|
157
|
+
updatedConsent.consentCategories !== undefined;
|
|
158
|
+
if (!(shouldTrackConsentUpdate &&
|
|
159
|
+
// we have to send this BEFORE the CDP is reconfigured or else the track will not be sent, usually in the case of a user opting out
|
|
160
|
+
updatedConsent.dontSend === true)) return [3 /*break*/, 2];
|
|
161
|
+
return [4 /*yield*/, chordAnalytics.track('Consent Preferences Updated', updatedConsent)];
|
|
162
|
+
case 1:
|
|
163
|
+
_a.sent();
|
|
164
|
+
_a.label = 2;
|
|
165
|
+
case 2: return [4 /*yield*/, configureCdpWithRetry(updatedConsent)];
|
|
166
|
+
case 3:
|
|
167
|
+
cdpConfigured = _a.sent();
|
|
168
|
+
if (!cdpConfigured) {
|
|
169
|
+
// CDP has not yet loaded via the snippet or all retries failed.
|
|
170
|
+
window.jitsuConfig = { privacy: updatedConsent };
|
|
171
|
+
}
|
|
172
|
+
if (!(shouldTrackConsentUpdate &&
|
|
173
|
+
// we have to send this AFTER the CDP is reconfigured to ensure the track is sent, usually in the case of a user opting in
|
|
174
|
+
updatedConsent.dontSend === false)) return [3 /*break*/, 5];
|
|
175
|
+
return [4 /*yield*/, chordAnalytics.track('Consent Preferences Updated', updatedConsent)];
|
|
176
|
+
case 4:
|
|
177
|
+
_a.sent();
|
|
178
|
+
_a.label = 5;
|
|
179
|
+
case 5: return [2 /*return*/];
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}); };
|
|
183
|
+
/**
|
|
184
|
+
* Sets up consent management by initializing the adapter and handling consent updates.
|
|
185
|
+
*/
|
|
186
|
+
var setupConsentManagement = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
187
|
+
var initialConsent;
|
|
188
|
+
return __generator(this, function (_a) {
|
|
189
|
+
switch (_a.label) {
|
|
190
|
+
case 0:
|
|
191
|
+
if (!adapter)
|
|
192
|
+
return [2 /*return*/];
|
|
193
|
+
// Set up the consent update handler first to catch any immediate updates
|
|
194
|
+
adapter.handleConsentUpdates(function (updatedConsent) {
|
|
195
|
+
updateCdpConsent(updatedConsent);
|
|
196
|
+
});
|
|
197
|
+
return [4 /*yield*/, adapter.getCurrentConsent()];
|
|
198
|
+
case 1:
|
|
199
|
+
initialConsent = _a.sent();
|
|
200
|
+
return [4 /*yield*/, updateCdpConsent(initialConsent)];
|
|
201
|
+
case 2:
|
|
202
|
+
_a.sent();
|
|
203
|
+
return [2 /*return*/];
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}); };
|
|
207
|
+
/**
|
|
208
|
+
* Initializes consent management.
|
|
209
|
+
* Returns a promise that resolves to true if CDP should be loaded, false otherwise.
|
|
210
|
+
*/
|
|
211
|
+
var init = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
212
|
+
var canBeTracked;
|
|
213
|
+
return __generator(this, function (_a) {
|
|
214
|
+
switch (_a.label) {
|
|
215
|
+
case 0:
|
|
216
|
+
adapter = getAdapter();
|
|
217
|
+
if (adapter === null) {
|
|
218
|
+
console.error("Consent management adapter \"".concat(options.consent, "\" is not supported."));
|
|
219
|
+
return [2 /*return*/, false];
|
|
220
|
+
}
|
|
221
|
+
if (!options.awaitConsent) return [3 /*break*/, 2];
|
|
222
|
+
return [4 /*yield*/, checkUserCanBeTracked()];
|
|
223
|
+
case 1:
|
|
224
|
+
canBeTracked = _a.sent();
|
|
225
|
+
if (!canBeTracked)
|
|
226
|
+
return [2 /*return*/, false];
|
|
227
|
+
_a.label = 2;
|
|
228
|
+
case 2:
|
|
229
|
+
// Set up consent management in the background
|
|
230
|
+
setupConsentManagement().catch(function (error) {
|
|
231
|
+
console.error('Error setting up consent management:', error);
|
|
232
|
+
});
|
|
233
|
+
return [2 /*return*/, true];
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}); };
|
|
237
|
+
return {
|
|
238
|
+
init: init,
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
exports.addCdpConsent = addCdpConsent;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ConsentConfiguration } from '../../types/index.js';
|
|
2
|
+
declare global {
|
|
3
|
+
interface Window {
|
|
4
|
+
ketch?: (action: string, eventName: string, handler: () => void) => undefined;
|
|
5
|
+
ketchConsent?: KetchConsentCategories;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
interface KetchConsentCategories {
|
|
9
|
+
[key: string]: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare const ketchConsentAdapter: () => {
|
|
12
|
+
getCurrentConsent: () => ConsentConfiguration;
|
|
13
|
+
handleConsentUpdates: (updateCdpConsent: (consent: ConsentConfiguration) => void) => void;
|
|
14
|
+
userCanBeTracked: () => boolean;
|
|
15
|
+
};
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.ketchConsentAdapter = void 0;
|
|
15
|
+
/**
|
|
16
|
+
* Returns Ketch's consent categories.
|
|
17
|
+
*/
|
|
18
|
+
var getApi = function () { return window.ketch && window.ketchConsent; };
|
|
19
|
+
/**
|
|
20
|
+
* Returns whether the user can currently be tracked.
|
|
21
|
+
*/
|
|
22
|
+
var userCanBeTracked = function () {
|
|
23
|
+
var api = getApi();
|
|
24
|
+
return !!api && !!Object.keys(api).length;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Returns the user's current consent configuration.
|
|
28
|
+
*/
|
|
29
|
+
var getCurrentConsent = function () {
|
|
30
|
+
var api = getApi();
|
|
31
|
+
if (!api)
|
|
32
|
+
return {};
|
|
33
|
+
return {
|
|
34
|
+
consentCategories: __assign({}, api),
|
|
35
|
+
dontSend: !userCanBeTracked(),
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Handles subsequent changes to consent configuration.
|
|
40
|
+
*/
|
|
41
|
+
var handleConsentUpdates = function (updateCdpConsent) {
|
|
42
|
+
window.ketch('addListener', 'consent', function () {
|
|
43
|
+
updateCdpConsent(getCurrentConsent());
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
var ketchConsentAdapter = function () {
|
|
47
|
+
return {
|
|
48
|
+
getCurrentConsent: getCurrentConsent,
|
|
49
|
+
handleConsentUpdates: handleConsentUpdates,
|
|
50
|
+
userCanBeTracked: userCanBeTracked,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
exports.ketchConsentAdapter = ketchConsentAdapter;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ConsentConfiguration } from '../../types/index.js';
|
|
2
|
+
declare global {
|
|
3
|
+
interface Window {
|
|
4
|
+
OneTrust?: OneTrustApi;
|
|
5
|
+
OnetrustActiveGroups?: string;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
interface OneTrustApi {
|
|
9
|
+
OnConsentChanged: (callback: () => void) => void;
|
|
10
|
+
GetDomainData: () => {
|
|
11
|
+
Groups: OneTrustGroup[];
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
interface OneTrustGroup {
|
|
15
|
+
CustomGroupId: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const onetrustConsentAdapter: () => {
|
|
18
|
+
getCurrentConsent: () => ConsentConfiguration;
|
|
19
|
+
handleConsentUpdates: (updateCdpConsent: (consent: ConsentConfiguration) => void) => void;
|
|
20
|
+
userCanBeTracked: () => boolean;
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.onetrustConsentAdapter = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Returns OneTrust's API.
|
|
6
|
+
*/
|
|
7
|
+
var getApi = function () {
|
|
8
|
+
var oneTrust = window.OneTrust;
|
|
9
|
+
if (oneTrust &&
|
|
10
|
+
typeof oneTrust === 'object' &&
|
|
11
|
+
'OnConsentChanged' in oneTrust &&
|
|
12
|
+
'GetDomainData' in oneTrust) {
|
|
13
|
+
return oneTrust;
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Returns whether the user can currently be tracked.
|
|
19
|
+
*/
|
|
20
|
+
var userCanBeTracked = function () {
|
|
21
|
+
// Always loads, a la `consentModel: 'opt-out'` in the Segment wrapper.
|
|
22
|
+
var api = getApi();
|
|
23
|
+
return !!api;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Returns the user's current consent configuration.
|
|
27
|
+
*/
|
|
28
|
+
var getCurrentConsent = function () {
|
|
29
|
+
var api = getApi();
|
|
30
|
+
var activeGroups = window.OnetrustActiveGroups;
|
|
31
|
+
if (!api || !activeGroups || typeof activeGroups !== 'string')
|
|
32
|
+
return {};
|
|
33
|
+
var activeGroupIds = new Set(activeGroups.trim().split(',').filter(Boolean));
|
|
34
|
+
return {
|
|
35
|
+
consentCategories: api
|
|
36
|
+
.GetDomainData()
|
|
37
|
+
.Groups.reduce(function (acc, _a) {
|
|
38
|
+
var CustomGroupId = _a.CustomGroupId;
|
|
39
|
+
var groupId = CustomGroupId.trim();
|
|
40
|
+
acc[groupId] = activeGroupIds.has(groupId);
|
|
41
|
+
return acc;
|
|
42
|
+
}, {}),
|
|
43
|
+
dontSend: !userCanBeTracked(),
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Handles subsequent changes to consent configuration.
|
|
48
|
+
*/
|
|
49
|
+
var handleConsentUpdates = function (updateCdpConsent) {
|
|
50
|
+
getApi().OnConsentChanged(function () {
|
|
51
|
+
updateCdpConsent(getCurrentConsent());
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
var onetrustConsentAdapter = function () {
|
|
55
|
+
return {
|
|
56
|
+
getCurrentConsent: getCurrentConsent,
|
|
57
|
+
handleConsentUpdates: handleConsentUpdates,
|
|
58
|
+
userCanBeTracked: userCanBeTracked,
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
exports.onetrustConsentAdapter = onetrustConsentAdapter;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ConsentConfiguration } from '../../types/index.js';
|
|
2
|
+
declare global {
|
|
3
|
+
interface Window {
|
|
4
|
+
segmentConsent?: SegmentConsentCategories;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
interface SegmentConsentCategories {
|
|
8
|
+
[key: string]: {
|
|
9
|
+
[key: string]: boolean;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export declare const segmentConsentAdapter: () => {
|
|
13
|
+
getCurrentConsent: () => Promise<ConsentConfiguration>;
|
|
14
|
+
handleConsentUpdates: (updateCdpConsent: (consent: ConsentConfiguration) => void) => void;
|
|
15
|
+
userCanBeTracked: () => Promise<boolean>;
|
|
16
|
+
};
|
|
17
|
+
export {};
|