diff --git a/packages/react/src/analytics/integrations/GA4/GA4.ts b/packages/react/src/analytics/integrations/GA4/GA4.ts index 2cf194e71..cce3d7b31 100644 --- a/packages/react/src/analytics/integrations/GA4/GA4.ts +++ b/packages/react/src/analytics/integrations/GA4/GA4.ts @@ -183,6 +183,25 @@ class GA4 extends integrations.Integration { return this; } + /** + * Method to check if the integration is ready to be loaded. + * + * @param consent - User consent data. + * @param options - Options passed for the GA4 integration. + * + * @returns If the integration is ready to be loaded. + */ + static override shouldLoad( + consent: ConsentData, + options: GA4IntegrationOptions, + ) { + if (get(options, `${OPTION_GOOGLE_CONSENT_CONFIG}.mode`) === 'Advanced') { + return true; + } + + return super.shouldLoad(consent, options); + } + /** * Send page events to GA4. * diff --git a/packages/react/src/analytics/integrations/GA4/__tests__/GA4.test.ts b/packages/react/src/analytics/integrations/GA4/__tests__/GA4.test.ts index e8b1b591c..d04b8ccaa 100644 --- a/packages/react/src/analytics/integrations/GA4/__tests__/GA4.test.ts +++ b/packages/react/src/analytics/integrations/GA4/__tests__/GA4.test.ts @@ -90,6 +90,10 @@ function getWindowGa4Spy() { } describe('GA4 Integration', () => { + const validOptions = { + measurementId: 'GA-123456-12', + }; + beforeEach(() => { jest.clearAllMocks(); }); @@ -99,21 +103,39 @@ describe('GA4 Integration', () => { }); it('`shouldLoad` should return false if there is no user consent', () => { - expect(GA4.shouldLoad({ statistics: false }, {})).toBe(false); - expect(GA4.shouldLoad({}, {})).toBe(false); + expect(GA4.shouldLoad({ statistics: false }, { ...validOptions })).toBe( + false, + ); + expect(GA4.shouldLoad({}, { ...validOptions })).toBe(false); }); it('`shouldLoad` should return true if there is user consent', () => { - expect(GA4.shouldLoad({ statistics: true }, {})).toBe(true); + expect(GA4.shouldLoad({ statistics: true }, { ...validOptions })).toBe( + true, + ); + }); + + it('`shouldLoad` should return true if there google consent mode was assigned in advancedMode', () => { + expect( + GA4.shouldLoad( + {}, + { + ...validOptions, + googleConsentConfig: { + ad_personalization: {}, + ad_storage: {}, + ad_user_data: {}, + analytics_storage: {}, + mode: 'Advanced', + }, + }, + ), + ).toBe(true); }); describe('GA4 instance', () => { let ga4Instance; - const validOptions = { - measurementId: 'GA-123456-12', - }; - const loadData: LoadIntegrationEventData = { ...loadIntegrationData, user: { diff --git a/packages/react/src/analytics/integrations/shared/GoogleConsentMode/GoogleConsentMode.ts b/packages/react/src/analytics/integrations/shared/GoogleConsentMode/GoogleConsentMode.ts index 1a41c7b8f..4e14b5c75 100644 --- a/packages/react/src/analytics/integrations/shared/GoogleConsentMode/GoogleConsentMode.ts +++ b/packages/react/src/analytics/integrations/shared/GoogleConsentMode/GoogleConsentMode.ts @@ -12,7 +12,7 @@ import { isEqual, omit } from 'lodash-es'; export class GoogleConsentMode { private dataLayer!: string; // Stores different data layer names private config?: GoogleConsentModeConfig; // Stores default or customized consent category mappings - private configExcludingRegionsAndWaitForUpdate!: Record< + private configExcludingModeRegionsAndWaitForUpdate!: Record< string, GoogleConsentCategoryConfig >; // exclude not consent properties from config @@ -30,9 +30,10 @@ export class GoogleConsentMode { this.config = config; // select only the Google Consent Elements - this.configExcludingRegionsAndWaitForUpdate = omit(this.config || {}, [ + this.configExcludingModeRegionsAndWaitForUpdate = omit(this.config || {}, [ 'waitForUpdate', 'regions', + 'mode', ]); this.loadDefaults(initConsent); @@ -52,13 +53,13 @@ export class GoogleConsentMode { // Obtain default google consent registry const consentRegistry = Object.keys( - this.configExcludingRegionsAndWaitForUpdate, + this.configExcludingModeRegionsAndWaitForUpdate, ).reduce( (result, consentKey) => ({ ...result, [consentKey]: - this.configExcludingRegionsAndWaitForUpdate[consentKey]?.default || - GoogleConsentType.Denied, + this.configExcludingModeRegionsAndWaitForUpdate[consentKey] + ?.default || GoogleConsentType.Denied, }), initialValue, ); @@ -87,10 +88,11 @@ export class GoogleConsentMode { // Fill consent value into consent element, using analytics consent categories const consentRegistry = Object.keys( - this.configExcludingRegionsAndWaitForUpdate, + this.configExcludingModeRegionsAndWaitForUpdate, ).reduce((result, consentKey) => { let consentValue = GoogleConsentType.Denied; - const consent = this.configExcludingRegionsAndWaitForUpdate[consentKey]; + const consent = + this.configExcludingModeRegionsAndWaitForUpdate[consentKey]; if (consent) { // has consent config key diff --git a/packages/react/src/analytics/integrations/shared/GoogleConsentMode/types.ts b/packages/react/src/analytics/integrations/shared/GoogleConsentMode/types.ts index b9e5ac1b4..adbc06f1b 100644 --- a/packages/react/src/analytics/integrations/shared/GoogleConsentMode/types.ts +++ b/packages/react/src/analytics/integrations/shared/GoogleConsentMode/types.ts @@ -26,4 +26,5 @@ export type GoogleConsentModeConfig = GoogleConsentMappingsBase & { regions?: Array; waitForUpdate?: number; + mode?: 'Basic' | 'Advanced'; };