From f75b14865a211a30698473977ff6d144a00b2690 Mon Sep 17 00:00:00 2001 From: Jason Gill Date: Thu, 24 Apr 2025 15:22:48 -0600 Subject: [PATCH 1/4] Fix inacurate vendor count --- .../privacy-experience/preview/Preview.tsx | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx b/clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx index 8e035d5a620..065b9f178c3 100644 --- a/clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx +++ b/clients/admin-ui/src/features/privacy-experience/preview/Preview.tsx @@ -6,6 +6,7 @@ import Script from "next/script"; import React, { useEffect, useMemo, useState } from "react"; import { PREVIEW_CONTAINER_ID } from "~/constants"; +import { useGetVendorReportQuery } from "~/features/plus/plus.slice"; import { TranslationWithLanguageName } from "~/features/privacy-experience/form/helpers"; import { buildBaseConfig, @@ -21,7 +22,6 @@ import { PrivacyNoticeResponse, } from "~/types/api"; -import { useFeatures } from "../../common/features"; import { COMPONENT_MAP } from "../constants"; declare global { @@ -83,7 +83,18 @@ const Preview = ({ ComponentType.TCF_OVERLAY, ].includes(values.component); - const { systemsCount } = useFeatures(); + /** + * Selects the number of vendors + * By using the paginated getVendorReport endpoint, we can get the total number of vendors + */ + const { data: vendorReport } = useGetVendorReportQuery({ + pageIndex: 1, + pageSize: 1, + }); + const vendorCount = useMemo( + () => vendorReport?.total || 0, + [vendorReport?.total], + ); useEffect(() => { if ( @@ -192,7 +203,7 @@ const Preview = ({ ? values.layer1_button_options : Layer1ButtonOption.OPT_IN_OPT_OUT; updatedConfig.options.preventDismissal = !values.dismissable; - updatedConfig.experience.vendor_count = systemsCount; + updatedConfig.experience.vendor_count = vendorCount; updatedConfig.experience.experience_config.component = values.component; // reinitialize fides.js each time the form changes window.Fides.init(updatedConfig); @@ -207,7 +218,7 @@ const Preview = ({ baseConfig, allPrivacyNotices, isPreviewAvailable, - systemsCount, + vendorCount, fidesScriptLoaded, previewMode, values.privacy_notice_ids, From e2c11f879216040a8b6325b272c5b3f1a5cb3280 Mon Sep 17 00:00:00 2001 From: Jason Gill Date: Thu, 24 Apr 2025 15:51:11 -0600 Subject: [PATCH 2/4] Treat non-applicable as defaults then override --- clients/fides-js/src/integrations/gtm.ts | 32 ++++++++++++++---------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/clients/fides-js/src/integrations/gtm.ts b/clients/fides-js/src/integrations/gtm.ts index 1c2c49d7902..048d083ff62 100644 --- a/clients/fides-js/src/integrations/gtm.ts +++ b/clients/fides-js/src/integrations/gtm.ts @@ -51,23 +51,12 @@ const pushFidesVariableToGTM = ( nonApplicableFlagMode = GtmNonApplicableFlagMode.OMIT, flag_type: flagType = GtmFlagType.BOOLEAN, } = options ?? {}; - const consentValues: FidesVariable["consent"] = JSON.parse( - JSON.stringify(consent), - ); + const consentValues: FidesVariable["consent"] = {}; const privacyNotices = window.Fides?.experience?.privacy_notices; const nonApplicablePrivacyNotices = window.Fides?.experience?.non_applicable_privacy_notices; - if (privacyNotices && flagType === GtmFlagType.CONSENT_MECHANISM) { - Object.entries(consent).forEach(([key, value]) => { - consentValues[key] = transformConsentToFidesUserPreference( - value, - privacyNotices.find((notice) => notice.notice_key === key) - ?.consent_mechanism, - ); - }); - } - + // First set defaults for non-applicable privacy notices if needed if ( nonApplicableFlagMode === GtmNonApplicableFlagMode.INCLUDE && nonApplicablePrivacyNotices @@ -78,6 +67,23 @@ const pushFidesVariableToGTM = ( }); } + // Then override with actual consent values + if (consent) { + if (privacyNotices && flagType === GtmFlagType.CONSENT_MECHANISM) { + Object.entries(consent).forEach(([key, value]) => { + consentValues[key] = transformConsentToFidesUserPreference( + value, + privacyNotices.find((notice) => notice.notice_key === key) + ?.consent_mechanism, + ); + }); + } else { + Object.entries(consent).forEach(([key, value]) => { + consentValues[key] = value; + }); + } + } + // Construct the Fides variable that will be pushed to GTM const Fides: FidesVariable = { consent: consentValues, From a551fd91b65a04532500bb240ef0c5cc1e1e5e9c Mon Sep 17 00:00:00 2001 From: Jason Gill Date: Thu, 24 Apr 2025 16:00:49 -0600 Subject: [PATCH 3/4] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d37e927411b..5ebfb832d7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Changes can also be flagged with a GitHub label for tracking purposes. The URL o - Cleaning up test fixtures [#6008](https://github.com/ethyca/fides/pull/6008) ### Fixed +- Fixed GTM integration to properly handle duplicate notice keys [#6090](https://github.com/ethyca/fides/pull/6090) - Fix Special-purpose only vendors not correctly encoded in TC string [#6086](https://github.com/ethyca/fides/pull/6086) ## [2.60.0](https://github.com/ethyca/fides/compare/2.59.2...2.60.0) From ff4b8f74cf4f4ce2141b032827646dbf9fe779c3 Mon Sep 17 00:00:00 2001 From: Jason Gill Date: Thu, 24 Apr 2025 16:58:31 -0600 Subject: [PATCH 4/4] refactor to extract consent composition --- clients/fides-js/src/integrations/gtm.ts | 44 +++++++++++++++++------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/clients/fides-js/src/integrations/gtm.ts b/clients/fides-js/src/integrations/gtm.ts index 048d083ff62..9b3b3746024 100644 --- a/clients/fides-js/src/integrations/gtm.ts +++ b/clients/fides-js/src/integrations/gtm.ts @@ -32,6 +32,33 @@ export interface GtmOptions { flag_type?: GtmFlagType; } +/** + * Composes consent values based on the consent mechanism and flag type + */ +const composeConsent = ( + consent: Record, + privacyNotices: any[] | undefined, + flagType: GtmFlagType, +): Record => { + const consentValues: Record = {}; + + Object.entries(consent).forEach(([key, value]) => { + if (privacyNotices && flagType === GtmFlagType.CONSENT_MECHANISM) { + const relevantNotice = privacyNotices.find( + (notice) => notice.notice_key === key, + ); + consentValues[key] = transformConsentToFidesUserPreference( + value, + relevantNotice?.consent_mechanism, + ); + } else { + consentValues[key] = value; + } + }); + + return consentValues; +}; + // Helper function to push the Fides variable to the GTM data layer from a FidesEvent const pushFidesVariableToGTM = ( fidesEvent: { @@ -69,19 +96,10 @@ const pushFidesVariableToGTM = ( // Then override with actual consent values if (consent) { - if (privacyNotices && flagType === GtmFlagType.CONSENT_MECHANISM) { - Object.entries(consent).forEach(([key, value]) => { - consentValues[key] = transformConsentToFidesUserPreference( - value, - privacyNotices.find((notice) => notice.notice_key === key) - ?.consent_mechanism, - ); - }); - } else { - Object.entries(consent).forEach(([key, value]) => { - consentValues[key] = value; - }); - } + Object.assign( + consentValues, + composeConsent(consent, privacyNotices, flagType), + ); } // Construct the Fides variable that will be pushed to GTM