Skip to content

Conversation

@jjdaurora
Copy link
Contributor

@jjdaurora jjdaurora commented Dec 5, 2025

Ticket ENG-1944

Description Of Changes

Code Changes

  • Updated the Fides JS code snippet -- accessible from the Experiences and Property tabs -- with the full Fides JS wrapper script, defined here: https://github.com/ethyca/fde/blob/main/scripts/javascript/wrapper-script.js
  • Add a text field that allows the user to enter their Privacy Center Host URL, which populates dynamically into the template.
  • Extracted the Fides JS code snippet into a separate file called fidesJsScriptTemplate.js, which removes the need to update the code snippet in two separate places (originally in both the NewJavascriptTag.tsx and JavascriptTag.tsx.

Steps to Confirm

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Add a db-migration This indicates that a change includes a database migration label to the entry if your change includes a DB migration
    • Add a high-risk This issue suggests changes that have a high-probability of breaking existing code label to the entry if your change includes a high-risk change (i.e. potential for performance impact or unexpected regression) that should be flagged
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • All UX related changes have been reviewed by a designer
    • No UX review needed
  • Followup issues:
    • Followup issues created
    • No followup issues
  • Database migrations:
    • Ensure that your downrev is up to date with the latest revision on main
    • Ensure that your downgrade() migration is correct and works
      • If a downgrade migration is not possible for this change, please call this out in the PR description!
    • No migrations
  • Documentation:
    • Documentation complete, PR opened in fidesdocs
    • Documentation issue created in fidesdocs
    • If there are any new client scopes created as part of the pull request, remember to update public-facing documentation that references our scope registry
    • No documentation updates required

@jjdaurora jjdaurora requested a review from a team as a code owner December 5, 2025 14:58
@jjdaurora jjdaurora requested review from gilluminate and removed request for a team December 5, 2025 14:58
@vercel
Copy link

vercel bot commented Dec 5, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
fides-plus-nightly Error Error Dec 12, 2025 7:01pm
1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
fides-privacy-center Ignored Ignored Dec 12, 2025 7:01pm

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Dec 5, 2025

Greptile Overview

Greptile Summary

This PR enhances the JavaScript tag generation UI by adding a manual input field for the Privacy Center hostname and introducing a more comprehensive Fides JS script template with geolocation query parameter handling.

  • Refactored JavaScriptTag.tsx and NewJavaScriptTag.tsx to use a shared script template from the new fidesJsScriptTemplate.ts file
  • Added text input fields for users to manually enter their Privacy Center hostname, with NewJavaScriptTag preserving the Fides Cloud config as a fallback
  • Removed the optional GTM script tag section from both components
  • Added a large gvl.json vendor data file (10,767 lines) to the privacy center public assets
  • Added run_migrations.py development utility script for running database migrations locally

Issues found:

  • The script template has a URL construction bug that malforms query parameters when geolocation params are present

Confidence Score: 3/5

  • This PR has a logical bug in the script template that would cause malformed URLs when geolocation parameters are used.
  • The core refactoring is sound, but the new script template contains a URL construction bug that would produce malformed URLs when fidesSearchParams is non-empty. This could break the consent management functionality for users who utilize geolocation query parameters.
  • fidesJsScriptTemplate.ts requires attention for the URL concatenation bug on line 37.

Important Files Changed

File Analysis

Filename Score Overview
clients/admin-ui/src/features/privacy-experience/fidesJsScriptTemplate.ts 2/5 New shared template for Fides JS script with geolocation query param handling. Contains a bug in URL construction that malforms query parameters, and an unused variable declaration.
clients/admin-ui/src/features/privacy-experience/JavaScriptTag.tsx 4/5 Refactored to use shared template and added manual hostname input field. Removed Fides Cloud auto-population and GTM script section.
clients/admin-ui/src/features/privacy-experience/NewJavaScriptTag.tsx 4/5 Added manual hostname input field while preserving Fides Cloud fallback. Refactored to use shared template and removed GTM script section.
clients/privacy-center/public/gvl.json 4/5 Large vendor data file (10,767 lines) containing GVL and GACP vendor information with linked_system status.
run_migrations.py 3/5 Development utility script for running database migrations against localhost. Contains hardcoded credentials for local development.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@jjdaurora jjdaurora changed the title Jjdaurora/eng 1944 v2 Fides JS Code Snippet - Include wrapper script; add text field to set Privacy Center host URL Dec 5, 2025
Copy link
Contributor

@tvandort tvandort left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great start! Left a few feedback items. Could also use some tests.

Comment on lines 1 to 6
export const removePropertyIdFromScript = (script: string, hasPropertyId: boolean) => {
if (!hasPropertyId) {
script = script.replaceAll('+ "?property_id=" + fidesPropertyId + "&"', "");
}
return script;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have this be inserted instead of removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tvandort I changed the logic to insert the property ID now.

*/
const PROPERTY_UNIQUE_ID_TEMPLATE = (propertyId?: string | null): string => {
if (propertyId) {
return propertyId;
}
return "{property-unique-id}";

});
addEventListener("FidesInitialized", function () {
// support custom css hackery
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably don't want to use the word hackery here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth including an example of how to use it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed and updated comments

if (key.startsWith(fidesPrefix)) {
fidesSearchParams.set(
key.replace(fidesPrefix, ""),
key === fidesPrefix + "cache_bust" ? Date.now().toString() : value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should consider making the cache bust parameter also just pass refresh to the privacy center to make everyone's life easier.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Included refresh=true anytime the cache bust parameter is set:

FIDES_JS_SCRIPT_TEMPLATE,
PRIVACY_CENTER_HOSTNAME_TEMPLATE,
removePropertyIdFromScript
} from "./fidesJsScriptTemplate";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea when we want to use relative vs absolute imports as a "general rule". Personally I prefer all absolute but I don't know if that's our general practice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched the paths to absolute.

() => {
let script = FIDES_JS_SCRIPT_TEMPLATE;

script = removePropertyIdFromScript(script, false);
Copy link
Contributor

@tvandort tvandort Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see this more as something like:
getScript({propertyId: "example"}) or getScript()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know what you think of the new implementation. Now, pretty much all of the logic is contained in the script template, and the script tags just handle the rendering of the template with some logic to recompute the dynamic values when those are changed.

const fidesJsScriptTag = useMemo(
() => {
return FIDES_JS_SCRIPT_TEMPLATE(privacyCenterHostname);
},
[privacyCenterHostname],
);

Comment on lines 48 to 59
let script = FIDES_JS_SCRIPT_TEMPLATE.replaceAll(
PROPERTY_UNIQUE_ID_TEMPLATE,
property.id!.toString(),
);
if (isFidesCloud && isSuccess && fidesCloudConfig?.privacy_center_url) {
script.replace(
PRIVACY_CENTER_HOSTNAME_TEMPLATE,
fidesCloudConfig.privacy_center_url,
);
// Use user input if provided, otherwise fall back to Fides Cloud config
const hostname =
privacyCenterHostname ||
(isFidesCloud && isSuccess && fidesCloudConfig?.privacy_center_url
? fidesCloudConfig.privacy_center_url
: "");
if (hostname) {
script = script.replaceAll(PRIVACY_CENTER_HOSTNAME_TEMPLATE, hostname);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same feedback here, I'd love to see the templating inside of the function that returns the script.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See update here:

const fidesJsScriptTag = useMemo(
() => FIDES_JS_SCRIPT_TEMPLATE(privacyCenterHostname, property),
[privacyCenterHostname, property],
);

/**
* Generates the property ID query parameter string for the Fides.js script URL
*/
const PROPERTY_UNIQUE_ID_TEMPLATE = (propertyId?: string | null): string => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function naming pattern should be camelcase

/**
* Generates the complete Fides.js script tag with privacy center hostname and property ID
*/
export const FIDES_JS_SCRIPT_TEMPLATE = (privacyCenterHostname?: string, property?: Property): string => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function naming pattern should be camelcase

if (propertyId) {
return propertyId;
}
return "{property-unique-id}";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this return value ever used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it will return "{property-unique-id}" when there isn't a property in scope, which means this version will be rendered when accessing the script from the Experiences screen. I can add a comment that explains this.

Comment on lines 76 to 78
if (privacyCenterHostname) {
script = script.replaceAll(PRIVACY_CENTER_HOSTNAME_TEMPLATE, privacyCenterHostname);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The template is updated in 2 ways, both replacement and by string interpolation in the string itself. Do we need both?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants