@blotoutio/edgetag-sdk-js 0.24.2 → 0.26.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/index.cjs CHANGED
@@ -12,147 +12,6 @@ var api = /*#__PURE__*/Object.freeze({
12
12
  get user () { return user; }
13
13
  });
14
14
 
15
- const getMessage = (error) => {
16
- if (error instanceof Error) {
17
- return error.message;
18
- }
19
- if (typeof error === 'string') {
20
- return error;
21
- }
22
- try {
23
- return JSON.stringify(error);
24
- }
25
- catch {
26
- return error;
27
- }
28
- };
29
- const log = (data) => {
30
- console.log('[EdgeTag]', getMessage(data));
31
- };
32
- const error = (data) => {
33
- console.error('[EdgeTag]', getMessage(data));
34
- };
35
-
36
- let endpointUrl = '';
37
- const generateUrl = (path) => {
38
- const endpoint = getUrl();
39
- if (!endpoint) {
40
- log('URL is not valid');
41
- return '';
42
- }
43
- return `${endpoint}${path}`;
44
- };
45
- const getUrl = () => {
46
- return endpointUrl;
47
- };
48
- const setUrl = (url) => {
49
- if (url == null) {
50
- return;
51
- }
52
- endpointUrl = url;
53
- };
54
- const getTagURL = () => {
55
- return generateUrl('/tag');
56
- };
57
- const getInitURL = () => {
58
- return generateUrl('/init');
59
- };
60
- const getConsentURL = () => {
61
- return generateUrl('/consent');
62
- };
63
- const getUserURL = () => {
64
- return generateUrl('/user');
65
- };
66
- const getDataURL = () => {
67
- return generateUrl(`/data`);
68
- };
69
- const getGetDataURL = (keys) => {
70
- return generateUrl(`/data?keys=${encodeURIComponent(keys.join(','))}`);
71
- };
72
- const getKeysURL = () => {
73
- return generateUrl(`/keys`);
74
- };
75
-
76
- let allowedProvider = [];
77
- let initialized = false;
78
- let consentDisabled = false;
79
- const providersPackages = {};
80
- const setPreferences = (preferences) => {
81
- var _a;
82
- if (!preferences) {
83
- return false;
84
- }
85
- if (!preferences.edgeURL) {
86
- error('Please provide URL for EdgeTag');
87
- return false;
88
- }
89
- consentDisabled = !!preferences.disableConsentCheck;
90
- (_a = preferences.providers) === null || _a === void 0 ? void 0 : _a.forEach((provider) => {
91
- if (!provider.name) {
92
- return;
93
- }
94
- providersPackages[provider.name] = provider;
95
- });
96
- try {
97
- if (window && Array.isArray(window.edgetagProviders)) {
98
- window.edgetagProviders.forEach((provider) => {
99
- if (!provider.name) {
100
- return;
101
- }
102
- providersPackages[provider.name] = provider;
103
- });
104
- }
105
- }
106
- catch {
107
- // do nothing
108
- }
109
- setUrl(preferences.edgeURL);
110
- return true;
111
- };
112
- const isConsentDisabled = () => consentDisabled;
113
- const getProvidersPackage = () => providersPackages;
114
- const isInitialized = () => initialized;
115
- const setInitialized = () => {
116
- initialized = true;
117
- };
118
- const getAllowedProviders = () => allowedProvider;
119
- const setAllowedProviders = (providers) => {
120
- allowedProvider = providers;
121
- };
122
-
123
- const checkConsent = (providers) => {
124
- if (isConsentDisabled()) {
125
- return true;
126
- }
127
- const consent = getConsent();
128
- if (!consent) {
129
- return false;
130
- }
131
- const consentLength = Object.keys(consent).length;
132
- if (!consentLength || (consentLength === 1 && consent['all'] === false)) {
133
- return false;
134
- }
135
- const providersLength = Object.keys(providers || {}).length;
136
- if (!providers ||
137
- providersLength === 0 ||
138
- (providersLength === 1 && providers['all'])) {
139
- return (Object.values(consent).find((isAllowed) => isAllowed) || false);
140
- }
141
- for (const [key, value] of Object.entries(providers)) {
142
- if (value === false || consent[key] === false) {
143
- continue;
144
- }
145
- // we have consent
146
- if (consent[key] ||
147
- (consent['all'] === true && consent[key] === undefined)) {
148
- // we have provider
149
- if (value || (providers['all'] && providers[key] === undefined)) {
150
- return true;
151
- }
152
- }
153
- }
154
- return false;
155
- };
156
15
  const getUserAgent = () => {
157
16
  try {
158
17
  const nav = navigator;
@@ -210,81 +69,33 @@ const getPageTitle = () => {
210
69
  return '';
211
70
  }
212
71
  };
213
- const isProviderIncluded = (providers, providerValue) => {
214
- return (providerValue || (providers['all'] === true && providerValue === undefined));
215
- };
216
- const allowTag = (providers) => {
217
- if (!checkConsent(providers)) {
218
- return false;
219
- }
220
- const providersLength = Object.values(providers || {}).length;
221
- if (!providers || providersLength === 0) {
222
- return true;
223
- }
224
- const allProviders = getAllowedProviders();
225
- const allProvidersLength = Object.keys(allProviders || {}).length;
226
- if (allProvidersLength === 0) {
227
- return true;
228
- }
229
- for (const provider of allProviders) {
230
- if (isProviderIncluded(providers, providers[provider])) {
231
- return true;
232
- }
233
- }
234
- return false;
235
- };
236
- const allowProviders = (providers) => {
237
- if (!providers || Object.keys(providers).length === 0 || providers['all']) {
238
- return true;
72
+
73
+ const tagStorage = 'edgeTag';
74
+ const consentKey = 'consent';
75
+ const keyPrefix = `_worker`;
76
+ const cookieKey = 'tag_user_id';
77
+
78
+ const getMessage = (error) => {
79
+ if (error instanceof Error) {
80
+ return error.message;
239
81
  }
240
- const allowedProvider = getAllowedProviders();
241
- if (allowedProvider && allowedProvider.length > 0) {
242
- let found = false;
243
- Object.entries(providers).forEach(([key, value]) => {
244
- if (!value) {
245
- return;
246
- }
247
- if (allowedProvider.includes(key)) {
248
- found = true;
249
- }
250
- });
251
- return found;
82
+ if (typeof error === 'string') {
83
+ return error;
252
84
  }
253
- return true;
254
- };
255
- const allowProvider = (providerId) => {
256
- if (!providerId) {
257
- return true;
85
+ try {
86
+ return JSON.stringify(error);
258
87
  }
259
- const allowedProvider = getAllowedProviders();
260
- if (allowedProvider && allowedProvider.length > 0) {
261
- return allowedProvider.includes(providerId);
88
+ catch {
89
+ return error;
262
90
  }
263
- return true;
264
91
  };
265
- const allowProviderWithConsent = (providers, providerId) => {
266
- if (!allowProvider(providerId)) {
267
- return false;
268
- }
269
- if (!checkConsent(providers)) {
270
- return false;
271
- }
272
- if (providers && Object.keys(providers).length) {
273
- if (!isProviderIncluded(providers, providers[providerId])) {
274
- return false;
275
- }
276
- }
277
- return true;
92
+ const log = (data) => {
93
+ console.log('[EdgeTag]', getMessage(data));
278
94
  };
279
- const checkProviderConsent = (providerId) => {
280
- return checkConsent({ [providerId]: true });
95
+ const error = (data) => {
96
+ console.error('[EdgeTag]', getMessage(data));
281
97
  };
282
98
 
283
- const tagStorage = 'edgeTag';
284
- const consentKey = 'consent';
285
- const keyPrefix = `_worker`;
286
- const cookieKey = 'tag_user_id';
287
-
288
99
  const initKey = `${keyPrefix}Store`;
289
100
  const saveDataPerKey = (persistType, provider, value, key) => {
290
101
  const storage = getData$1(persistType);
@@ -512,7 +323,7 @@ const getStandardPayload = (payload) => {
512
323
  referrer: getReferrer(),
513
324
  search: getSearch(),
514
325
  locale: getLocale(),
515
- sdkVersion: "0.24.2" ,
326
+ sdkVersion: "0.26.0" ,
516
327
  ...(payload || {}),
517
328
  };
518
329
  let storage = {};
@@ -555,6 +366,46 @@ async function getRequest(url, options) {
555
366
  return await ajax('GET', url);
556
367
  }
557
368
 
369
+ let endpointUrl = '';
370
+ const generateUrl = (path) => {
371
+ const endpoint = getUrl();
372
+ if (!endpoint) {
373
+ log('URL is not valid');
374
+ return '';
375
+ }
376
+ return `${endpoint}${path}`;
377
+ };
378
+ const getUrl = () => {
379
+ return endpointUrl;
380
+ };
381
+ const setUrl = (url) => {
382
+ if (url == null) {
383
+ return;
384
+ }
385
+ endpointUrl = url;
386
+ };
387
+ const getTagURL = () => {
388
+ return generateUrl('/tag');
389
+ };
390
+ const getInitURL = () => {
391
+ return generateUrl('/init');
392
+ };
393
+ const getConsentURL = () => {
394
+ return generateUrl('/consent');
395
+ };
396
+ const getUserURL = () => {
397
+ return generateUrl('/user');
398
+ };
399
+ const getDataURL = () => {
400
+ return generateUrl(`/data`);
401
+ };
402
+ const getGetDataURL = (keys) => {
403
+ return generateUrl(`/data?keys=${encodeURIComponent(keys.join(','))}`);
404
+ };
405
+ const getKeysURL = () => {
406
+ return generateUrl(`/keys`);
407
+ };
408
+
558
409
  let memoryConsent;
559
410
  const saveConsent = (consent) => {
560
411
  setConsent(consent);
@@ -580,6 +431,53 @@ const getConsent = () => {
580
431
  return memoryConsent;
581
432
  };
582
433
 
434
+ const allowedProvider = new Set();
435
+ let initialized = false;
436
+ const providersPackages = {};
437
+ const setPreferences = (preferences) => {
438
+ var _a;
439
+ if (!preferences) {
440
+ return false;
441
+ }
442
+ if (!preferences.edgeURL) {
443
+ error('Please provide URL for EdgeTag');
444
+ return false;
445
+ }
446
+ !!preferences.disableConsentCheck;
447
+ (_a = preferences.providers) === null || _a === void 0 ? void 0 : _a.forEach((provider) => {
448
+ if (!provider.name) {
449
+ return;
450
+ }
451
+ providersPackages[provider.name] = provider;
452
+ });
453
+ try {
454
+ if (window && Array.isArray(window.edgetagProviders)) {
455
+ window.edgetagProviders.forEach((provider) => {
456
+ if (!provider.name) {
457
+ return;
458
+ }
459
+ providersPackages[provider.name] = provider;
460
+ });
461
+ }
462
+ }
463
+ catch {
464
+ // do nothing
465
+ }
466
+ setUrl(preferences.edgeURL);
467
+ return true;
468
+ };
469
+ const getProvidersPackage = () => providersPackages;
470
+ const isInitialized = () => initialized;
471
+ const setInitialized = () => {
472
+ initialized = true;
473
+ };
474
+ const getAllowedProviders = () => allowedProvider;
475
+ const setAllowedProviders = (providers) => {
476
+ for (const provider of providers) {
477
+ allowedProvider.add(provider);
478
+ }
479
+ };
480
+
583
481
  const manifestVariables = {};
584
482
  const addProviderVariable = (name, variables, tagName) => {
585
483
  manifestVariables[name] = {
@@ -613,11 +511,60 @@ const processStubs = () => {
613
511
  }
614
512
  };
615
513
 
616
- const sendTag = ({ eventName, eventId, data, providerData, providers, options, }) => {
617
- if (!allowProviders(providers)) {
618
- log('Provider is not allowed.');
619
- return;
514
+ const isBool = (v) => typeof v == 'boolean';
515
+ const isRecord = (v) => !!v && typeof v == 'object';
516
+ /**
517
+ * This function validates user consent for a given provider and tag name.
518
+ * It should be used in conjunction with `UserConsent`, not `ProvidersConfig`.
519
+ */
520
+ const hasUserConsent = (consent, provider, tagName) => {
521
+ if (!isRecord(consent)) {
522
+ return false;
523
+ }
524
+ let allowed = isBool(consent.all) ? consent.all : false;
525
+ if (provider in consent) {
526
+ const providerSpecific = consent[provider];
527
+ if (isBool(providerSpecific)) {
528
+ allowed = providerSpecific;
529
+ }
530
+ else if (isRecord(providerSpecific)) {
531
+ if ('all' in providerSpecific && isBool(providerSpecific.all)) {
532
+ allowed = providerSpecific.all;
533
+ }
534
+ if (tagName in providerSpecific && isBool(providerSpecific[tagName])) {
535
+ allowed = providerSpecific[tagName];
536
+ }
537
+ }
538
+ }
539
+ return allowed;
540
+ };
541
+ /**
542
+ * This function validates provider allowance for a given provider and tag name.
543
+ * It should not be used to validate `UserConsent`.
544
+ */
545
+ const isProviderInstanceAllowed = (providersConfig, provider, tagName) => {
546
+ if (!isRecord(providersConfig)) {
547
+ return true;
620
548
  }
549
+ let allowed = isBool(providersConfig.all) ? providersConfig.all : true;
550
+ if (provider in providersConfig) {
551
+ const providerSpecific = providersConfig[provider];
552
+ if (isBool(providerSpecific)) {
553
+ allowed = providerSpecific;
554
+ }
555
+ else if (isRecord(providerSpecific)) {
556
+ if ('all' in providerSpecific && isBool(providerSpecific.all)) {
557
+ allowed = providerSpecific.all;
558
+ }
559
+ if (tagName in providerSpecific && isBool(providerSpecific[tagName])) {
560
+ allowed = providerSpecific[tagName];
561
+ }
562
+ }
563
+ }
564
+ return allowed;
565
+ };
566
+
567
+ const sendTag = ({ eventName, eventId, data, providerData, providers, options, }) => {
621
568
  const payload = {
622
569
  eventName,
623
570
  eventId,
@@ -638,14 +585,6 @@ const handleTag = (eventName, data = {}, providers, options) => {
638
585
  });
639
586
  return;
640
587
  }
641
- if (!allowProviders(providers)) {
642
- log('Provider is not allowed.');
643
- return;
644
- }
645
- if (!allowTag(providers)) {
646
- log('Consent is missing.');
647
- return;
648
- }
649
588
  let eventId = data['eventId'];
650
589
  if (!eventId) {
651
590
  eventId = generateEventId(eventName);
@@ -653,18 +592,32 @@ const handleTag = (eventName, data = {}, providers, options) => {
653
592
  const providerPackages = getProvidersPackage();
654
593
  const userId = handleGetUserId();
655
594
  const providerData = {};
595
+ const consent = getConsent();
596
+ const allowedProviders = getAllowedProviders();
597
+ let anyProviderCalled = false;
656
598
  if (providerPackages) {
657
- Object.values(providerPackages).forEach((pkg) => {
658
- if (!pkg ||
659
- !pkg.name ||
660
- !pkg.tag ||
661
- !checkProviderConsent(pkg.name) ||
662
- !allowProviderWithConsent(providers, pkg.name)) {
663
- return;
599
+ for (const pkg of Object.values(providerPackages)) {
600
+ if (!pkg || !pkg.name || !pkg.tag) {
601
+ continue;
602
+ }
603
+ if (!allowedProviders.has(pkg.name)) {
604
+ log(`Provider ${pkg.name} is not in allow list`);
605
+ continue;
664
606
  }
665
607
  const variables = getProviderVariables(pkg.name);
666
608
  const result = {};
667
- for (const [tagName, variableSet] of Object.entries(variables)) {
609
+ const providerVariables = Object.entries(variables);
610
+ const executionContext = new Map();
611
+ for (const [tagName, variableSet] of providerVariables) {
612
+ if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
613
+ log(`Provider instance is not allowed (${pkg.name}: ${tagName})`);
614
+ continue;
615
+ }
616
+ if (!hasUserConsent(consent, pkg.name, tagName)) {
617
+ log(`Consent is missing (${pkg.name}: ${tagName})`);
618
+ continue;
619
+ }
620
+ anyProviderCalled = true;
668
621
  result[tagName] = pkg.tag({
669
622
  userId,
670
623
  eventName,
@@ -672,10 +625,14 @@ const handleTag = (eventName, data = {}, providers, options) => {
672
625
  data: JSON.parse(JSON.stringify(data)),
673
626
  sendTag,
674
627
  manifestVariables: variableSet,
628
+ executionContext,
675
629
  });
676
630
  }
677
631
  providerData[pkg.name] = result;
678
- });
632
+ }
633
+ }
634
+ if (!anyProviderCalled) {
635
+ return;
679
636
  }
680
637
  sendTag({
681
638
  eventName,
@@ -695,23 +652,34 @@ const handleData = (data, providers, options) => {
695
652
  saveKV(data);
696
653
  const providerPackages = getProvidersPackage();
697
654
  const userId = handleGetUserId();
655
+ const consent = getConsent();
656
+ const allowedProviders = getAllowedProviders();
698
657
  if (providerPackages) {
699
- Object.values(providerPackages).forEach((pkg) => {
700
- if (!pkg ||
701
- !pkg.user ||
702
- !pkg.name ||
703
- !allowProviderWithConsent(providers, pkg.name)) {
704
- return;
658
+ for (const pkg of Object.values(providerPackages)) {
659
+ if (!pkg || !pkg.user || !pkg.name) {
660
+ continue;
661
+ }
662
+ if (!allowedProviders.has(pkg.name)) {
663
+ log(`Provider ${pkg.name} is not in allow list`);
664
+ continue;
705
665
  }
706
666
  const variables = getProviderVariables(pkg.name);
707
- for (const variableSet of Object.values(variables)) {
667
+ for (const [tagName, variableSet] of Object.entries(variables)) {
668
+ if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
669
+ log(`Data not allowed for ${pkg.name} (${tagName})`);
670
+ continue;
671
+ }
672
+ if (!hasUserConsent(consent, pkg.name, tagName)) {
673
+ log(`Consent is missing for ${pkg.name} (${tagName})`);
674
+ continue;
675
+ }
708
676
  pkg.user({
709
677
  userId,
710
678
  data,
711
679
  manifestVariables: variableSet,
712
680
  });
713
681
  }
714
- });
682
+ }
715
683
  }
716
684
  postRequest(getDataURL(), { data, providers }, options).catch(error);
717
685
  };
@@ -828,16 +796,15 @@ const handleManifest = (manifest) => {
828
796
  }
829
797
  if (providerPackages) {
830
798
  const pkg = providerPackages[provider.package];
831
- if (pkg && pkg.name && pkg.init && allowProvider(pkg.name)) {
832
- const initData = {
799
+ if (pkg && pkg.name && pkg.init) {
800
+ pkg.init({
833
801
  userId,
834
802
  manifest: provider,
835
803
  sendTag,
836
804
  sendEdgeData: handleData,
837
805
  getEdgeData: handleGetData,
838
806
  keyName: `${keyPrefix}Store`,
839
- };
840
- pkg.init(initData);
807
+ });
841
808
  }
842
809
  }
843
810
  });
@@ -888,25 +855,37 @@ const handleUser = (key, value, providers, options) => {
888
855
  saveKV({
889
856
  [key]: value,
890
857
  });
858
+ const consent = getConsent();
859
+ const allowedProviders = getAllowedProviders();
891
860
  const providerPackages = getProvidersPackage();
892
861
  const userId = handleGetUserId();
893
862
  if (providerPackages) {
894
- Object.values(providerPackages).forEach((pkg) => {
895
- if (!pkg ||
896
- !pkg.name ||
897
- !pkg.user ||
898
- !allowProviderWithConsent(providers, pkg.name)) {
899
- return;
863
+ for (const pkg of Object.values(providerPackages)) {
864
+ if (!pkg || !pkg.name || !pkg.user) {
865
+ continue;
866
+ }
867
+ if (!allowedProviders.has(pkg.name)) {
868
+ log(`Provider ${pkg.name} is not in allow list`);
869
+ continue;
900
870
  }
901
871
  const variables = getProviderVariables(pkg.name);
902
- for (const variableSet of Object.values(variables)) {
872
+ for (const [tagName, variableSet] of Object.entries(variables)) {
873
+ if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
874
+ // should we be logging this?
875
+ log(`User not allowed for ${pkg.name} (${tagName})`);
876
+ continue;
877
+ }
878
+ if (!hasUserConsent(consent, pkg.name, tagName)) {
879
+ log(`User doesn't have consent for ${pkg.name} (${tagName})`);
880
+ continue;
881
+ }
903
882
  pkg.user({
904
883
  userId,
905
884
  data: { [key]: value },
906
885
  manifestVariables: variableSet,
907
886
  });
908
887
  }
909
- });
888
+ }
910
889
  }
911
890
  postRequest(getUserURL(), {
912
891
  key,
@@ -929,14 +908,14 @@ const init = (preferences) => {
929
908
  const tag = (name, data, providers, options) => {
930
909
  handleTag(name, data, providers, options);
931
910
  };
932
- const consent = (consent, options) => {
933
- handleConsent(consent, options);
911
+ const consent = (value, options) => {
912
+ handleConsent(value, options);
934
913
  };
935
914
  const user = (key, value, providers, options) => {
936
915
  handleUser(key, value, providers, options);
937
916
  };
938
- const data = (data, providers, options) => {
939
- handleData(data, providers, options);
917
+ const data = (value, providers, options) => {
918
+ handleData(value, providers, options);
940
919
  };
941
920
  const getData = (keys, callback) => {
942
921
  handleGetData(keys, callback);
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  // TODO this all located in '@blotoutio/shared/utility-sdk'
2
2
 
3
- import { Library } from '@blotoutio/cdn/types'
3
+ import { Library, ProvidersConfig } from '@blotoutio/cdn/types'
4
4
 
5
5
  type PersistType = 'local' | 'session' | 'edge'
6
6
 
@@ -15,7 +15,7 @@ export type SendTag = {
15
15
  eventId: string
16
16
  data: Data
17
17
  providerData?: Partial<Record<Library, Record<string, Data>>>
18
- providers?: Data
18
+ providers?: Possibly<ProvidersConfig>
19
19
  options?: EventOptions
20
20
  }
21
21
 
@@ -27,7 +27,7 @@ type ManifestRule = {
27
27
  }
28
28
 
29
29
  type Manifest = {
30
- package: string
30
+ package: Library
31
31
  tagName: string
32
32
  variables?: Record<string, string>
33
33
  rules: Record<string, ManifestRule[]>
@@ -46,10 +46,11 @@ type TagParams = {
46
46
  data: Data
47
47
  manifestVariables: Record<string, string>
48
48
  sendTag: (params: SendTag) => void
49
+ executionContext: Map<string, unknown>
49
50
  }
50
51
 
51
52
  type ProviderInit = {
52
- name?: string
53
+ name?: Library
53
54
  init?: (params: InitParams) => void
54
55
  tag?: (params: TagParams) => unknown
55
56
  }
@@ -84,7 +85,7 @@ export declare const init: (preferences: InitPreferences) => void
84
85
  export declare const tag: (
85
86
  name: string,
86
87
  data?: Data,
87
- providers?: Data,
88
+ providers?: ProvidersConfig,
88
89
  options?: EventOptions
89
90
  ) => void
90
91
 
@@ -93,13 +94,13 @@ export declare const consent: (consent: Data) => void
93
94
  export declare const user: (
94
95
  key: UserKey,
95
96
  value: string,
96
- providers?: Data,
97
+ providers?: ProvidersConfig,
97
98
  options?: EventOptions
98
99
  ) => void
99
100
 
100
101
  export declare const data: (
101
102
  data: Record<string, string>,
102
- providers?: Data,
103
+ providers?: ProvidersConfig,
103
104
  options?: EventOptions
104
105
  ) => void
105
106
 
package/index.esm.js CHANGED
@@ -10,147 +10,6 @@ var api = /*#__PURE__*/Object.freeze({
10
10
  get user () { return user; }
11
11
  });
12
12
 
13
- const getMessage = (error) => {
14
- if (error instanceof Error) {
15
- return error.message;
16
- }
17
- if (typeof error === 'string') {
18
- return error;
19
- }
20
- try {
21
- return JSON.stringify(error);
22
- }
23
- catch {
24
- return error;
25
- }
26
- };
27
- const log = (data) => {
28
- console.log('[EdgeTag]', getMessage(data));
29
- };
30
- const error = (data) => {
31
- console.error('[EdgeTag]', getMessage(data));
32
- };
33
-
34
- let endpointUrl = '';
35
- const generateUrl = (path) => {
36
- const endpoint = getUrl();
37
- if (!endpoint) {
38
- log('URL is not valid');
39
- return '';
40
- }
41
- return `${endpoint}${path}`;
42
- };
43
- const getUrl = () => {
44
- return endpointUrl;
45
- };
46
- const setUrl = (url) => {
47
- if (url == null) {
48
- return;
49
- }
50
- endpointUrl = url;
51
- };
52
- const getTagURL = () => {
53
- return generateUrl('/tag');
54
- };
55
- const getInitURL = () => {
56
- return generateUrl('/init');
57
- };
58
- const getConsentURL = () => {
59
- return generateUrl('/consent');
60
- };
61
- const getUserURL = () => {
62
- return generateUrl('/user');
63
- };
64
- const getDataURL = () => {
65
- return generateUrl(`/data`);
66
- };
67
- const getGetDataURL = (keys) => {
68
- return generateUrl(`/data?keys=${encodeURIComponent(keys.join(','))}`);
69
- };
70
- const getKeysURL = () => {
71
- return generateUrl(`/keys`);
72
- };
73
-
74
- let allowedProvider = [];
75
- let initialized = false;
76
- let consentDisabled = false;
77
- const providersPackages = {};
78
- const setPreferences = (preferences) => {
79
- var _a;
80
- if (!preferences) {
81
- return false;
82
- }
83
- if (!preferences.edgeURL) {
84
- error('Please provide URL for EdgeTag');
85
- return false;
86
- }
87
- consentDisabled = !!preferences.disableConsentCheck;
88
- (_a = preferences.providers) === null || _a === void 0 ? void 0 : _a.forEach((provider) => {
89
- if (!provider.name) {
90
- return;
91
- }
92
- providersPackages[provider.name] = provider;
93
- });
94
- try {
95
- if (window && Array.isArray(window.edgetagProviders)) {
96
- window.edgetagProviders.forEach((provider) => {
97
- if (!provider.name) {
98
- return;
99
- }
100
- providersPackages[provider.name] = provider;
101
- });
102
- }
103
- }
104
- catch {
105
- // do nothing
106
- }
107
- setUrl(preferences.edgeURL);
108
- return true;
109
- };
110
- const isConsentDisabled = () => consentDisabled;
111
- const getProvidersPackage = () => providersPackages;
112
- const isInitialized = () => initialized;
113
- const setInitialized = () => {
114
- initialized = true;
115
- };
116
- const getAllowedProviders = () => allowedProvider;
117
- const setAllowedProviders = (providers) => {
118
- allowedProvider = providers;
119
- };
120
-
121
- const checkConsent = (providers) => {
122
- if (isConsentDisabled()) {
123
- return true;
124
- }
125
- const consent = getConsent();
126
- if (!consent) {
127
- return false;
128
- }
129
- const consentLength = Object.keys(consent).length;
130
- if (!consentLength || (consentLength === 1 && consent['all'] === false)) {
131
- return false;
132
- }
133
- const providersLength = Object.keys(providers || {}).length;
134
- if (!providers ||
135
- providersLength === 0 ||
136
- (providersLength === 1 && providers['all'])) {
137
- return (Object.values(consent).find((isAllowed) => isAllowed) || false);
138
- }
139
- for (const [key, value] of Object.entries(providers)) {
140
- if (value === false || consent[key] === false) {
141
- continue;
142
- }
143
- // we have consent
144
- if (consent[key] ||
145
- (consent['all'] === true && consent[key] === undefined)) {
146
- // we have provider
147
- if (value || (providers['all'] && providers[key] === undefined)) {
148
- return true;
149
- }
150
- }
151
- }
152
- return false;
153
- };
154
13
  const getUserAgent = () => {
155
14
  try {
156
15
  const nav = navigator;
@@ -208,81 +67,33 @@ const getPageTitle = () => {
208
67
  return '';
209
68
  }
210
69
  };
211
- const isProviderIncluded = (providers, providerValue) => {
212
- return (providerValue || (providers['all'] === true && providerValue === undefined));
213
- };
214
- const allowTag = (providers) => {
215
- if (!checkConsent(providers)) {
216
- return false;
217
- }
218
- const providersLength = Object.values(providers || {}).length;
219
- if (!providers || providersLength === 0) {
220
- return true;
221
- }
222
- const allProviders = getAllowedProviders();
223
- const allProvidersLength = Object.keys(allProviders || {}).length;
224
- if (allProvidersLength === 0) {
225
- return true;
226
- }
227
- for (const provider of allProviders) {
228
- if (isProviderIncluded(providers, providers[provider])) {
229
- return true;
230
- }
231
- }
232
- return false;
233
- };
234
- const allowProviders = (providers) => {
235
- if (!providers || Object.keys(providers).length === 0 || providers['all']) {
236
- return true;
70
+
71
+ const tagStorage = 'edgeTag';
72
+ const consentKey = 'consent';
73
+ const keyPrefix = `_worker`;
74
+ const cookieKey = 'tag_user_id';
75
+
76
+ const getMessage = (error) => {
77
+ if (error instanceof Error) {
78
+ return error.message;
237
79
  }
238
- const allowedProvider = getAllowedProviders();
239
- if (allowedProvider && allowedProvider.length > 0) {
240
- let found = false;
241
- Object.entries(providers).forEach(([key, value]) => {
242
- if (!value) {
243
- return;
244
- }
245
- if (allowedProvider.includes(key)) {
246
- found = true;
247
- }
248
- });
249
- return found;
80
+ if (typeof error === 'string') {
81
+ return error;
250
82
  }
251
- return true;
252
- };
253
- const allowProvider = (providerId) => {
254
- if (!providerId) {
255
- return true;
83
+ try {
84
+ return JSON.stringify(error);
256
85
  }
257
- const allowedProvider = getAllowedProviders();
258
- if (allowedProvider && allowedProvider.length > 0) {
259
- return allowedProvider.includes(providerId);
86
+ catch {
87
+ return error;
260
88
  }
261
- return true;
262
89
  };
263
- const allowProviderWithConsent = (providers, providerId) => {
264
- if (!allowProvider(providerId)) {
265
- return false;
266
- }
267
- if (!checkConsent(providers)) {
268
- return false;
269
- }
270
- if (providers && Object.keys(providers).length) {
271
- if (!isProviderIncluded(providers, providers[providerId])) {
272
- return false;
273
- }
274
- }
275
- return true;
90
+ const log = (data) => {
91
+ console.log('[EdgeTag]', getMessage(data));
276
92
  };
277
- const checkProviderConsent = (providerId) => {
278
- return checkConsent({ [providerId]: true });
93
+ const error = (data) => {
94
+ console.error('[EdgeTag]', getMessage(data));
279
95
  };
280
96
 
281
- const tagStorage = 'edgeTag';
282
- const consentKey = 'consent';
283
- const keyPrefix = `_worker`;
284
- const cookieKey = 'tag_user_id';
285
-
286
97
  const initKey = `${keyPrefix}Store`;
287
98
  const saveDataPerKey = (persistType, provider, value, key) => {
288
99
  const storage = getData$1(persistType);
@@ -510,7 +321,7 @@ const getStandardPayload = (payload) => {
510
321
  referrer: getReferrer(),
511
322
  search: getSearch(),
512
323
  locale: getLocale(),
513
- sdkVersion: "0.24.2" ,
324
+ sdkVersion: "0.26.0" ,
514
325
  ...(payload || {}),
515
326
  };
516
327
  let storage = {};
@@ -553,6 +364,46 @@ async function getRequest(url, options) {
553
364
  return await ajax('GET', url);
554
365
  }
555
366
 
367
+ let endpointUrl = '';
368
+ const generateUrl = (path) => {
369
+ const endpoint = getUrl();
370
+ if (!endpoint) {
371
+ log('URL is not valid');
372
+ return '';
373
+ }
374
+ return `${endpoint}${path}`;
375
+ };
376
+ const getUrl = () => {
377
+ return endpointUrl;
378
+ };
379
+ const setUrl = (url) => {
380
+ if (url == null) {
381
+ return;
382
+ }
383
+ endpointUrl = url;
384
+ };
385
+ const getTagURL = () => {
386
+ return generateUrl('/tag');
387
+ };
388
+ const getInitURL = () => {
389
+ return generateUrl('/init');
390
+ };
391
+ const getConsentURL = () => {
392
+ return generateUrl('/consent');
393
+ };
394
+ const getUserURL = () => {
395
+ return generateUrl('/user');
396
+ };
397
+ const getDataURL = () => {
398
+ return generateUrl(`/data`);
399
+ };
400
+ const getGetDataURL = (keys) => {
401
+ return generateUrl(`/data?keys=${encodeURIComponent(keys.join(','))}`);
402
+ };
403
+ const getKeysURL = () => {
404
+ return generateUrl(`/keys`);
405
+ };
406
+
556
407
  let memoryConsent;
557
408
  const saveConsent = (consent) => {
558
409
  setConsent(consent);
@@ -578,6 +429,53 @@ const getConsent = () => {
578
429
  return memoryConsent;
579
430
  };
580
431
 
432
+ const allowedProvider = new Set();
433
+ let initialized = false;
434
+ const providersPackages = {};
435
+ const setPreferences = (preferences) => {
436
+ var _a;
437
+ if (!preferences) {
438
+ return false;
439
+ }
440
+ if (!preferences.edgeURL) {
441
+ error('Please provide URL for EdgeTag');
442
+ return false;
443
+ }
444
+ !!preferences.disableConsentCheck;
445
+ (_a = preferences.providers) === null || _a === void 0 ? void 0 : _a.forEach((provider) => {
446
+ if (!provider.name) {
447
+ return;
448
+ }
449
+ providersPackages[provider.name] = provider;
450
+ });
451
+ try {
452
+ if (window && Array.isArray(window.edgetagProviders)) {
453
+ window.edgetagProviders.forEach((provider) => {
454
+ if (!provider.name) {
455
+ return;
456
+ }
457
+ providersPackages[provider.name] = provider;
458
+ });
459
+ }
460
+ }
461
+ catch {
462
+ // do nothing
463
+ }
464
+ setUrl(preferences.edgeURL);
465
+ return true;
466
+ };
467
+ const getProvidersPackage = () => providersPackages;
468
+ const isInitialized = () => initialized;
469
+ const setInitialized = () => {
470
+ initialized = true;
471
+ };
472
+ const getAllowedProviders = () => allowedProvider;
473
+ const setAllowedProviders = (providers) => {
474
+ for (const provider of providers) {
475
+ allowedProvider.add(provider);
476
+ }
477
+ };
478
+
581
479
  const manifestVariables = {};
582
480
  const addProviderVariable = (name, variables, tagName) => {
583
481
  manifestVariables[name] = {
@@ -611,11 +509,60 @@ const processStubs = () => {
611
509
  }
612
510
  };
613
511
 
614
- const sendTag = ({ eventName, eventId, data, providerData, providers, options, }) => {
615
- if (!allowProviders(providers)) {
616
- log('Provider is not allowed.');
617
- return;
512
+ const isBool = (v) => typeof v == 'boolean';
513
+ const isRecord = (v) => !!v && typeof v == 'object';
514
+ /**
515
+ * This function validates user consent for a given provider and tag name.
516
+ * It should be used in conjunction with `UserConsent`, not `ProvidersConfig`.
517
+ */
518
+ const hasUserConsent = (consent, provider, tagName) => {
519
+ if (!isRecord(consent)) {
520
+ return false;
521
+ }
522
+ let allowed = isBool(consent.all) ? consent.all : false;
523
+ if (provider in consent) {
524
+ const providerSpecific = consent[provider];
525
+ if (isBool(providerSpecific)) {
526
+ allowed = providerSpecific;
527
+ }
528
+ else if (isRecord(providerSpecific)) {
529
+ if ('all' in providerSpecific && isBool(providerSpecific.all)) {
530
+ allowed = providerSpecific.all;
531
+ }
532
+ if (tagName in providerSpecific && isBool(providerSpecific[tagName])) {
533
+ allowed = providerSpecific[tagName];
534
+ }
535
+ }
536
+ }
537
+ return allowed;
538
+ };
539
+ /**
540
+ * This function validates provider allowance for a given provider and tag name.
541
+ * It should not be used to validate `UserConsent`.
542
+ */
543
+ const isProviderInstanceAllowed = (providersConfig, provider, tagName) => {
544
+ if (!isRecord(providersConfig)) {
545
+ return true;
618
546
  }
547
+ let allowed = isBool(providersConfig.all) ? providersConfig.all : true;
548
+ if (provider in providersConfig) {
549
+ const providerSpecific = providersConfig[provider];
550
+ if (isBool(providerSpecific)) {
551
+ allowed = providerSpecific;
552
+ }
553
+ else if (isRecord(providerSpecific)) {
554
+ if ('all' in providerSpecific && isBool(providerSpecific.all)) {
555
+ allowed = providerSpecific.all;
556
+ }
557
+ if (tagName in providerSpecific && isBool(providerSpecific[tagName])) {
558
+ allowed = providerSpecific[tagName];
559
+ }
560
+ }
561
+ }
562
+ return allowed;
563
+ };
564
+
565
+ const sendTag = ({ eventName, eventId, data, providerData, providers, options, }) => {
619
566
  const payload = {
620
567
  eventName,
621
568
  eventId,
@@ -636,14 +583,6 @@ const handleTag = (eventName, data = {}, providers, options) => {
636
583
  });
637
584
  return;
638
585
  }
639
- if (!allowProviders(providers)) {
640
- log('Provider is not allowed.');
641
- return;
642
- }
643
- if (!allowTag(providers)) {
644
- log('Consent is missing.');
645
- return;
646
- }
647
586
  let eventId = data['eventId'];
648
587
  if (!eventId) {
649
588
  eventId = generateEventId(eventName);
@@ -651,18 +590,32 @@ const handleTag = (eventName, data = {}, providers, options) => {
651
590
  const providerPackages = getProvidersPackage();
652
591
  const userId = handleGetUserId();
653
592
  const providerData = {};
593
+ const consent = getConsent();
594
+ const allowedProviders = getAllowedProviders();
595
+ let anyProviderCalled = false;
654
596
  if (providerPackages) {
655
- Object.values(providerPackages).forEach((pkg) => {
656
- if (!pkg ||
657
- !pkg.name ||
658
- !pkg.tag ||
659
- !checkProviderConsent(pkg.name) ||
660
- !allowProviderWithConsent(providers, pkg.name)) {
661
- return;
597
+ for (const pkg of Object.values(providerPackages)) {
598
+ if (!pkg || !pkg.name || !pkg.tag) {
599
+ continue;
600
+ }
601
+ if (!allowedProviders.has(pkg.name)) {
602
+ log(`Provider ${pkg.name} is not in allow list`);
603
+ continue;
662
604
  }
663
605
  const variables = getProviderVariables(pkg.name);
664
606
  const result = {};
665
- for (const [tagName, variableSet] of Object.entries(variables)) {
607
+ const providerVariables = Object.entries(variables);
608
+ const executionContext = new Map();
609
+ for (const [tagName, variableSet] of providerVariables) {
610
+ if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
611
+ log(`Provider instance is not allowed (${pkg.name}: ${tagName})`);
612
+ continue;
613
+ }
614
+ if (!hasUserConsent(consent, pkg.name, tagName)) {
615
+ log(`Consent is missing (${pkg.name}: ${tagName})`);
616
+ continue;
617
+ }
618
+ anyProviderCalled = true;
666
619
  result[tagName] = pkg.tag({
667
620
  userId,
668
621
  eventName,
@@ -670,10 +623,14 @@ const handleTag = (eventName, data = {}, providers, options) => {
670
623
  data: JSON.parse(JSON.stringify(data)),
671
624
  sendTag,
672
625
  manifestVariables: variableSet,
626
+ executionContext,
673
627
  });
674
628
  }
675
629
  providerData[pkg.name] = result;
676
- });
630
+ }
631
+ }
632
+ if (!anyProviderCalled) {
633
+ return;
677
634
  }
678
635
  sendTag({
679
636
  eventName,
@@ -693,23 +650,34 @@ const handleData = (data, providers, options) => {
693
650
  saveKV(data);
694
651
  const providerPackages = getProvidersPackage();
695
652
  const userId = handleGetUserId();
653
+ const consent = getConsent();
654
+ const allowedProviders = getAllowedProviders();
696
655
  if (providerPackages) {
697
- Object.values(providerPackages).forEach((pkg) => {
698
- if (!pkg ||
699
- !pkg.user ||
700
- !pkg.name ||
701
- !allowProviderWithConsent(providers, pkg.name)) {
702
- return;
656
+ for (const pkg of Object.values(providerPackages)) {
657
+ if (!pkg || !pkg.user || !pkg.name) {
658
+ continue;
659
+ }
660
+ if (!allowedProviders.has(pkg.name)) {
661
+ log(`Provider ${pkg.name} is not in allow list`);
662
+ continue;
703
663
  }
704
664
  const variables = getProviderVariables(pkg.name);
705
- for (const variableSet of Object.values(variables)) {
665
+ for (const [tagName, variableSet] of Object.entries(variables)) {
666
+ if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
667
+ log(`Data not allowed for ${pkg.name} (${tagName})`);
668
+ continue;
669
+ }
670
+ if (!hasUserConsent(consent, pkg.name, tagName)) {
671
+ log(`Consent is missing for ${pkg.name} (${tagName})`);
672
+ continue;
673
+ }
706
674
  pkg.user({
707
675
  userId,
708
676
  data,
709
677
  manifestVariables: variableSet,
710
678
  });
711
679
  }
712
- });
680
+ }
713
681
  }
714
682
  postRequest(getDataURL(), { data, providers }, options).catch(error);
715
683
  };
@@ -826,16 +794,15 @@ const handleManifest = (manifest) => {
826
794
  }
827
795
  if (providerPackages) {
828
796
  const pkg = providerPackages[provider.package];
829
- if (pkg && pkg.name && pkg.init && allowProvider(pkg.name)) {
830
- const initData = {
797
+ if (pkg && pkg.name && pkg.init) {
798
+ pkg.init({
831
799
  userId,
832
800
  manifest: provider,
833
801
  sendTag,
834
802
  sendEdgeData: handleData,
835
803
  getEdgeData: handleGetData,
836
804
  keyName: `${keyPrefix}Store`,
837
- };
838
- pkg.init(initData);
805
+ });
839
806
  }
840
807
  }
841
808
  });
@@ -886,25 +853,37 @@ const handleUser = (key, value, providers, options) => {
886
853
  saveKV({
887
854
  [key]: value,
888
855
  });
856
+ const consent = getConsent();
857
+ const allowedProviders = getAllowedProviders();
889
858
  const providerPackages = getProvidersPackage();
890
859
  const userId = handleGetUserId();
891
860
  if (providerPackages) {
892
- Object.values(providerPackages).forEach((pkg) => {
893
- if (!pkg ||
894
- !pkg.name ||
895
- !pkg.user ||
896
- !allowProviderWithConsent(providers, pkg.name)) {
897
- return;
861
+ for (const pkg of Object.values(providerPackages)) {
862
+ if (!pkg || !pkg.name || !pkg.user) {
863
+ continue;
864
+ }
865
+ if (!allowedProviders.has(pkg.name)) {
866
+ log(`Provider ${pkg.name} is not in allow list`);
867
+ continue;
898
868
  }
899
869
  const variables = getProviderVariables(pkg.name);
900
- for (const variableSet of Object.values(variables)) {
870
+ for (const [tagName, variableSet] of Object.entries(variables)) {
871
+ if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
872
+ // should we be logging this?
873
+ log(`User not allowed for ${pkg.name} (${tagName})`);
874
+ continue;
875
+ }
876
+ if (!hasUserConsent(consent, pkg.name, tagName)) {
877
+ log(`User doesn't have consent for ${pkg.name} (${tagName})`);
878
+ continue;
879
+ }
901
880
  pkg.user({
902
881
  userId,
903
882
  data: { [key]: value },
904
883
  manifestVariables: variableSet,
905
884
  });
906
885
  }
907
- });
886
+ }
908
887
  }
909
888
  postRequest(getUserURL(), {
910
889
  key,
@@ -927,14 +906,14 @@ const init = (preferences) => {
927
906
  const tag = (name, data, providers, options) => {
928
907
  handleTag(name, data, providers, options);
929
908
  };
930
- const consent = (consent, options) => {
931
- handleConsent(consent, options);
909
+ const consent = (value, options) => {
910
+ handleConsent(value, options);
932
911
  };
933
912
  const user = (key, value, providers, options) => {
934
913
  handleUser(key, value, providers, options);
935
914
  };
936
- const data = (data, providers, options) => {
937
- handleData(data, providers, options);
915
+ const data = (value, providers, options) => {
916
+ handleData(value, providers, options);
938
917
  };
939
918
  const getData = (keys, callback) => {
940
919
  handleGetData(keys, callback);
package/internal.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Library } from '@blotoutio/cdn/types'
1
+ import { Library, ProvidersConfig, UserConsent } from '@blotoutio/cdn/types'
2
2
  import { UserKey, Data } from './index'
3
3
 
4
4
  type Navigator = {
@@ -11,22 +11,22 @@ type TagPayload = {
11
11
  timestamp: number
12
12
  providerData?: Partial<Record<Library, Record<string, Data>>>
13
13
  data?: Data
14
- providers?: Data
14
+ providers?: ProvidersConfig | null | undefined
15
15
  }
16
16
 
17
17
  type ConsentPayload = {
18
- consentString: Data
18
+ consentString: UserConsent
19
19
  }
20
20
 
21
21
  type UserPayload = {
22
22
  key: UserKey
23
23
  value: string
24
- providers?: Data
24
+ providers?: ProvidersConfig | null | undefined
25
25
  }
26
26
 
27
27
  type DataPayload = {
28
28
  data: Record<string, string>
29
- providers?: Data
29
+ providers?: ProvidersConfig | null | undefined
30
30
  }
31
31
 
32
32
  type PostPayload = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blotoutio/edgetag-sdk-js",
3
- "version": "0.24.2",
3
+ "version": "0.26.0",
4
4
  "description": "JS SDK for EdgeTag",
5
5
  "author": "Blotout",
6
6
  "license": "MIT",