@blotoutio/edgetag-sdk-js 0.25.0 → 0.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.25.0" ,
326
+ sdkVersion: "0.26.1" ,
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,31 @@ 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
+ continue;
664
605
  }
665
606
  const variables = getProviderVariables(pkg.name);
666
607
  const result = {};
667
- for (const [tagName, variableSet] of Object.entries(variables)) {
608
+ const providerVariables = Object.entries(variables);
609
+ const executionContext = new Map();
610
+ for (const [tagName, variableSet] of providerVariables) {
611
+ if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
612
+ log(`Provider instance is not allowed (${pkg.name}: ${tagName})`);
613
+ continue;
614
+ }
615
+ if (!hasUserConsent(consent, pkg.name, tagName)) {
616
+ log(`Consent is missing (${pkg.name}: ${tagName})`);
617
+ continue;
618
+ }
619
+ anyProviderCalled = true;
668
620
  result[tagName] = pkg.tag({
669
621
  userId,
670
622
  eventName,
@@ -672,10 +624,14 @@ const handleTag = (eventName, data = {}, providers, options) => {
672
624
  data: JSON.parse(JSON.stringify(data)),
673
625
  sendTag,
674
626
  manifestVariables: variableSet,
627
+ executionContext,
675
628
  });
676
629
  }
677
630
  providerData[pkg.name] = result;
678
- });
631
+ }
632
+ }
633
+ if (!anyProviderCalled) {
634
+ return;
679
635
  }
680
636
  sendTag({
681
637
  eventName,
@@ -695,23 +651,33 @@ const handleData = (data, providers, options) => {
695
651
  saveKV(data);
696
652
  const providerPackages = getProvidersPackage();
697
653
  const userId = handleGetUserId();
654
+ const consent = getConsent();
655
+ const allowedProviders = getAllowedProviders();
698
656
  if (providerPackages) {
699
- Object.values(providerPackages).forEach((pkg) => {
700
- if (!pkg ||
701
- !pkg.user ||
702
- !pkg.name ||
703
- !allowProviderWithConsent(providers, pkg.name)) {
704
- return;
657
+ for (const pkg of Object.values(providerPackages)) {
658
+ if (!pkg || !pkg.user || !pkg.name) {
659
+ continue;
660
+ }
661
+ if (!allowedProviders.has(pkg.name)) {
662
+ continue;
705
663
  }
706
664
  const variables = getProviderVariables(pkg.name);
707
- 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
+ }
708
674
  pkg.user({
709
675
  userId,
710
676
  data,
711
677
  manifestVariables: variableSet,
712
678
  });
713
679
  }
714
- });
680
+ }
715
681
  }
716
682
  postRequest(getDataURL(), { data, providers }, options).catch(error);
717
683
  };
@@ -828,16 +794,15 @@ const handleManifest = (manifest) => {
828
794
  }
829
795
  if (providerPackages) {
830
796
  const pkg = providerPackages[provider.package];
831
- if (pkg && pkg.name && pkg.init && allowProvider(pkg.name)) {
832
- const initData = {
797
+ if (pkg && pkg.name && pkg.init) {
798
+ pkg.init({
833
799
  userId,
834
800
  manifest: provider,
835
801
  sendTag,
836
802
  sendEdgeData: handleData,
837
803
  getEdgeData: handleGetData,
838
804
  keyName: `${keyPrefix}Store`,
839
- };
840
- pkg.init(initData);
805
+ });
841
806
  }
842
807
  }
843
808
  });
