@blotoutio/providers-google-analytics-4-sdk 0.72.0 → 1.0.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 (4) hide show
  1. package/index.cjs.js +72 -10
  2. package/index.js +72 -10
  3. package/index.mjs +72 -10
  4. package/package.json +1 -1
package/index.cjs.js CHANGED
@@ -3,6 +3,40 @@
3
3
  const packageName = 'googleAnalytics4';
4
4
  const tagManagerUrl = 'https://www.googletagmanager.com/gtag/js';
5
5
 
6
+ const isBool = (v) => typeof v == 'boolean';
7
+ const isRecord = (v) => !!v && typeof v == 'object' && !Array.isArray(v);
8
+ /**
9
+ * This function validates user consent for a given provider type, not based on tagName.
10
+ */
11
+ const hasUserConsentForProvider = (consent, provider) => {
12
+ if (!isRecord(consent)) {
13
+ return false;
14
+ }
15
+ let allowed = isBool(consent.all) ? consent.all : false;
16
+ if (provider in consent) {
17
+ const providerSpecific = consent[provider];
18
+ if (isBool(providerSpecific)) {
19
+ allowed = providerSpecific;
20
+ }
21
+ else if (isRecord(providerSpecific)) {
22
+ return Object.keys(providerSpecific).some((instance) => providerSpecific[instance] === true);
23
+ }
24
+ }
25
+ return allowed;
26
+ };
27
+ const isCategoryConsented = (consentCategories, category) => {
28
+ if (!consentCategories)
29
+ return false;
30
+ let allowed = isBool(consentCategories.all) ? consentCategories.all : false;
31
+ if (category in consentCategories) {
32
+ const categorySpecific = consentCategories[category];
33
+ if (isBool(categorySpecific)) {
34
+ allowed = categorySpecific;
35
+ }
36
+ }
37
+ return allowed;
38
+ };
39
+
6
40
  const upsert = (map, key, update, createDefault) => {
7
41
  const currentValue = map.has(key)
8
42
  ? map.get(key)
@@ -304,7 +338,30 @@ const isoCountries = new Map([
304
338
  new Set(isoCountries.keys());
305
339
 
306
340
  // eslint-disable-next-line @nx/enforce-module-boundaries
307
- const initGA4 = (ID, executionContext) => {
341
+ const getGoogleConsentFromCategories = (categories) => {
342
+ const advertisingConsent = isCategoryConsented(categories, 'advertising');
343
+ const analyticsConsent = isCategoryConsented(categories, 'analytics');
344
+ return {
345
+ analytics_storage: analyticsConsent ? 'granted' : 'denied',
346
+ ad_storage: advertisingConsent ? 'granted' : 'denied',
347
+ ad_user_data: advertisingConsent ? 'granted' : 'denied',
348
+ ad_personalization: advertisingConsent ? 'granted' : 'denied',
349
+ };
350
+ };
351
+ // TODO: once categories becomes a stable field, we need to remove this and start using categories data for google consent mode.
352
+ const getGoogleConsentFromChannels = (consent) => {
353
+ const gadsConsent = hasUserConsentForProvider(consent, 'googleAdsClicks');
354
+ const ga4Consent = hasUserConsentForProvider(consent, 'googleAnalytics4');
355
+ return {
356
+ analytics_storage: ga4Consent ? 'granted' : 'denied',
357
+ ad_storage: gadsConsent ? 'granted' : 'denied',
358
+ ad_user_data: gadsConsent ? 'granted' : 'denied',
359
+ ad_personalization: gadsConsent ? 'granted' : 'denied',
360
+ };
361
+ };
362
+
363
+ // eslint-disable-next-line @nx/enforce-module-boundaries
364
+ const initGA4 = (ID, advancedConsentMode, consentData, executionContext) => {
308
365
  var _a;
309
366
  window.dataLayer = window.dataLayer || [];
310
367
  window.gtag = function gtag() {
@@ -318,14 +375,15 @@ const initGA4 = (ID, executionContext) => {
318
375
  break;
319
376
  }
320
377
  }
378
+ const data = advancedConsentMode === '1'
379
+ ? getGoogleConsentFromCategories(consentData.categories)
380
+ : getGoogleConsentFromChannels(consentData.consent);
321
381
  if (isConsentInitialised) {
322
- window.gtag('consent', 'update', {
323
- analytics_storage: 'granted',
324
- });
382
+ window.gtag('consent', 'update', data);
325
383
  }
326
384
  else {
327
385
  window.gtag('consent', 'default', {
328
- analytics_storage: 'granted',
386
+ ...data,
329
387
  functional_storage: 'granted',
330
388
  personalization_storage: 'granted',
331
389
  security_storage: 'granted',
@@ -343,7 +401,7 @@ const initGA4 = (ID, executionContext) => {
343
401
  script.parentNode.insertBefore(element, script);
344
402
  }
345
403
  };
346
- const init = ({ manifest, userId, executionContext }) => {
404
+ const init = ({ manifest, userId, executionContext, consentData, }) => {
347
405
  if (!window ||
348
406
  !manifest.variables ||
349
407
  !manifest.variables['measurementId'] ||
@@ -352,7 +410,7 @@ const init = ({ manifest, userId, executionContext }) => {
352
410
  }
353
411
  if (!window.google_tag_manager ||
354
412
  !window.google_tag_manager[manifest.variables['measurementId']]) {
355
- initGA4(manifest.variables['measurementId'], executionContext);
413
+ initGA4(manifest.variables['measurementId'], manifest.variables['advancedConsentMode'], consentData, executionContext);
356
414
  }
357
415
  if (window.gtag) {
358
416
  window.gtag('config', manifest.variables['measurementId'], {
@@ -613,16 +671,20 @@ const tag = ({ data, eventName, manifestVariables, eventId }) => {
613
671
  }
614
672
  return {
615
673
  loaded: isLoaded,
616
- sdkVersion: "0.72.0" ,
674
+ sdkVersion: "1.0.0" ,
617
675
  };
618
676
  };
619
677
 
620
- const consent = ({ hasConsent }) => {
678
+ const consent = ({ consentData, variables }) => {
621
679
  if (!(window === null || window === void 0 ? void 0 : window.gtag)) {
622
680
  return;
623
681
  }
682
+ const isAdvancedConsentModeEnabled = variables.some((variable) => { var _a; return ((_a = variable.variableSet) === null || _a === void 0 ? void 0 : _a['advancedConsentMode']) === '1'; });
683
+ const data = isAdvancedConsentModeEnabled
684
+ ? getGoogleConsentFromCategories(consentData.categories)
685
+ : getGoogleConsentFromChannels(consentData.consent);
624
686
  window.gtag('consent', 'update', {
625
- analytics_storage: hasConsent ? 'granted' : 'denied',
687
+ ...data,
626
688
  functional_storage: 'granted',
627
689
  personalization_storage: 'granted',
628
690
  security_storage: 'granted',
package/index.js CHANGED
@@ -4,6 +4,40 @@ var ProvidersGoogleAnalytics4Sdk = (function () {
4
4
  const packageName = 'googleAnalytics4';
5
5
  const tagManagerUrl = 'https://www.googletagmanager.com/gtag/js';
6
6
 
7
+ const isBool = (v) => typeof v == 'boolean';
8
+ const isRecord = (v) => !!v && typeof v == 'object' && !Array.isArray(v);
9
+ /**
10
+ * This function validates user consent for a given provider type, not based on tagName.
11
+ */
12
+ const hasUserConsentForProvider = (consent, provider) => {
13
+ if (!isRecord(consent)) {
14
+ return false;
15
+ }
16
+ let allowed = isBool(consent.all) ? consent.all : false;
17
+ if (provider in consent) {
18
+ const providerSpecific = consent[provider];
19
+ if (isBool(providerSpecific)) {
20
+ allowed = providerSpecific;
21
+ }
22
+ else if (isRecord(providerSpecific)) {
23
+ return Object.keys(providerSpecific).some((instance) => providerSpecific[instance] === true);
24
+ }
25
+ }
26
+ return allowed;
27
+ };
28
+ const isCategoryConsented = (consentCategories, category) => {
29
+ if (!consentCategories)
30
+ return false;
31
+ let allowed = isBool(consentCategories.all) ? consentCategories.all : false;
32
+ if (category in consentCategories) {
33
+ const categorySpecific = consentCategories[category];
34
+ if (isBool(categorySpecific)) {
35
+ allowed = categorySpecific;
36
+ }
37
+ }
38
+ return allowed;
39
+ };
40
+
7
41
  const upsert = (map, key, update, createDefault) => {
8
42
  const currentValue = map.has(key)
9
43
  ? map.get(key)
@@ -305,7 +339,30 @@ var ProvidersGoogleAnalytics4Sdk = (function () {
305
339
  new Set(isoCountries.keys());
306
340
 
307
341
  // eslint-disable-next-line @nx/enforce-module-boundaries
308
- const initGA4 = (ID, executionContext) => {
342
+ const getGoogleConsentFromCategories = (categories) => {
343
+ const advertisingConsent = isCategoryConsented(categories, 'advertising');
344
+ const analyticsConsent = isCategoryConsented(categories, 'analytics');
345
+ return {
346
+ analytics_storage: analyticsConsent ? 'granted' : 'denied',
347
+ ad_storage: advertisingConsent ? 'granted' : 'denied',
348
+ ad_user_data: advertisingConsent ? 'granted' : 'denied',
349
+ ad_personalization: advertisingConsent ? 'granted' : 'denied',
350
+ };
351
+ };
352
+ // TODO: once categories becomes a stable field, we need to remove this and start using categories data for google consent mode.
353
+ const getGoogleConsentFromChannels = (consent) => {
354
+ const gadsConsent = hasUserConsentForProvider(consent, 'googleAdsClicks');
355
+ const ga4Consent = hasUserConsentForProvider(consent, 'googleAnalytics4');
356
+ return {
357
+ analytics_storage: ga4Consent ? 'granted' : 'denied',
358
+ ad_storage: gadsConsent ? 'granted' : 'denied',
359
+ ad_user_data: gadsConsent ? 'granted' : 'denied',
360
+ ad_personalization: gadsConsent ? 'granted' : 'denied',
361
+ };
362
+ };
363
+
364
+ // eslint-disable-next-line @nx/enforce-module-boundaries
365
+ const initGA4 = (ID, advancedConsentMode, consentData, executionContext) => {
309
366
  var _a;
310
367
  window.dataLayer = window.dataLayer || [];
311
368
  window.gtag = function gtag() {
@@ -319,14 +376,15 @@ var ProvidersGoogleAnalytics4Sdk = (function () {
319
376
  break;
320
377
  }
321
378
  }
379
+ const data = advancedConsentMode === '1'
380
+ ? getGoogleConsentFromCategories(consentData.categories)
381
+ : getGoogleConsentFromChannels(consentData.consent);
322
382
  if (isConsentInitialised) {
323
- window.gtag('consent', 'update', {
324
- analytics_storage: 'granted',
325
- });
383
+ window.gtag('consent', 'update', data);
326
384
  }
327
385
  else {
328
386
  window.gtag('consent', 'default', {
329
- analytics_storage: 'granted',
387
+ ...data,
330
388
  functional_storage: 'granted',
331
389
  personalization_storage: 'granted',
332
390
  security_storage: 'granted',
@@ -344,7 +402,7 @@ var ProvidersGoogleAnalytics4Sdk = (function () {
344
402
  script.parentNode.insertBefore(element, script);
345
403
  }
346
404
  };
347
- const init = ({ manifest, userId, executionContext }) => {
405
+ const init = ({ manifest, userId, executionContext, consentData, }) => {
348
406
  if (!window ||
349
407
  !manifest.variables ||
350
408
  !manifest.variables['measurementId'] ||
@@ -353,7 +411,7 @@ var ProvidersGoogleAnalytics4Sdk = (function () {
353
411
  }
354
412
  if (!window.google_tag_manager ||
355
413
  !window.google_tag_manager[manifest.variables['measurementId']]) {
356
- initGA4(manifest.variables['measurementId'], executionContext);
414
+ initGA4(manifest.variables['measurementId'], manifest.variables['advancedConsentMode'], consentData, executionContext);
357
415
  }
358
416
  if (window.gtag) {
359
417
  window.gtag('config', manifest.variables['measurementId'], {
@@ -614,16 +672,20 @@ var ProvidersGoogleAnalytics4Sdk = (function () {
614
672
  }
615
673
  return {
616
674
  loaded: isLoaded,
617
- sdkVersion: "0.72.0" ,
675
+ sdkVersion: "1.0.0" ,
618
676
  };
619
677
  };
620
678
 
621
- const consent = ({ hasConsent }) => {
679
+ const consent = ({ consentData, variables }) => {
622
680
  if (!(window === null || window === void 0 ? void 0 : window.gtag)) {
623
681
  return;
624
682
  }
683
+ const isAdvancedConsentModeEnabled = variables.some((variable) => { var _a; return ((_a = variable.variableSet) === null || _a === void 0 ? void 0 : _a['advancedConsentMode']) === '1'; });
684
+ const data = isAdvancedConsentModeEnabled
685
+ ? getGoogleConsentFromCategories(consentData.categories)
686
+ : getGoogleConsentFromChannels(consentData.consent);
625
687
  window.gtag('consent', 'update', {
626
- analytics_storage: hasConsent ? 'granted' : 'denied',
688
+ ...data,
627
689
  functional_storage: 'granted',
628
690
  personalization_storage: 'granted',
629
691
  security_storage: 'granted',
package/index.mjs CHANGED
@@ -1,6 +1,40 @@
1
1
  const packageName = 'googleAnalytics4';
2
2
  const tagManagerUrl = 'https://www.googletagmanager.com/gtag/js';
3
3
 
4
+ const isBool = (v) => typeof v == 'boolean';
5
+ const isRecord = (v) => !!v && typeof v == 'object' && !Array.isArray(v);
6
+ /**
7
+ * This function validates user consent for a given provider type, not based on tagName.
8
+ */
9
+ const hasUserConsentForProvider = (consent, provider) => {
10
+ if (!isRecord(consent)) {
11
+ return false;
12
+ }
13
+ let allowed = isBool(consent.all) ? consent.all : false;
14
+ if (provider in consent) {
15
+ const providerSpecific = consent[provider];
16
+ if (isBool(providerSpecific)) {
17
+ allowed = providerSpecific;
18
+ }
19
+ else if (isRecord(providerSpecific)) {
20
+ return Object.keys(providerSpecific).some((instance) => providerSpecific[instance] === true);
21
+ }
22
+ }
23
+ return allowed;
24
+ };
25
+ const isCategoryConsented = (consentCategories, category) => {
26
+ if (!consentCategories)
27
+ return false;
28
+ let allowed = isBool(consentCategories.all) ? consentCategories.all : false;
29
+ if (category in consentCategories) {
30
+ const categorySpecific = consentCategories[category];
31
+ if (isBool(categorySpecific)) {
32
+ allowed = categorySpecific;
33
+ }
34
+ }
35
+ return allowed;
36
+ };
37
+
4
38
  const upsert = (map, key, update, createDefault) => {
5
39
  const currentValue = map.has(key)
6
40
  ? map.get(key)
@@ -302,7 +336,30 @@ const isoCountries = new Map([
302
336
  new Set(isoCountries.keys());
303
337
 
304
338
  // eslint-disable-next-line @nx/enforce-module-boundaries
305
- const initGA4 = (ID, executionContext) => {
339
+ const getGoogleConsentFromCategories = (categories) => {
340
+ const advertisingConsent = isCategoryConsented(categories, 'advertising');
341
+ const analyticsConsent = isCategoryConsented(categories, 'analytics');
342
+ return {
343
+ analytics_storage: analyticsConsent ? 'granted' : 'denied',
344
+ ad_storage: advertisingConsent ? 'granted' : 'denied',
345
+ ad_user_data: advertisingConsent ? 'granted' : 'denied',
346
+ ad_personalization: advertisingConsent ? 'granted' : 'denied',
347
+ };
348
+ };
349
+ // TODO: once categories becomes a stable field, we need to remove this and start using categories data for google consent mode.
350
+ const getGoogleConsentFromChannels = (consent) => {
351
+ const gadsConsent = hasUserConsentForProvider(consent, 'googleAdsClicks');
352
+ const ga4Consent = hasUserConsentForProvider(consent, 'googleAnalytics4');
353
+ return {
354
+ analytics_storage: ga4Consent ? 'granted' : 'denied',
355
+ ad_storage: gadsConsent ? 'granted' : 'denied',
356
+ ad_user_data: gadsConsent ? 'granted' : 'denied',
357
+ ad_personalization: gadsConsent ? 'granted' : 'denied',
358
+ };
359
+ };
360
+
361
+ // eslint-disable-next-line @nx/enforce-module-boundaries
362
+ const initGA4 = (ID, advancedConsentMode, consentData, executionContext) => {
306
363
  var _a;
307
364
  window.dataLayer = window.dataLayer || [];
308
365
  window.gtag = function gtag() {
@@ -316,14 +373,15 @@ const initGA4 = (ID, executionContext) => {
316
373
  break;
317
374
  }
318
375
  }
376
+ const data = advancedConsentMode === '1'
377
+ ? getGoogleConsentFromCategories(consentData.categories)
378
+ : getGoogleConsentFromChannels(consentData.consent);
319
379
  if (isConsentInitialised) {
320
- window.gtag('consent', 'update', {
321
- analytics_storage: 'granted',
322
- });
380
+ window.gtag('consent', 'update', data);
323
381
  }
324
382
  else {
325
383
  window.gtag('consent', 'default', {
326
- analytics_storage: 'granted',
384
+ ...data,
327
385
  functional_storage: 'granted',
328
386
  personalization_storage: 'granted',
329
387
  security_storage: 'granted',
@@ -341,7 +399,7 @@ const initGA4 = (ID, executionContext) => {
341
399
  script.parentNode.insertBefore(element, script);
342
400
  }
343
401
  };
344
- const init = ({ manifest, userId, executionContext }) => {
402
+ const init = ({ manifest, userId, executionContext, consentData, }) => {
345
403
  if (!window ||
346
404
  !manifest.variables ||
347
405
  !manifest.variables['measurementId'] ||
@@ -350,7 +408,7 @@ const init = ({ manifest, userId, executionContext }) => {
350
408
  }
351
409
  if (!window.google_tag_manager ||
352
410
  !window.google_tag_manager[manifest.variables['measurementId']]) {
353
- initGA4(manifest.variables['measurementId'], executionContext);
411
+ initGA4(manifest.variables['measurementId'], manifest.variables['advancedConsentMode'], consentData, executionContext);
354
412
  }
355
413
  if (window.gtag) {
356
414
  window.gtag('config', manifest.variables['measurementId'], {
@@ -611,16 +669,20 @@ const tag = ({ data, eventName, manifestVariables, eventId }) => {
611
669
  }
612
670
  return {
613
671
  loaded: isLoaded,
614
- sdkVersion: "0.72.0" ,
672
+ sdkVersion: "1.0.0" ,
615
673
  };
616
674
  };
617
675
 
618
- const consent = ({ hasConsent }) => {
676
+ const consent = ({ consentData, variables }) => {
619
677
  if (!(window === null || window === void 0 ? void 0 : window.gtag)) {
620
678
  return;
621
679
  }
680
+ const isAdvancedConsentModeEnabled = variables.some((variable) => { var _a; return ((_a = variable.variableSet) === null || _a === void 0 ? void 0 : _a['advancedConsentMode']) === '1'; });
681
+ const data = isAdvancedConsentModeEnabled
682
+ ? getGoogleConsentFromCategories(consentData.categories)
683
+ : getGoogleConsentFromChannels(consentData.consent);
622
684
  window.gtag('consent', 'update', {
623
- analytics_storage: hasConsent ? 'granted' : 'denied',
685
+ ...data,
624
686
  functional_storage: 'granted',
625
687
  personalization_storage: 'granted',
626
688
  security_storage: 'granted',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blotoutio/providers-google-analytics-4-sdk",
3
- "version": "0.72.0",
3
+ "version": "1.0.0",
4
4
  "description": "Google Analytics 4 Browser SDK for EdgeTag",
5
5
  "author": "Blotout",
6
6
  "license": "MIT",