@blotoutio/edgetag-sdk-browser 0.51.0 → 0.52.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.
Files changed (2) hide show
  1. package/index.js +626 -490
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -16,11 +16,174 @@
16
16
  get user () { return user; }
17
17
  });
18
18
 
19
- const _config = {};
20
- const setConfig$1 = (config) => {
21
- Object.assign(_config, config);
19
+ const isBool = (v) => typeof v == 'boolean';
20
+ const isRecord = (v) => !!v && typeof v == 'object' && !Array.isArray(v);
21
+ /**
22
+ * This function validates user consent for a given provider and tag name.
23
+ * It should be used in conjunction with `UserConsent`, not `ProvidersConfig`.
24
+ */
25
+ const hasUserConsent = (consent, provider, tagName) => {
26
+ if (!isRecord(consent)) {
27
+ return false;
28
+ }
29
+ let allowed = isBool(consent.all) ? consent.all : false;
30
+ if (provider in consent) {
31
+ const providerSpecific = consent[provider];
32
+ if (isBool(providerSpecific)) {
33
+ allowed = providerSpecific;
34
+ }
35
+ else if (isRecord(providerSpecific)) {
36
+ if ('all' in providerSpecific && isBool(providerSpecific.all)) {
37
+ allowed = providerSpecific.all;
38
+ }
39
+ if (tagName in providerSpecific && isBool(providerSpecific[tagName])) {
40
+ allowed = providerSpecific[tagName];
41
+ }
42
+ }
43
+ }
44
+ return allowed;
45
+ };
46
+ /**
47
+ * This function validates user consent for a given provider type, not based on tagName.
48
+ */
49
+ const hasUserConsentForProvider = (consent, provider) => {
50
+ if (!isRecord(consent)) {
51
+ return false;
52
+ }
53
+ let allowed = isBool(consent.all) ? consent.all : false;
54
+ if (provider in consent) {
55
+ const providerSpecific = consent[provider];
56
+ if (isBool(providerSpecific)) {
57
+ allowed = providerSpecific;
58
+ }
59
+ else if (isRecord(providerSpecific)) {
60
+ return Object.keys(providerSpecific).some((instance) => providerSpecific[instance] === true);
61
+ }
62
+ }
63
+ return allowed;
64
+ };
65
+ /**
66
+ * This function validates provider allowance for a given provider and tag name.
67
+ * It should not be used to validate `UserConsent`.
68
+ */
69
+ const isProviderInstanceAllowed = (providersConfig, provider, tagName) => {
70
+ if (!isRecord(providersConfig)) {
71
+ return true;
72
+ }
73
+ if (provider in providersConfig) {
74
+ const providerSpecific = providersConfig[provider];
75
+ if (isBool(providerSpecific)) {
76
+ return providerSpecific;
77
+ }
78
+ if (isRecord(providerSpecific)) {
79
+ const tagKeys = Object.keys(providerSpecific).filter((k) => k != 'all');
80
+ if (tagName in providerSpecific && isBool(providerSpecific[tagName])) {
81
+ return providerSpecific[tagName];
82
+ }
83
+ return isBool(providerSpecific.all)
84
+ ? providerSpecific.all
85
+ : tagKeys.length == 0;
86
+ }
87
+ }
88
+ const providerKeys = Object.keys(providersConfig).filter((k) => k != 'all');
89
+ return isBool(providersConfig.all)
90
+ ? providersConfig.all
91
+ : providerKeys.length == 0;
92
+ };
93
+
94
+ const upsert = (map, key, update, createDefault) => {
95
+ const currentValue = map.has(key)
96
+ ? map.get(key)
97
+ : createDefault();
98
+ return map.set(key, update(currentValue));
99
+ };
100
+
101
+ const expand = (str) => str.split(',').flatMap((entry) => {
102
+ if (!entry.includes('-')) {
103
+ return entry;
104
+ }
105
+ const result = [];
106
+ const [start, end] = entry.split('-').map(Number);
107
+ for (let i = start; i <= end; i++) {
108
+ result.push(i.toString());
109
+ }
110
+ return result;
111
+ });
112
+ /**
113
+ * Exported from https://en.wikipedia.org/wiki/List_of_North_American_Numbering_Plan_area_codes
114
+ *
115
+ * In Dev Tools, select the `tbody` element containing the area codes and run the following code,
116
+ * replacing the emdash character with a simple endash:
117
+ *
118
+ * ```ts
119
+ * [...$0.querySelectorAll('td:first-child')]
120
+ * .filter(cell => cell.firstChild.nodeName != 'A')
121
+ * .map(cell => cell.textContent.trim()).join(',')
122
+ * ```
123
+ */
124
+ new Set([
125
+ ...expand('200,211,221,222,230,232,233,235,237-238,241,243,244,245,247,255,257,258-259,261,265,266,271,273,274,275,277,278,280,282,283,285-287,288,290-299'),
126
+ ...expand('300,311,322,324,327,328,333,335,338,342,344,348-349,353,355,356,357-359,362,366,369,370-379,381,382,383-384,387,388,389,390-399'),
127
+ ...expand('400,411,420,421-422,426-427,428,429,433,439,444,446,449,451-454,455,456,457,459,460,461-462,465,466,467,471,476,477,481-483,485-486,487,488,489,490-499'),
128
+ ...expand('511,532,535,536,537,538,542-543,545-547,549-550,552-554,555,556,558,560,565,568,569,576,578,583,589,590-599'),
129
+ ...expand('611,621,624,625,627,632,633,634-635,637-638,642-643,644,648,652-654,655,663,665,666,668,673-676,677,679,685,686,687,688,690-699'),
130
+ ...expand('711,722,723,729,733,735-736,739,741,744,745-746,748,749-751,752,755,756,759,761,764,766,768,776,777,783,788,789,790-799'),
131
+ ...expand('811,821,822,823-824,827,834,836,841-842,846,851,852-853,871,874-875,879,880-887,889,890-899'),
132
+ ...expand('911,921,922,923,924,926,927,932,933,935,942,944,946,950,953,955,957-958,960-969,974,975,976,977,981-982,987,988,990-999'),
133
+ ]);
134
+
135
+ // eslint-disable-next-line @nx/enforce-module-boundaries
136
+ let edgeTagSettings;
137
+ const initSettings = (destination, options) => {
138
+ if (!edgeTagSettings) {
139
+ edgeTagSettings = {};
140
+ }
141
+ edgeTagSettings[destination] = {
142
+ destination,
143
+ initialized: false,
144
+ stubs: [],
145
+ channels: new Map(),
146
+ ...options,
147
+ };
148
+ };
149
+ const setSetting = (options, destination) => {
150
+ if (!edgeTagSettings) {
151
+ return;
152
+ }
153
+ if (!destination) {
154
+ Object.keys(edgeTagSettings).forEach((key) => {
155
+ edgeTagSettings[key] = {
156
+ ...edgeTagSettings[key],
157
+ ...options,
158
+ };
159
+ });
160
+ return;
161
+ }
162
+ edgeTagSettings[destination] = {
163
+ ...edgeTagSettings[destination],
164
+ ...options,
165
+ };
166
+ };
167
+ const getSetting = (destination, key) => {
168
+ var _a;
169
+ return (_a = edgeTagSettings === null || edgeTagSettings === void 0 ? void 0 : edgeTagSettings[destination]) === null || _a === void 0 ? void 0 : _a[key];
170
+ };
171
+ const getInstances = () => {
172
+ return Object.keys(edgeTagSettings || {});
173
+ };
174
+ const addChannel = (destination, pkg, tagName) => upsert(getSetting(destination, 'channels'), pkg, (names) => names.add(tagName), () => new Set());
175
+ const getProviderVariables = (destination, packageId) => {
176
+ const setting = getSetting(destination, 'packages');
177
+ if (!setting) {
178
+ return [];
179
+ }
180
+ return (setting
181
+ .filter((pkg) => pkg.package === packageId)
182
+ .map((pkg) => ({
183
+ tagName: pkg.tagName,
184
+ variableSet: pkg.variables || {},
185
+ })) || []);
22
186
  };
23
- const getConfig = () => _config;
24
187
 
25
188
  const getUserAgent = () => {
26
189
  try {
@@ -31,11 +194,11 @@
31
194
  return '';
32
195
  }
33
196
  };
34
- const getReferrer = () => {
197
+ const getReferrer = (destination) => {
35
198
  let referrer = '';
36
199
  try {
37
200
  const referrerUrl = new URL(document.referrer);
38
- const pageUrl = new URL(getPageUrl());
201
+ const pageUrl = new URL(getPageUrl(destination));
39
202
  if (referrerUrl.host !== pageUrl.host) {
40
203
  referrer = referrerUrl.href;
41
204
  }
@@ -45,22 +208,22 @@
45
208
  return referrer;
46
209
  }
47
210
  };
48
- const getPageUrl = () => {
211
+ const getPageUrl = (destination) => {
49
212
  try {
50
213
  // we need to leave this one in for existing Custom pixel customers
51
214
  if (window.edgetagData && window.edgetagData['pageUrl']) {
52
215
  return window.edgetagData['pageUrl'];
53
216
  }
54
- const { pageUrl } = getConfig();
55
- return pageUrl || window.location.href;
217
+ const config = getSetting(destination, 'config');
218
+ return (config === null || config === void 0 ? void 0 : config.pageUrl) || window.location.href;
56
219
  }
57
220
  catch {
58
221
  return '';
59
222
  }
60
223
  };
61
- const getSearch = () => {
224
+ const getSearch = (destination) => {
62
225
  try {
63
- return new URL(getPageUrl()).search;
226
+ return new URL(getPageUrl(destination)).search;
64
227
  }
65
228
  catch {
66
229
  return '';
@@ -113,7 +276,6 @@
113
276
  const tagStorage = 'edgeTag';
114
277
  const consentKey = 'consent';
115
278
  const keyPrefix = `_worker`;
116
- const cookieKey = 'tag_user_id';
117
279
 
118
280
  const getMessage = (error) => {
119
281
  if (error instanceof Error) {
@@ -147,9 +309,9 @@
147
309
  console.error('[EdgeTag]', getMessage(data));
148
310
  };
149
311
 
150
- const initKey = `${keyPrefix}Store`;
151
- const saveDataPerKey = (persistType, provider, value, key) => {
152
- const storage = getData$1(persistType);
312
+ const initKey = `${keyPrefix}StoreMultiple`;
313
+ const saveDataPerKey = (destination, persistType, provider, value, key) => {
314
+ const storage = getData$1(destination, persistType);
153
315
  if (!storage['data']) {
154
316
  storage['data'] = {};
155
317
  }
@@ -157,49 +319,54 @@
157
319
  storage['data'][provider] = {};
158
320
  }
159
321
  storage['data'][provider][key] = value;
160
- saveData(persistType, storage);
322
+ saveData(destination, persistType, storage);
323
+ };
324
+ const saveKV = (destination, data) => {
325
+ const currentSession = getData$1(destination, 'session');
326
+ if (!currentSession['kv']) {
327
+ currentSession['kv'] = {};
328
+ }
329
+ currentSession['kv'] = {
330
+ ...currentSession['kv'],
331
+ ...data,
332
+ };
333
+ saveData(destination, 'session', currentSession);
161
334
  };
162
- const savePerKey = (persistType, provider, value, key) => {
163
- const storage = getData$1(persistType);
335
+ const savePerKey = (destination, persistType, provider, value, key) => {
336
+ const storage = getData$1(destination, persistType);
164
337
  if (!storage[provider]) {
165
338
  storage[provider] = {};
166
339
  }
167
340
  storage[provider][key] = value;
168
- saveData(persistType, storage);
341
+ saveData(destination, persistType, storage);
169
342
  };
170
- const getDataPerKey = (persistType, provider, key) => {
171
- const storage = getData$1(persistType);
343
+ const getDataPerKey = (destination, persistType, provider, key) => {
344
+ const storage = getData$1(destination, persistType);
172
345
  if (!storage[provider]) {
173
346
  return undefined;
174
347
  }
175
348
  return storage[provider][key];
176
349
  };
177
- const saveData = (persistType, value, key = initKey) => {
350
+ const saveData = (destination, persistType, value, key = initKey) => {
178
351
  if (persistType === 'session') {
179
- saveSession(value, key);
352
+ const data = getSession(key);
353
+ data[destination] = value;
354
+ saveSession(data, key);
180
355
  return;
181
356
  }
182
- saveLocal(value, key);
357
+ const data = getLocal(key);
358
+ data[destination] = value;
359
+ saveLocal(data, key);
183
360
  };
184
- const getData$1 = (persistType, key = initKey) => {
361
+ const getData$1 = (destination, persistType, key = initKey) => {
362
+ let data;
185
363
  if (persistType === 'session') {
186
- return getSession(key);
364
+ data = getSession(key);
187
365
  }
188
- return getLocal(key);
189
- };
190
- const saveKV = (data) => {
191
- let currentSession = getData$1('session');
192
- if (!currentSession) {
193
- currentSession = {};
194
- }
195
- if (!currentSession['kv']) {
196
- currentSession['kv'] = {};
366
+ else {
367
+ data = getLocal(key);
197
368
  }
198
- currentSession['kv'] = {
199
- ...currentSession['kv'],
200
- ...data,
201
- };
202
- saveData('session', currentSession);
369
+ return (data === null || data === void 0 ? void 0 : data[destination]) || {};
203
370
  };
204
371
  const saveLocal = (value, key) => {
205
372
  try {
@@ -254,85 +421,19 @@
254
421
  }
255
422
  };
256
423
 
257
- const encodeString = (name) => {
258
- if (typeof btoa === 'undefined') {
259
- return Buffer.from(name).toString('base64');
260
- }
261
- return btoa(name);
262
- };
263
- const getBasicRandomNumber = () => {
264
- return parseInt((Math.random() * 10000000000).toString(), 10);
424
+ const getUserId$1 = (destination) => {
425
+ return getSetting(destination, 'userId');
265
426
  };
266
- const generateUUID = () => {
267
- let id = '';
268
- try {
269
- id = crypto.randomUUID();
270
- if (!id) {
271
- const array = new Uint32Array(20);
272
- const numbers = crypto.getRandomValues(array);
273
- for (let i = 0; i < 5; i++) {
274
- const y = i * 3;
275
- if (i !== 0) {
276
- id += '-';
277
- }
278
- const sum = numbers[y + 1] + numbers[y + 2] + numbers[y + 3];
279
- id += sum.toString();
280
- }
281
- }
427
+ const handleGetUserId = (options) => {
428
+ if (options === null || options === void 0 ? void 0 : options.destination) {
429
+ return getUserId$1(options.destination);
282
430
  }
283
- catch {
284
- id = `${getBasicRandomNumber()}-${getBasicRandomNumber()}-${getBasicRandomNumber()}-${getBasicRandomNumber()}-${getBasicRandomNumber()}`;
285
- console.log('[EdgeTag] Crypto module not found');
431
+ const instances = getInstances();
432
+ if (instances.length > 1) {
433
+ error('Multiple instances detected! Please provide a destination.');
434
+ return null;
286
435
  }
287
- return id;
288
- };
289
- const generateEventId = (name) => {
290
- let time = Date.now().toString();
291
- if (typeof performance !== 'undefined' &&
292
- typeof performance.now === 'function') {
293
- const perf = performance.now();
294
- if (perf) {
295
- time = perf.toFixed(4);
296
- }
297
- }
298
- return `${encodeString(name)}-${generateUUID()}-${time}`;
299
- };
300
-
301
- const getCookieValue = (key) => {
302
- try {
303
- if (!document || !document.cookie) {
304
- return '';
305
- }
306
- const name = `${key}=`;
307
- const decodedCookie = decodeURIComponent(document.cookie);
308
- const ca = decodedCookie.split(';');
309
- for (let i = 0; i < ca.length; i++) {
310
- let c = ca[i];
311
- while (c.charAt(0) === ' ') {
312
- c = c.substring(1);
313
- }
314
- if (c.indexOf(name) === 0) {
315
- return c.substring(name.length, c.length);
316
- }
317
- }
318
- return '';
319
- }
320
- catch {
321
- return '';
322
- }
323
- };
324
-
325
- let initUserId = '';
326
- const handleGetUserId = () => {
327
- if (initUserId) {
328
- return initUserId;
329
- }
330
- // leaving this for backward compatibility as worker was maybe not updated yet
331
- // reference https://github.com/blotoutio/solutions/issues/1960
332
- return getCookieValue(cookieKey);
333
- };
334
- const setUserId = (userId) => {
335
- initUserId = userId;
436
+ return getUserId$1(instances[0]);
336
437
  };
337
438
 
338
439
  const beacon = (url, payload) => {
@@ -347,12 +448,12 @@
347
448
  return Promise.reject(new Error('Beacon not supported.'));
348
449
  }
349
450
  };
350
- const ajax = (method, url, payload) => fetch(url, {
451
+ const ajax = (destination, method, url, payload) => fetch(url, {
351
452
  method,
352
453
  headers: {
353
454
  'Content-type': 'application/json; charset=utf-8',
354
455
  Accept: 'application/json; charset=utf-8',
355
- EdgeTagUserId: handleGetUserId(),
456
+ EdgeTagUserId: getUserId$1(destination),
356
457
  },
357
458
  body: JSON.stringify(payload),
358
459
  credentials: 'include',
@@ -366,26 +467,26 @@
366
467
  }
367
468
  return Promise.resolve(body);
368
469
  });
369
- const getStandardPayload = (payload) => {
470
+ const getStandardPayload = (destination, payload) => {
370
471
  const data = {
371
- pageUrl: getPageUrl(),
472
+ pageUrl: getPageUrl(destination),
372
473
  pageTitle: getPageTitle(),
373
474
  userAgent: getUserAgent(),
374
- referrer: getReferrer(),
375
- search: getSearch(),
475
+ referrer: getReferrer(destination),
476
+ search: getSearch(destination),
376
477
  locale: getLocale(),
377
- sdkVersion: "0.51.0" ,
478
+ sdkVersion: "0.52.0" ,
378
479
  ...(payload || {}),
379
480
  };
380
481
  let storage = {};
381
- const session = getData$1('session');
482
+ const session = getData$1(destination, 'session');
382
483
  if (session) {
383
484
  storage = {
384
485
  ...storage,
385
486
  ...session,
386
487
  };
387
488
  }
388
- const local = getData$1('local');
489
+ const local = getData$1(destination, 'local');
389
490
  if (local) {
390
491
  storage = {
391
492
  ...storage,
@@ -399,11 +500,13 @@
399
500
  if (!url) {
400
501
  return Promise.reject(new Error('URL is empty.'));
401
502
  }
402
- const payload = getStandardPayload(data);
503
+ const parsedUrl = new URL(url);
504
+ const destination = parsedUrl.origin;
505
+ const payload = getStandardPayload(destination, data);
403
506
  if (options && options.method === 'beacon') {
404
507
  return Promise.resolve(beacon(url, payload));
405
508
  }
406
- return await ajax('POST', url, payload);
509
+ return await ajax(destination, 'POST', url, payload);
407
510
  }
408
511
  async function getRequest(url, options) {
409
512
  if (!url) {
@@ -414,170 +517,44 @@
414
517
  result: Promise.resolve(beacon(url)),
415
518
  };
416
519
  }
417
- return await ajax('GET', url);
520
+ const parsedUrl = new URL(url);
521
+ const destination = parsedUrl.origin;
522
+ return await ajax(destination, 'GET', url);
418
523
  }
419
524
 
420
- let endpointUrl = '';
421
- const generateUrl = (path) => {
422
- const endpoint = getUrl();
423
- if (!endpoint) {
525
+ const generateUrl = (destination, path) => {
526
+ if (!destination) {
424
527
  log('URL is not valid');
425
528
  return '';
426
529
  }
427
- return `${endpoint}${path}`;
428
- };
429
- const getUrl = () => {
430
- return endpointUrl;
530
+ return `${destination}${path}`;
431
531
  };
432
- const setUrl = (url) => {
433
- if (url == null) {
434
- return;
435
- }
436
- endpointUrl = url;
437
- };
438
- const getTagURL = (options) => {
439
- const url = new URL(generateUrl('/tag'));
532
+ const getTagURL = (destination, options) => {
533
+ const parsedUrl = new URL(generateUrl(destination, '/tag'));
440
534
  if (options === null || options === void 0 ? void 0 : options.sync) {
441
- url.searchParams.set('sync', 'true');
535
+ parsedUrl.searchParams.set('sync', 'true');
442
536
  }
443
- return url.toString();
537
+ return parsedUrl.toString();
444
538
  };
445
- const getInitURL = () => {
446
- return generateUrl('/init');
539
+ const getInitURL = (destination) => {
540
+ return generateUrl(destination, '/init');
447
541
  };
448
- const getConsentURL = () => {
449
- return generateUrl('/consent');
542
+ const getConsentURL = (destination) => {
543
+ return generateUrl(destination, '/consent');
450
544
  };
451
- const getUserURL = () => {
452
- return generateUrl('/user');
545
+ const getUserURL = (destination) => {
546
+ return generateUrl(destination, '/user');
453
547
  };
454
- const getDataURL = () => {
455
- return generateUrl(`/data`);
548
+ const getDataURL = (destination) => {
549
+ return generateUrl(destination, `/data`);
456
550
  };
457
- const getGetDataURL = (keys) => {
458
- return generateUrl(`/data?keys=${encodeURIComponent(keys.join(','))}`);
551
+ const getGetDataURL = (destination, keys) => {
552
+ return generateUrl(destination, `/data?keys=${encodeURIComponent(keys.join(','))}`);
459
553
  };
460
- const getKeysURL = () => {
461
- return generateUrl(`/keys`);
554
+ const getKeysURL = (destination) => {
555
+ return generateUrl(destination, `/keys`);
462
556
  };
463
557
 
464
- const isBool = (v) => typeof v == 'boolean';
465
- const isRecord = (v) => !!v && typeof v == 'object' && !Array.isArray(v);
466
- /**
467
- * This function validates user consent for a given provider and tag name.
468
- * It should be used in conjunction with `UserConsent`, not `ProvidersConfig`.
469
- */
470
- const hasUserConsent = (consent, provider, tagName) => {
471
- if (!isRecord(consent)) {
472
- return false;
473
- }
474
- let allowed = isBool(consent.all) ? consent.all : false;
475
- if (provider in consent) {
476
- const providerSpecific = consent[provider];
477
- if (isBool(providerSpecific)) {
478
- allowed = providerSpecific;
479
- }
480
- else if (isRecord(providerSpecific)) {
481
- if ('all' in providerSpecific && isBool(providerSpecific.all)) {
482
- allowed = providerSpecific.all;
483
- }
484
- if (tagName in providerSpecific && isBool(providerSpecific[tagName])) {
485
- allowed = providerSpecific[tagName];
486
- }
487
- }
488
- }
489
- return allowed;
490
- };
491
- /**
492
- * This function validates user consent for a given provider type, not based on tagName.
493
- */
494
- const hasUserConsentForProvider = (consent, provider) => {
495
- if (!isRecord(consent)) {
496
- return false;
497
- }
498
- let allowed = isBool(consent.all) ? consent.all : false;
499
- if (provider in consent) {
500
- const providerSpecific = consent[provider];
501
- if (isBool(providerSpecific)) {
502
- allowed = providerSpecific;
503
- }
504
- else if (isRecord(providerSpecific)) {
505
- return Object.keys(providerSpecific).some((instance) => providerSpecific[instance] === true);
506
- }
507
- }
508
- return allowed;
509
- };
510
- /**
511
- * This function validates provider allowance for a given provider and tag name.
512
- * It should not be used to validate `UserConsent`.
513
- */
514
- const isProviderInstanceAllowed = (providersConfig, provider, tagName) => {
515
- if (!isRecord(providersConfig)) {
516
- return true;
517
- }
518
- if (provider in providersConfig) {
519
- const providerSpecific = providersConfig[provider];
520
- if (isBool(providerSpecific)) {
521
- return providerSpecific;
522
- }
523
- if (isRecord(providerSpecific)) {
524
- const tagKeys = Object.keys(providerSpecific).filter((k) => k != 'all');
525
- if (tagName in providerSpecific && isBool(providerSpecific[tagName])) {
526
- return providerSpecific[tagName];
527
- }
528
- return isBool(providerSpecific.all)
529
- ? providerSpecific.all
530
- : tagKeys.length == 0;
531
- }
532
- }
533
- const providerKeys = Object.keys(providersConfig).filter((k) => k != 'all');
534
- return isBool(providersConfig.all)
535
- ? providersConfig.all
536
- : providerKeys.length == 0;
537
- };
538
-
539
- const upsert = (map, key, update, createDefault) => {
540
- const currentValue = map.has(key)
541
- ? map.get(key)
542
- : createDefault();
543
- return map.set(key, update(currentValue));
544
- };
545
-
546
- const expand = (str) => str.split(',').flatMap((entry) => {
547
- if (!entry.includes('-')) {
548
- return entry;
549
- }
550
- const result = [];
551
- const [start, end] = entry.split('-').map(Number);
552
- for (let i = start; i <= end; i++) {
553
- result.push(i.toString());
554
- }
555
- return result;
556
- });
557
- /**
558
- * Exported from https://en.wikipedia.org/wiki/List_of_North_American_Numbering_Plan_area_codes
559
- *
560
- * In Dev Tools, select the `tbody` element containing the area codes and run the following code,
561
- * replacing the emdash character with a simple endash:
562
- *
563
- * ```ts
564
- * [...$0.querySelectorAll('td:first-child')]
565
- * .filter(cell => cell.firstChild.nodeName != 'A')
566
- * .map(cell => cell.textContent.trim()).join(',')
567
- * ```
568
- */
569
- new Set([
570
- ...expand('200,211,221,222,230,232,233,235,237-238,241,243,244,245,247,255,257,258-259,261,265,266,271,273,274,275,277,278,280,282,283,285-287,288,290-299'),
571
- ...expand('300,311,322,324,327,328,333,335,338,342,344,348-349,353,355,356,357-359,362,366,369,370-379,381,382,383-384,387,388,389,390-399'),
572
- ...expand('400,411,420,421-422,426-427,428,429,433,439,444,446,449,451-454,455,456,457,459,460,461-462,465,466,467,471,476,477,481-483,485-486,487,488,489,490-499'),
573
- ...expand('511,532,535,536,537,538,542-543,545-547,549-550,552-554,555,556,558,560,565,568,569,576,578,583,589,590-599'),
574
- ...expand('611,621,624,625,627,632,633,634-635,637-638,642-643,644,648,652-654,655,663,665,666,668,673-676,677,679,685,686,687,688,690-699'),
575
- ...expand('711,722,723,729,733,735-736,739,741,744,745-746,748,749-751,752,755,756,759,761,764,766,768,776,777,783,788,789,790-799'),
576
- ...expand('811,821,822,823-824,827,834,836,841-842,846,851,852-853,871,874-875,879,880-887,889,890-899'),
577
- ...expand('911,921,922,923,924,926,927,932,933,935,942,944,946,950,953,955,957-958,960-969,974,975,976,977,981-982,987,988,990-999'),
578
- ]);
579
-
580
- let initialized = false;
581
558
  const providersPackages = {};
582
559
  const setPreferences = (preferences) => {
583
560
  var _a;
@@ -588,7 +565,6 @@
588
565
  error('Please provide URL for EdgeTag');
589
566
  return false;
590
567
  }
591
- !!preferences.disableConsentCheck;
592
568
  (_a = preferences.providers) === null || _a === void 0 ? void 0 : _a.forEach((provider) => {
593
569
  if (!provider.name) {
594
570
  return;
@@ -608,52 +584,122 @@
608
584
  catch {
609
585
  // do nothing
610
586
  }
611
- setUrl(preferences.edgeURL);
587
+ initSettings(preferences.edgeURL, {
588
+ disableConsent: !!preferences.disableConsentCheck,
589
+ });
612
590
  return true;
613
591
  };
614
- const getProvidersPackage = () => providersPackages;
615
- const isInitialized = () => initialized;
616
- const setInitialized = () => {
617
- initialized = true;
592
+ const getProvidersPackage = (destination) => {
593
+ const packages = getSetting(destination, 'packages');
594
+ const providers = [];
595
+ packages === null || packages === void 0 ? void 0 : packages.forEach((pkg) => {
596
+ const provider = providersPackages[pkg.package];
597
+ if (!provider) {
598
+ return;
599
+ }
600
+ providers.push(provider);
601
+ });
602
+ return providers;
618
603
  };
619
- const configuredTags = new Map();
620
- const addConfiguredTag = (pkg, tagName) => upsert(configuredTags, pkg, (names) => names.add(tagName), () => new Set());
621
- const getConfiguredTags = () => configuredTags;
622
604
 
623
- const manifestVariables = {};
624
- const addProviderVariable = (name, variables, tagName) => {
625
- manifestVariables[name] = {
626
- ...manifestVariables[name],
627
- [tagName]: variables || {},
628
- };
605
+ const encodeString = (name) => {
606
+ if (typeof btoa === 'undefined') {
607
+ return Buffer.from(name).toString('base64');
608
+ }
609
+ return btoa(name);
629
610
  };
630
- const getProviderVariables = (name) => {
631
- if (!name) {
632
- return {};
611
+ const getBasicRandomNumber = () => {
612
+ return parseInt((Math.random() * 10000000000).toString(), 10);
613
+ };
614
+ const generateUUID = () => {
615
+ let id = '';
616
+ try {
617
+ id = crypto.randomUUID();
618
+ if (!id) {
619
+ const array = new Uint32Array(20);
620
+ const numbers = crypto.getRandomValues(array);
621
+ for (let i = 0; i < 5; i++) {
622
+ const y = i * 3;
623
+ if (i !== 0) {
624
+ id += '-';
625
+ }
626
+ const sum = numbers[y + 1] + numbers[y + 2] + numbers[y + 3];
627
+ id += sum.toString();
628
+ }
629
+ }
633
630
  }
634
- return manifestVariables[name] || {};
631
+ catch {
632
+ id = `${getBasicRandomNumber()}-${getBasicRandomNumber()}-${getBasicRandomNumber()}-${getBasicRandomNumber()}-${getBasicRandomNumber()}`;
633
+ console.log('[EdgeTag] Crypto module not found');
634
+ }
635
+ return id;
636
+ };
637
+ const generateEventId = (name) => {
638
+ let time = Date.now().toString();
639
+ if (typeof performance !== 'undefined' &&
640
+ typeof performance.now === 'function') {
641
+ const perf = performance.now();
642
+ if (perf) {
643
+ time = perf.toFixed(4);
644
+ }
645
+ }
646
+ return `${encodeString(name)}-${generateUUID()}-${time}`;
635
647
  };
636
648
 
637
- let stubs = [];
638
- const addStubs = (newStubs) => {
639
- stubs = [...stubs, ...newStubs];
649
+ const getCookieValue = (key) => {
650
+ try {
651
+ if (!document || !document.cookie) {
652
+ return '';
653
+ }
654
+ const name = `${key}=`;
655
+ const decodedCookie = decodeURIComponent(document.cookie);
656
+ const ca = decodedCookie.split(';');
657
+ for (let i = 0; i < ca.length; i++) {
658
+ let c = ca[i];
659
+ while (c.charAt(0) === ' ') {
660
+ c = c.substring(1);
661
+ }
662
+ if (c.indexOf(name) === 0) {
663
+ return c.substring(name.length, c.length);
664
+ }
665
+ }
666
+ return '';
667
+ }
668
+ catch {
669
+ return '';
670
+ }
640
671
  };
641
- const addStub = (stub) => {
642
- stubs.push(stub);
672
+
673
+ const getConsent$1 = (destination) => {
674
+ const storageConsent = getDataPerKey(destination, 'local', tagStorage, consentKey);
675
+ if (storageConsent) {
676
+ return storageConsent;
677
+ }
678
+ return getSetting(destination, 'consent');
643
679
  };
644
- const processStubs = () => {
680
+
681
+ const processStubs = (destination) => {
645
682
  try {
683
+ const stubs = getSetting(destination, 'stubs');
646
684
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
647
685
  // @ts-ignore
648
686
  stubs.forEach((stub) => api$1[stub.name](...(stub.arguments || [])));
649
- stubs = [];
687
+ setSetting({
688
+ stubs: [],
689
+ }, destination);
650
690
  }
651
691
  catch (e) {
652
692
  error(e);
653
693
  }
654
694
  };
695
+ const addStub = (destination, stub) => {
696
+ const otherStubs = getSetting(destination, 'stubs') || [];
697
+ setSetting({
698
+ stubs: [...otherStubs, stub],
699
+ }, destination);
700
+ };
655
701
 
656
- const sendTag = ({ eventName, eventId, data, providerData, providers, options, }) => {
702
+ const sendTag = (destination, { eventName, eventId, data, providerData, providers, options }) => {
657
703
  const payload = {
658
704
  eventName,
659
705
  eventId,
@@ -664,11 +710,11 @@
664
710
  if (providers) {
665
711
  payload.providers = providers;
666
712
  }
667
- postRequest(getTagURL(options), payload, options).catch(error);
713
+ postRequest(getTagURL(destination, options), payload, options).catch(error);
668
714
  };
669
- const handleTag = (eventName, data = {}, providers, options) => {
670
- if (!isInitialized()) {
671
- addStub({
715
+ const processTag = (destination, eventName, data = {}, providers, options) => {
716
+ if (!getSetting(destination, 'initialized')) {
717
+ addStub(destination, {
672
718
  name: 'tag',
673
719
  arguments: [eventName, data, providers, options],
674
720
  });
@@ -678,11 +724,11 @@
678
724
  if (!eventId) {
679
725
  eventId = generateEventId(eventName);
680
726
  }
681
- const providerPackages = getProvidersPackage();
682
- const configuredTags = getConfiguredTags();
683
- const userId = handleGetUserId();
727
+ const providerPackages = getProvidersPackage(destination);
728
+ const configuredTags = getSetting(destination, 'channels');
729
+ const userId = getUserId$1(destination);
684
730
  const providerData = {};
685
- const consent = getConsent$1();
731
+ const consent = getConsent$1(destination);
686
732
  for (const pkg of Object.values(providerPackages)) {
687
733
  if (!pkg || !pkg.name || !pkg.tag) {
688
734
  continue;
@@ -691,26 +737,25 @@
691
737
  log(`Provider ${pkg.name} is not in allow list`);
692
738
  continue;
693
739
  }
694
- const variables = getProviderVariables(pkg.name);
740
+ const variables = getProviderVariables(destination, pkg.name);
695
741
  const result = {};
696
- const providerVariables = Object.entries(variables);
697
742
  const executionContext = new Map();
698
- for (const [tagName, variableSet] of providerVariables) {
699
- if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
700
- log(`Provider instance is not allowed (${pkg.name}: ${tagName})`);
743
+ for (const variable of variables) {
744
+ if (!isProviderInstanceAllowed(providers, pkg.name, variable.tagName)) {
745
+ log(`Provider instance is not allowed (${pkg.name}: ${variable.tagName})`);
701
746
  continue;
702
747
  }
703
- if (!hasUserConsent(consent, pkg.name, tagName)) {
704
- log(`Consent is missing (${pkg.name}: ${tagName})`);
748
+ if (!hasUserConsent(consent, pkg.name, variable.tagName)) {
749
+ log(`Consent is missing (${pkg.name}: ${variable.tagName})`);
705
750
  continue;
706
751
  }
707
- result[tagName] = pkg.tag({
752
+ result[variable.tagName] = pkg.tag({
708
753
  userId,
709
754
  eventName,
710
755
  eventId,
711
756
  data: JSON.parse(JSON.stringify(data)),
712
- sendTag,
713
- manifestVariables: variableSet,
757
+ sendTag: sendTag.bind(null, destination),
758
+ manifestVariables: variable.variableSet,
714
759
  executionContext,
715
760
  });
716
761
  }
@@ -719,7 +764,7 @@
719
764
  if (!hasAllowedManifestTags(configuredTags, consent, providers)) {
720
765
  return;
721
766
  }
722
- sendTag({
767
+ sendTag(destination, {
723
768
  eventName,
724
769
  eventId,
725
770
  data,
@@ -728,6 +773,15 @@
728
773
  options,
729
774
  });
730
775
  };
776
+ const handleTag = (eventName, data = {}, providers, options) => {
777
+ if (options === null || options === void 0 ? void 0 : options.destination) {
778
+ processTag(options.destination, eventName, data, providers, options);
779
+ return;
780
+ }
781
+ getInstances().forEach((instance) => {
782
+ processTag(instance, eventName, data, providers, options);
783
+ });
784
+ };
731
785
  const hasAllowedManifestTags = (tags, consent, providersConfig) => {
732
786
  for (const [pkg, tagNames] of tags) {
733
787
  for (const tagName of tagNames) {
@@ -740,28 +794,37 @@
740
794
  return false;
741
795
  };
742
796
 
743
- const handleGetData = (keys, callback) => {
744
- if (!keys || keys.length === 0) {
745
- error('Provide keys for get data API.');
746
- return;
747
- }
748
- getRequest(getGetDataURL(keys))
797
+ const processGetData = (destination, keys, callback) => {
798
+ getRequest(getGetDataURL(destination, keys))
749
799
  .then((result) => {
750
800
  callback((result === null || result === void 0 ? void 0 : result.result) || {});
751
801
  })
752
802
  .catch(error);
753
803
  };
754
-
755
- const handleData = (data, providers, options) => {
756
- if (!data || Object.keys(data).length === 0) {
757
- error('Provide data for data API.');
804
+ const handleGetData = (keys, callback, options) => {
805
+ if (!keys || keys.length === 0) {
806
+ error('Provide keys for get data API.');
807
+ return;
808
+ }
809
+ if (options === null || options === void 0 ? void 0 : options.destination) {
810
+ processGetData(options.destination, keys, callback);
758
811
  return;
759
812
  }
760
- saveKV(data);
761
- const providerPackages = getProvidersPackage();
762
- const configuredTags = getConfiguredTags();
763
- const userId = handleGetUserId();
764
- const consent = getConsent$1();
813
+ const instances = getInstances();
814
+ if (instances.length > 1) {
815
+ error('Multiple instances found! Please provide destination.');
816
+ callback({});
817
+ return;
818
+ }
819
+ processGetData(instances[0], keys, callback);
820
+ };
821
+
822
+ const processData = (destination, data, providers, options) => {
823
+ saveKV(destination, data);
824
+ const providerPackages = getProvidersPackage(destination);
825
+ const configuredTags = getSetting(destination, 'channels');
826
+ const userId = getUserId$1(destination);
827
+ const consent = getConsent$1(destination);
765
828
  for (const pkg of Object.values(providerPackages)) {
766
829
  if (!pkg || !pkg.user || !pkg.name) {
767
830
  continue;
@@ -770,70 +833,92 @@
770
833
  log(`Provider ${pkg.name} is not in allow list`);
771
834
  continue;
772
835
  }
773
- const variables = getProviderVariables(pkg.name);
774
- for (const [tagName, variableSet] of Object.entries(variables)) {
775
- if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
776
- log(`Data not allowed for ${pkg.name} (${tagName})`);
836
+ const variables = getProviderVariables(destination, pkg.name);
837
+ for (const variable of variables) {
838
+ if (!isProviderInstanceAllowed(providers, pkg.name, variable.tagName)) {
839
+ log(`Data not allowed for ${pkg.name} (${variable.tagName})`);
777
840
  continue;
778
841
  }
779
- if (!hasUserConsent(consent, pkg.name, tagName)) {
780
- log(`Consent is missing for ${pkg.name} (${tagName})`);
842
+ if (!hasUserConsent(consent, pkg.name, variable.tagName)) {
843
+ log(`Consent is missing for ${pkg.name} (${variable.tagName})`);
781
844
  continue;
782
845
  }
783
846
  pkg.user({
784
847
  userId,
785
848
  data,
786
- manifestVariables: variableSet,
849
+ manifestVariables: variable.variableSet,
787
850
  });
788
851
  }
789
852
  }
790
- postRequest(getDataURL(), { data, providers }, options).catch(error);
853
+ postRequest(getDataURL(destination), { data, providers }, options).catch(error);
791
854
  };
792
-
793
- let memoryConsent;
794
- const saveConsent = (consent) => {
795
- setConsent(consent);
796
- savePerKey('local', tagStorage, consent, consentKey);
855
+ const handleData = (data, providers, options) => {
856
+ if (!data || Object.keys(data).length === 0) {
857
+ error('Provide data for data API.');
858
+ return;
859
+ }
860
+ if (options === null || options === void 0 ? void 0 : options.destination) {
861
+ processData(options.destination, data, providers, options);
862
+ return;
863
+ }
864
+ getInstances().forEach((destination) => {
865
+ processData(destination, data, providers, options);
866
+ });
797
867
  };
868
+
798
869
  const handleConsent = (consent, options) => {
799
- const existingConsent = getConsent$1();
870
+ if (options === null || options === void 0 ? void 0 : options.destination) {
871
+ processConsent(options.destination, consent, options === null || options === void 0 ? void 0 : options.localSave);
872
+ return;
873
+ }
874
+ getInstances().forEach((destination) => {
875
+ processConsent(destination, consent, options === null || options === void 0 ? void 0 : options.localSave);
876
+ });
877
+ };
878
+ const saveConsent = (destination, consent) => {
879
+ setSetting({
880
+ consent,
881
+ }, destination);
882
+ savePerKey(destination, 'local', tagStorage, consent, consentKey);
883
+ };
884
+ const processConsent = (destination, consent, localSave) => {
885
+ const existingConsent = getConsent$1(destination);
800
886
  if (areEqual(existingConsent, consent)) {
801
887
  return;
802
888
  }
803
889
  const payload = {
804
890
  consentString: consent,
805
891
  };
806
- saveConsent(consent);
807
- if (!(options === null || options === void 0 ? void 0 : options.localSave)) {
808
- postRequest(getConsentURL(), payload).catch(error);
892
+ saveConsent(destination, consent);
893
+ if (!localSave) {
894
+ postRequest(getConsentURL(destination), payload).catch(error);
809
895
  }
810
- const userId = handleGetUserId();
811
- const providerPackages = getProvidersPackage();
896
+ const userId = getUserId$1(destination);
897
+ const providerPackages = getProvidersPackage(destination);
812
898
  const executionContext = new Map();
813
899
  /* Calling Init for all provider instances based on consent check */
814
900
  for (const pkg of Object.values(providerPackages)) {
815
901
  if (!pkg || !pkg.name || !pkg.init) {
816
902
  continue;
817
903
  }
818
- const variables = getProviderVariables(pkg.name);
819
- const providerVariables = Object.entries(variables);
820
- for (const [tagName, variablesSet] of providerVariables) {
821
- const hasConsent = hasUserConsent(consent, pkg.name, tagName);
904
+ const variables = getProviderVariables(destination, pkg.name);
905
+ for (const variable of variables) {
906
+ const hasConsent = hasUserConsent(consent, pkg.name, variable.tagName);
822
907
  if (!hasConsent) {
823
908
  continue;
824
909
  }
825
910
  pkg.init({
826
911
  userId,
827
912
  isNewUser: false,
828
- baseUrl: getUrl(),
913
+ baseUrl: destination,
829
914
  manifest: {
830
- tagName,
831
- variables: variablesSet,
915
+ tagName: variable.tagName,
916
+ variables: variable.variableSet,
832
917
  package: pkg.name,
833
918
  },
834
- sendTag,
835
- sendEdgeData: handleData,
836
- getEdgeData: handleGetData,
919
+ sendTag: sendTag.bind(null, destination),
920
+ sendEdgeData: processData.bind(null, destination),
921
+ getEdgeData: processGetData.bind(null, destination),
837
922
  keyName: `${keyPrefix}Store`,
838
923
  executionContext,
839
924
  session: null,
@@ -843,6 +928,7 @@
843
928
  try {
844
929
  window.dispatchEvent(new CustomEvent('edgetag-consent', {
845
930
  detail: {
931
+ destination,
846
932
  oldConsent: existingConsent,
847
933
  newConsent: consent,
848
934
  },
@@ -861,20 +947,10 @@
861
947
  pkg.consent({ hasConsent });
862
948
  }
863
949
  };
864
- const setConsent = (newConsent) => {
865
- memoryConsent = newConsent;
866
- };
867
- const getConsent$1 = () => {
868
- const storageConsent = getDataPerKey('local', tagStorage, consentKey);
869
- if (storageConsent) {
870
- return storageConsent;
871
- }
872
- return memoryConsent;
873
- };
874
950
 
875
951
  const cacheKey = `${keyPrefix}Cache`;
876
952
  const identity = (v) => v;
877
- const saveDataToEdge = (key, value, provider) => {
953
+ const saveDataToEdge = (destination, key, value, provider) => {
878
954
  if (!value) {
879
955
  return;
880
956
  }
@@ -888,9 +964,11 @@
888
964
  return;
889
965
  }
890
966
  }
891
- handleData({ [`${provider}::${key}`]: updatedValue });
967
+ handleData({ [`${provider}::${key}`]: updatedValue }, undefined, {
968
+ destination,
969
+ });
892
970
  };
893
- const handleCaptureQuery = (provider, key, persistType, map) => {
971
+ const handleCaptureQuery = (destination, provider, key, persistType, map) => {
894
972
  try {
895
973
  if (!window) {
896
974
  return;
@@ -899,7 +977,7 @@
899
977
  catch {
900
978
  return;
901
979
  }
902
- const params = new URLSearchParams(getSearch());
980
+ const params = new URLSearchParams(getSearch(destination));
903
981
  if (!params || !params.get(key)) {
904
982
  return;
905
983
  }
@@ -908,27 +986,29 @@
908
986
  return;
909
987
  }
910
988
  if (persistType === 'edge') {
911
- saveDataToEdge(key, data, provider);
989
+ saveDataToEdge(destination, key, data, provider);
912
990
  return;
913
991
  }
914
- saveDataPerKey(persistType, provider, data, key);
992
+ saveDataPerKey(destination, persistType, provider, data, key);
915
993
  };
916
- const getFromCache = (persistType, provider, key) => {
994
+ const getFromCache = (destination, persistType, provider, key) => {
917
995
  var _a;
918
- const cache = getData$1(persistType === 'edge' ? 'local' : persistType, cacheKey);
996
+ const type = persistType === 'edge' ? 'local' : persistType;
997
+ const cache = getData$1(destination, type, cacheKey);
919
998
  return (_a = cache[provider]) === null || _a === void 0 ? void 0 : _a[key];
920
999
  };
921
- const saveToCache = (persistType, provider, key, value) => {
922
- const cache = getData$1(persistType === 'edge' ? 'local' : persistType, cacheKey);
1000
+ const saveToCache = (destination, persistType, provider, key, value) => {
1001
+ const type = persistType === 'edge' ? 'local' : persistType;
1002
+ const cache = getData$1(destination, type, cacheKey);
923
1003
  if (!cache[provider]) {
924
1004
  cache[provider] = { [key]: value };
925
1005
  }
926
1006
  else {
927
1007
  cache[provider][key] = value;
928
1008
  }
929
- saveData(persistType === 'edge' ? 'local' : persistType, cache, cacheKey);
1009
+ saveData(destination, type, cache, cacheKey);
930
1010
  };
931
- const handleCaptureStorage = (provider, key, persistType, location, map) => {
1011
+ const handleCaptureStorage = (destination, provider, key, persistType, location, map) => {
932
1012
  let data;
933
1013
  try {
934
1014
  switch (location) {
@@ -951,44 +1031,43 @@
951
1031
  if (!data) {
952
1032
  return;
953
1033
  }
954
- const cachedKey = `${handleGetUserId()}/${key}`;
955
- const cachedValue = getFromCache(persistType, provider, cachedKey);
1034
+ const cachedKey = `${getUserId$1(destination)}/${key}`;
1035
+ const cachedValue = getFromCache(destination, persistType, provider, cachedKey);
956
1036
  if (persistType === 'edge' && cachedValue !== data) {
957
- saveDataToEdge(key, data, provider);
958
- saveToCache(persistType, provider, cachedKey, data);
1037
+ saveDataToEdge(destination, key, data, provider);
1038
+ saveToCache(destination, persistType, provider, cachedKey, data);
959
1039
  return;
960
1040
  }
961
- saveDataPerKey(persistType, provider, data, key);
1041
+ saveDataPerKey(destination, persistType, provider, data, key);
962
1042
  };
963
- const handleCapture = (provider, params, capture) => {
1043
+ const handleCapture = (destination, provider, params, capture) => {
964
1044
  params.forEach((param) => {
965
1045
  switch (param.type) {
966
1046
  case 'query': {
967
- handleCaptureQuery(provider, param.key, param.persist, capture === null || capture === void 0 ? void 0 : capture.bind(null, param));
1047
+ handleCaptureQuery(destination, provider, param.key, param.persist, capture === null || capture === void 0 ? void 0 : capture.bind(null, param));
968
1048
  break;
969
1049
  }
970
1050
  case 'storage': {
971
- handleCaptureStorage(provider, param.key, param.persist, param.location, capture === null || capture === void 0 ? void 0 : capture.bind(null, param));
1051
+ handleCaptureStorage(destination, provider, param.key, param.persist, param.location, capture === null || capture === void 0 ? void 0 : capture.bind(null, param));
972
1052
  break;
973
1053
  }
974
1054
  }
975
1055
  });
976
1056
  };
977
1057
 
978
- const handleManifest = (response, consent) => {
979
- const providerPackages = getProvidersPackage();
980
- const userId = handleGetUserId();
1058
+ const handleManifest = (destination, response) => {
1059
+ const providerPackages = getProvidersPackage(destination);
1060
+ const userId = getUserId$1(destination);
981
1061
  const executionContext = new Map();
982
1062
  const manifest = response.result;
983
1063
  manifest.forEach((provider) => {
984
- addConfiguredTag(provider.package, provider.tagName);
985
- addProviderVariable(provider.package, provider.variables, provider.tagName);
1064
+ addChannel(destination, provider.package, provider.tagName);
986
1065
  const pkg = providerPackages[provider.package];
987
1066
  if (provider.rules) {
988
1067
  Object.entries(provider.rules).forEach(([name, recipe]) => {
989
1068
  switch (name) {
990
1069
  case 'capture': {
991
- handleCapture(provider.package, recipe, pkg === null || pkg === void 0 ? void 0 : pkg.capture);
1070
+ handleCapture(destination, provider.package, recipe, pkg === null || pkg === void 0 ? void 0 : pkg.capture);
992
1071
  return;
993
1072
  }
994
1073
  }
@@ -996,36 +1075,27 @@
996
1075
  }
997
1076
  if (pkg && pkg.name && pkg.init) {
998
1077
  /* this defines if the consent is given for a specific instance of a provider */
999
- const hasConsent = hasUserConsent(consent, pkg.name, provider.tagName);
1078
+ const hasConsent = hasUserConsent(getSetting(destination, 'consent'), pkg.name, provider.tagName);
1000
1079
  if (hasConsent) {
1001
1080
  pkg.init({
1002
1081
  userId,
1003
1082
  isNewUser: !!response.isNewUser,
1004
1083
  session: response.session,
1005
- baseUrl: getUrl(),
1084
+ baseUrl: destination,
1006
1085
  manifest: provider,
1007
- sendTag,
1008
- sendEdgeData: handleData,
1009
- getEdgeData: handleGetData,
1086
+ sendTag: sendTag.bind(null, destination),
1087
+ sendEdgeData: processData.bind(null, destination),
1088
+ getEdgeData: processGetData.bind(null, destination),
1010
1089
  keyName: `${keyPrefix}Store`,
1011
1090
  executionContext,
1012
1091
  });
1013
1092
  }
1014
1093
  }
1015
1094
  });
1016
- setInitialized();
1017
- processStubs();
1018
- };
1019
-
1020
- let initIsNewUser = undefined;
1021
- const handleIsNewUser = () => {
1022
- if (initIsNewUser !== undefined) {
1023
- return initIsNewUser;
1024
- }
1025
- return undefined;
1026
- };
1027
- const setIsNewUSer = (isNewUser) => {
1028
- initIsNewUser = isNewUser;
1095
+ setSetting({
1096
+ initialized: true,
1097
+ }, destination);
1098
+ processStubs(destination);
1029
1099
  };
1030
1100
 
1031
1101
  const handleInit = (preferences) => {
@@ -1034,15 +1104,17 @@
1034
1104
  return;
1035
1105
  }
1036
1106
  if (preferences.afterManifestEvents) {
1037
- addStubs(preferences.afterManifestEvents);
1107
+ setSetting({
1108
+ stubs: preferences.afterManifestEvents,
1109
+ }, preferences.edgeURL);
1038
1110
  }
1039
- const url = new URL(getInitURL());
1111
+ const url = new URL(getInitURL(preferences.edgeURL));
1040
1112
  if (preferences.disableConsentCheck) {
1041
1113
  url.searchParams.set('consentDisabled', 'true');
1042
- saveConsent({ all: true });
1114
+ saveConsent(preferences.edgeURL, { all: true });
1043
1115
  }
1044
1116
  if (preferences.userId) {
1045
- setUserId(preferences.userId);
1117
+ setSetting({ userId: preferences.userId }, preferences.edgeURL);
1046
1118
  url.searchParams.set('userId', preferences.userId);
1047
1119
  }
1048
1120
  getRequest(url.href)
@@ -1051,18 +1123,17 @@
1051
1123
  error('Initialization failed');
1052
1124
  return;
1053
1125
  }
1054
- if (result.userId) {
1055
- setUserId(result.userId);
1056
- }
1057
- const consent = getConsent$1();
1058
- if (result.consent && !consent) {
1059
- saveConsent(result.consent);
1060
- }
1061
- setIsNewUSer(result.isNewUser);
1062
- handleManifest(result, consent || result.consent);
1126
+ setSetting({
1127
+ isNewUser: result.isNewUser,
1128
+ consent: getConsent$1(preferences.edgeURL) || result.consent,
1129
+ userId: result.userId,
1130
+ packages: result.result,
1131
+ }, preferences.edgeURL);
1132
+ handleManifest(preferences.edgeURL, result);
1063
1133
  try {
1064
1134
  window.dispatchEvent(new CustomEvent('edgetag-initialized', {
1065
1135
  detail: {
1136
+ destination: preferences.edgeURL,
1066
1137
  userId: result.userId,
1067
1138
  isNewUser: result.isNewUser,
1068
1139
  consent: result.consent,
@@ -1078,18 +1149,14 @@
1078
1149
  .catch(error);
1079
1150
  };
1080
1151
 
1081
- const handleUser = (key, value, providers, options) => {
1082
- if (!key || !value) {
1083
- error('Key or Value is missing in user API.');
1084
- return;
1085
- }
1086
- saveKV({
1152
+ const processUser = (destination, key, value, providers, options) => {
1153
+ saveKV(destination, {
1087
1154
  [key]: value,
1088
1155
  });
1089
- const providerPackages = getProvidersPackage();
1090
- const configuredTags = getConfiguredTags();
1091
- const consent = getConsent$1();
1092
- const userId = handleGetUserId();
1156
+ const providerPackages = getProvidersPackage(destination);
1157
+ const configuredTags = getSetting(destination, 'channels');
1158
+ const consent = getConsent$1(destination);
1159
+ const userId = getUserId$1(destination);
1093
1160
  for (const pkg of Object.values(providerPackages)) {
1094
1161
  if (!pkg || !pkg.name || !pkg.user) {
1095
1162
  continue;
@@ -1098,47 +1165,73 @@
1098
1165
  log(`Provider ${pkg.name} is not in allow list`);
1099
1166
  continue;
1100
1167
  }
1101
- const variables = getProviderVariables(pkg.name);
1102
- for (const [tagName, variableSet] of Object.entries(variables)) {
1103
- if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
1104
- log(`User not allowed for ${pkg.name} (${tagName})`);
1168
+ const variables = getProviderVariables(destination, pkg.name);
1169
+ for (const variable of variables) {
1170
+ if (!isProviderInstanceAllowed(providers, pkg.name, variable.tagName)) {
1171
+ log(`User not allowed for ${pkg.name} (${variable.tagName})`);
1105
1172
  continue;
1106
1173
  }
1107
- if (!hasUserConsent(consent, pkg.name, tagName)) {
1108
- log(`User doesn't have consent for ${pkg.name} (${tagName})`);
1174
+ if (!hasUserConsent(consent, pkg.name, variable.tagName)) {
1175
+ log(`User doesn't have consent for ${pkg.name} (${variable.tagName})`);
1109
1176
  continue;
1110
1177
  }
1111
1178
  pkg.user({
1112
1179
  userId,
1113
1180
  data: { [key]: value },
1114
- manifestVariables: variableSet,
1181
+ manifestVariables: variable.variableSet,
1115
1182
  });
1116
1183
  }
1117
1184
  }
1118
- postRequest(getUserURL(), {
1185
+ postRequest(getUserURL(destination), {
1119
1186
  key,
1120
1187
  value,
1121
1188
  providers,
1122
1189
  }, options).catch(error);
1123
1190
  };
1191
+ const handleUser = (key, value, providers, options) => {
1192
+ if (!key || !value) {
1193
+ error('Key or Value is missing in user API.');
1194
+ return;
1195
+ }
1196
+ if (options === null || options === void 0 ? void 0 : options.destination) {
1197
+ processUser(options.destination, key, value, providers, options);
1198
+ return;
1199
+ }
1200
+ getInstances().forEach((destination) => {
1201
+ processUser(destination, key, value, providers, options);
1202
+ });
1203
+ };
1124
1204
 
1125
- const handleKeys = (callback) => {
1126
- getRequest(getKeysURL())
1205
+ const processKeys = (destination, callback) => {
1206
+ getRequest(getKeysURL(destination))
1127
1207
  .then((result) => {
1128
1208
  callback((result === null || result === void 0 ? void 0 : result.result) || []);
1129
1209
  })
1130
1210
  .catch(error);
1131
1211
  };
1212
+ const handleKeys = (callback, options) => {
1213
+ if (options === null || options === void 0 ? void 0 : options.destination) {
1214
+ processKeys(options.destination, callback);
1215
+ return;
1216
+ }
1217
+ const instances = getInstances();
1218
+ if (instances.length > 1) {
1219
+ error('Multiple instances found! Please provide destination.');
1220
+ callback([]);
1221
+ return;
1222
+ }
1223
+ processKeys(instances[0], callback);
1224
+ };
1132
1225
 
1133
- const handleGetConsent = (callback) => {
1134
- getRequest(getConsentURL())
1226
+ const processGetConsent = (destination, callback) => {
1227
+ getRequest(getConsentURL(destination))
1135
1228
  .then((result) => {
1136
1229
  // this will try to return the consent data stored in Edge
1137
1230
  return result === null || result === void 0 ? void 0 : result.result;
1138
1231
  })
1139
1232
  .catch(() => undefined)
1140
1233
  .then((result) => {
1141
- const consent = result !== null && result !== void 0 ? result : getConsent$1(); // this is a default value i.e. value from local storage and memory incase Edge doesn't have consent
1234
+ const consent = result !== null && result !== void 0 ? result : getConsent$1(destination); // this is a default value i.e. value from local storage and memory incase Edge doesn't have consent
1142
1235
  if (consent) {
1143
1236
  callback(consent);
1144
1237
  }
@@ -1147,9 +1240,48 @@
1147
1240
  }
1148
1241
  });
1149
1242
  };
1243
+ const handleGetConsent = (callback, options) => {
1244
+ if (options === null || options === void 0 ? void 0 : options.destination) {
1245
+ processGetConsent(options.destination, callback);
1246
+ return;
1247
+ }
1248
+ const instances = getInstances();
1249
+ if (instances.length > 1) {
1250
+ callback(null, new Error('Multiple instances found! Please provide destination.'));
1251
+ return;
1252
+ }
1253
+ processGetConsent(instances[0], callback);
1254
+ };
1150
1255
 
1151
- const handleConfig = (config) => {
1152
- setConfig$1(config);
1256
+ const handleIsNewUser = (options) => {
1257
+ if (options === null || options === void 0 ? void 0 : options.destination) {
1258
+ return getSetting(options.destination, 'isNewUser');
1259
+ }
1260
+ const instances = getInstances();
1261
+ if (instances.length > 1) {
1262
+ error('Multiple instances found! Please provide destination.');
1263
+ return undefined;
1264
+ }
1265
+ return getSetting(instances[0], 'isNewUser');
1266
+ };
1267
+
1268
+ const processConfig = (destination, config) => {
1269
+ const existingConfig = getSetting(destination, 'config');
1270
+ setSetting({
1271
+ config: {
1272
+ ...existingConfig,
1273
+ ...config,
1274
+ },
1275
+ }, destination);
1276
+ };
1277
+ const handleConfig = (config, options) => {
1278
+ if (options === null || options === void 0 ? void 0 : options.destination) {
1279
+ processConfig(options.destination, config);
1280
+ return;
1281
+ }
1282
+ getInstances().forEach((destination) => {
1283
+ processConfig(destination, config);
1284
+ });
1153
1285
  };
1154
1286
 
1155
1287
  const init = (preferences) => {
@@ -1167,23 +1299,23 @@
1167
1299
  const data = (value, providers, options) => {
1168
1300
  handleData(value, providers, options);
1169
1301
  };
1170
- const getData = (keys, callback) => {
1171
- handleGetData(keys, callback);
1302
+ const getData = (keys, callback, options) => {
1303
+ handleGetData(keys, callback, options);
1172
1304
  };
1173
- const keys = (callback) => {
1174
- handleKeys(callback);
1305
+ const keys = (callback, options) => {
1306
+ handleKeys(callback, options);
1175
1307
  };
1176
- const getUserId = () => {
1177
- return handleGetUserId();
1308
+ const getUserId = (options) => {
1309
+ return handleGetUserId(options);
1178
1310
  };
1179
- const getConsent = (callback) => {
1180
- handleGetConsent(callback);
1311
+ const getConsent = (callback, options) => {
1312
+ handleGetConsent(callback, options);
1181
1313
  };
1182
- const isNewUser = () => {
1183
- return handleIsNewUser();
1314
+ const isNewUser = (options) => {
1315
+ return handleIsNewUser(options);
1184
1316
  };
1185
- const setConfig = (config) => {
1186
- return handleConfig(config);
1317
+ const setConfig = (config, options) => {
1318
+ handleConfig(config, options);
1187
1319
  };
1188
1320
 
1189
1321
  // TODO https://github.com/blotoutio/solutions/issues/826
@@ -1197,8 +1329,8 @@
1197
1329
  tag(name, data, providers, options);
1198
1330
  }
1199
1331
 
1200
- consent(consentString, consentOptions) {
1201
- consent(consentString, consentOptions);
1332
+ consent(consentString, options) {
1333
+ consent(consentString, options);
1202
1334
  }
1203
1335
 
1204
1336
  user(key, value, providers, options) {
@@ -1209,28 +1341,28 @@
1209
1341
  data(data$1, providers, options);
1210
1342
  }
1211
1343
 
1212
- getData(keys, callback) {
1213
- getData(keys, callback);
1344
+ getData(keys, callback, options) {
1345
+ getData(keys, callback, options);
1214
1346
  }
1215
1347
 
1216
- keys(callback) {
1217
- keys(callback);
1348
+ keys(callback, options) {
1349
+ keys(callback, options);
1218
1350
  }
1219
1351
 
1220
- getUserId() {
1221
- return getUserId()
1352
+ getUserId(options) {
1353
+ return getUserId(options)
1222
1354
  }
1223
1355
 
1224
- getConsent(callback, error) {
1225
- getConsent(callback);
1356
+ getConsent(callback, options) {
1357
+ getConsent(callback, options);
1226
1358
  }
1227
1359
 
1228
- isNewUser() {
1229
- return isNewUser()
1360
+ isNewUser(options) {
1361
+ return isNewUser(options)
1230
1362
  }
1231
1363
 
1232
- setConfig(config) {
1233
- return setConfig()
1364
+ setConfig(config, options) {
1365
+ setConfig(config, options);
1234
1366
  }
1235
1367
  }
1236
1368
 
@@ -1267,7 +1399,7 @@
1267
1399
 
1268
1400
  const beforeManifestEvents = [];
1269
1401
  const afterManifestEvents = [];
1270
- let initCall = null;
1402
+ const initCalls = [];
1271
1403
 
1272
1404
  stubs.forEach((arg) => {
1273
1405
  const sliced = [].slice.call(arg);
@@ -1276,7 +1408,7 @@
1276
1408
  }
1277
1409
 
1278
1410
  if (sliced[0] === 'init') {
1279
- initCall = sliced.slice(1);
1411
+ initCalls.push(sliced.slice(1));
1280
1412
  return
1281
1413
  }
1282
1414
 
@@ -1294,11 +1426,15 @@
1294
1426
  });
1295
1427
  });
1296
1428
 
1297
- if (initCall) {
1298
- initCall[0]['afterManifestEvents'] = afterManifestEvents;
1299
- handleStubs({
1300
- name: 'init',
1301
- arguments: initCall,
1429
+ if (initCalls?.length) {
1430
+ initCalls[initCalls.length - 1][0]['afterManifestEvents'] =
1431
+ afterManifestEvents;
1432
+
1433
+ initCalls.forEach((initCall) => {
1434
+ handleStubs({
1435
+ name: 'init',
1436
+ arguments: initCall,
1437
+ });
1302
1438
  });
1303
1439
  }
1304
1440