@@ -888,25 +853,36 @@ const handleUser = (key, value, providers, options) => {
888
853
  saveKV({
889
854
  [key]: value,
890
855
  });
856
+ const consent = getConsent();
857
+ const allowedProviders = getAllowedProviders();
891
858
  const providerPackages = getProvidersPackage();
892
859
  const userId = handleGetUserId();
893
860
  if (providerPackages) {
894
- Object.values(providerPackages).forEach((pkg) => {
895
- if (!pkg ||
896
- !pkg.name ||
897
- !pkg.user ||
898
- !allowProviderWithConsent(providers, pkg.name)) {
899
- 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
+ continue;
900
867
  }
901
868
  const variables = getProviderVariables(pkg.name);
902
- for (const variableSet of Object.values(variables)) {
869
+ for (const [tagName, variableSet] of Object.entries(variables)) {
870
+ if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
871
+ // should we be logging this?
872
+ log(`User not allowed for ${pkg.name} (${tagName})`);
873
+ continue;
874
+ }
875
+ if (!hasUserConsent(consent, pkg.name, tagName)) {
876
+ log(`User doesn't have consent for ${pkg.name} (${tagName})`);
877
+ continue;
878
+ }
903
879
  pkg.user({
904
880
  userId,
905
881
  data: { [key]: value },
906
882
  manifestVariables: variableSet,
907
883
  });
908
884
  }
909
- });
885
+ }
910
886
  }
911
887
  postRequest(getUserURL(), {
912
888
  key,
@@ -929,14 +905,14 @@ const init = (preferences) => {
929
905
  const tag = (name, data, providers, options) => {
930
906
  handleTag(name, data, providers, options);
931
907
  };
932
- const consent = (consent, options) => {
933
- handleConsent(consent, options);
908
+ const consent = (value, options) => {
909
+ handleConsent(value, options);
934
910
  };
935
911
  const user = (key, value, providers, options) => {
936
912
  handleUser(key, value, providers, options);
937
913
  };
938
- const data = (data, providers, options) => {
939
- handleData(data, providers, options);
914
+ const data = (value, providers, options) => {
915
+ handleData(value, providers, options);
940
916
  };
941
917
  const getData = (keys, callback) => {
942
918
  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.25.0" ,
324
+ sdkVersion: "0.26.1" ,
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,31 @@ 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
+ continue;
662
603
  }
663
604
  const variables = getProviderVariables(pkg.name);
664
605
  const result = {};
665
- for (const [tagName, variableSet] of Object.entries(variables)) {
606
+ const providerVariables = Object.entries(variables);
607
+ const executionContext = new Map();
608
+ for (const [tagName, variableSet] of providerVariables) {
609
+ if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
610
+ log(`Provider instance is not allowed (${pkg.name}: ${tagName})`);
611
+ continue;
612
+ }
613
+ if (!hasUserConsent(consent, pkg.name, tagName)) {
614
+ log(`Consent is missing (${pkg.name}: ${tagName})`);
615
+ continue;
616
+ }
617
+ anyProviderCalled = true;
666
618
  result[tagName] = pkg.tag({
667
619
  userId,
668
620
  eventName,
@@ -670,10 +622,14 @@ const handleTag = (eventName, data = {}, providers, options) => {
670
622
  data: JSON.parse(JSON.stringify(data)),
671
623
  sendTag,
672
624
  manifestVariables: variableSet,
625
+ executionContext,
673
626
  });
674
627
  }
675
628
  providerData[pkg.name] = result;
676
- });
629
+ }
630
+ }
631
+ if (!anyProviderCalled) {
632
+ return;
677
633
  }
678
634
  sendTag({
679
635
  eventName,
@@ -693,23 +649,33 @@ const handleData = (data, providers, options) => {
693
649
  saveKV(data);
694
650
  const providerPackages = getProvidersPackage();
695
651
  const userId = handleGetUserId();
652
+ const consent = getConsent();
653
+ const allowedProviders = getAllowedProviders();
696
654
  if (providerPackages) {
697
- Object.values(providerPackages).forEach((pkg) => {
698
- if (!pkg ||
699
- !pkg.user ||
700
- !pkg.name ||
701
- !allowProviderWithConsent(providers, pkg.name)) {
702
- return;
655
+ for (const pkg of Object.values(providerPackages)) {
656
+ if (!pkg || !pkg.user || !pkg.name) {
657
+ continue;
658
+ }
659
+ if (!allowedProviders.has(pkg.name)) {
660
+ continue;
703
661
  }
704
662
  const variables = getProviderVariables(pkg.name);
705
- for (const variableSet of Object.values(variables)) {
663
+ for (const [tagName, variableSet] of Object.entries(variables)) {
664
+ if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
665
+ log(`Data not allowed for ${pkg.name} (${tagName})`);
666
+ continue;
667
+ }
668
+ if (!hasUserConsent(consent, pkg.name, tagName)) {
669
+ log(`Consent is missing for ${pkg.name} (${tagName})`);
670
+ continue;
671
+ }
706
672
  pkg.user({
707
673
  userId,
708
674
  data,
709
675
  manifestVariables: variableSet,
710
676
  });
711
677
  }
712
- });
678
+ }
713
679
  }
714
680
  postRequest(getDataURL(), { data, providers }, options).catch(error);
715
681
  };
@@ -826,16 +792,15 @@ const handleManifest = (manifest) => {
826
792
  }
827
793
  if (providerPackages) {
828
794
  const pkg = providerPackages[provider.package];
829
- if (pkg && pkg.name && pkg.init && allowProvider(pkg.name)) {
830
- const initData = {
795
+ if (pkg && pkg.name && pkg.init) {
796
+ pkg.init({
831
797
  userId,
832
798
  manifest: provider,
833
799
  sendTag,
834
800
  sendEdgeData: handleData,
835
801
  getEdgeData: handleGetData,
836
802
  keyName: `${keyPrefix}Store`,
837
- };
838
- pkg.init(initData);
803
+ });
839
804
  }
840
805
  }
841
806
  });
@@ -886,25 +851,36 @@ const handleUser = (key, value, providers, options) => {
886
851
  saveKV({
887
852
  [key]: value,
888
853
  });
854
+ const consent = getConsent();
855
+ const allowedProviders = getAllowedProviders();
889
856
  const providerPackages = getProvidersPackage();
890
857
  const userId = handleGetUserId();
891
858
  if (providerPackages) {
892
- Object.values(providerPackages).forEach((pkg) => {
893
- if (!pkg ||
894
- !pkg.name ||
895
- !pkg.user ||
896
- !allowProviderWithConsent(providers, pkg.name)) {
897
- return;
859
+ for (const pkg of Object.values(providerPackages)) {
860
+ if (!pkg || !pkg.name || !pkg.user) {
861
+ continue;
862
+ }
863
+ if (!allowedProviders.has(pkg.name)) {
864
+ continue;
898
865
  }
899
866
  const variables = getProviderVariables(pkg.name);
900
- for (const variableSet of Object.values(variables)) {
867
+ for (const [tagName, variableSet] of Object.entries(variables)) {
868
+ if (!isProviderInstanceAllowed(providers, pkg.name, tagName)) {
869
+ // should we be logging this?
870
+ log(`User not allowed for ${pkg.name} (${tagName})`);
871
+ continue;
872
+ }
873
+ if (!hasUserConsent(consent, pkg.name, tagName)) {
874
+ log(`User doesn't have consent for ${pkg.name} (${tagName})`);
875
+ continue;
876
+ }
901
877
  pkg.user({
902
878
  userId,
903
879
  data: { [key]: value },
904
880
  manifestVariables: variableSet,
905
881
  });
906
882
  }
907
- });
883
+ }
908
884
  }
909
885
  postRequest(getUserURL(), {
910
886
  key,
@@ -927,14 +903,14 @@ const init = (preferences) => {
927
903
  const tag = (name, data, providers, options) => {
928
904
  handleTag(name, data, providers, options);
929
905
  };
930
- const consent = (consent, options) => {
931
- handleConsent(consent, options);
906
+ const consent = (value, options) => {
907
+ handleConsent(value, options);
932
908
  };
933
909
  const user = (key, value, providers, options) => {
934
910
  handleUser(key, value, providers, options);
935
911
  };
936
- const data = (data, providers, options) => {
937
- handleData(data, providers, options);
912
+ const data = (value, providers, options) => {
913
+ handleData(value, providers, options);
938
914
  };
939
915
  const getData = (keys, callback) => {
940
916
  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.25.0",
3
+ "version": "0.26.1",
4
4
  "description": "JS SDK for EdgeTag",
5
5
  "author": "Blotout",
6
6
  "license": "MIT",