-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GPP serving TCF strings #4433
GPP serving TCF strings #4433
Changes from all commits
d346943
f733f8c
32e89e8
93b9a98
c92520b
bdfcb04
34605e7
0af8335
379e37a
79646f3
7170378
c1463dc
319955f
a70f69e
94ebc99
9af64df
31ae240
8d96a72
6588867
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,71 @@ | ||
/* eslint-disable no-underscore-dangle */ | ||
/** | ||
* Extension for GPP | ||
* | ||
* Usage: | ||
* Include as a script tag as early as possible (even before fides.js) | ||
*/ | ||
|
||
import { | ||
CmpApi, | ||
CmpDisplayStatus, | ||
CmpStatus, | ||
SignalStatus, | ||
} from "@iabgpp/cmpapi"; | ||
import { makeStub } from "../lib/gpp/stub"; | ||
import { fidesEventToTcString } from "../lib/tcf/events"; | ||
import { | ||
isPrivacyExperience, | ||
shouldResurfaceConsent, | ||
} from "../lib/consent-utils"; | ||
import { ETHYCA_CMP_ID } from "../lib/tcf/constants"; | ||
|
||
const CMP_VERSION = 1; | ||
|
||
const TCF_SECTION_ID = 2; | ||
|
||
export const initializeGppCmpApi = () => { | ||
makeStub(); | ||
|
||
// TODO: instantiate a real (non-stubbed) GPP CMP API and set up listeners | ||
const cmpApi = new CmpApi(ETHYCA_CMP_ID, CMP_VERSION); | ||
cmpApi.setApplicableSections([TCF_SECTION_ID]); | ||
cmpApi.setCmpStatus(CmpStatus.LOADED); | ||
|
||
// If consent does not need to be resurfaced, then we can set the signal to Ready here | ||
window.addEventListener("FidesInitialized", (event) => { | ||
const { experience } = window.Fides; | ||
if ( | ||
isPrivacyExperience(experience) && | ||
!shouldResurfaceConsent(experience, event.detail) | ||
) { | ||
cmpApi.setSignalStatus(SignalStatus.READY); | ||
} | ||
}); | ||
|
||
window.addEventListener("FidesUIShown", () => { | ||
cmpApi.setSignalStatus(SignalStatus.NOT_READY); | ||
cmpApi.setCmpDisplayStatus(CmpDisplayStatus.VISIBLE); | ||
}); | ||
|
||
window.addEventListener("FidesModalClosed", (event) => { | ||
cmpApi.setCmpDisplayStatus(CmpDisplayStatus.HIDDEN); | ||
// If the modal was closed without the user saving, set signal status back to Ready | ||
if ( | ||
event.detail.extraDetails && | ||
event.detail.extraDetails.saved === false | ||
) { | ||
cmpApi.setSignalStatus(SignalStatus.READY); | ||
} | ||
}); | ||
|
||
window.addEventListener("FidesUpdated", (event) => { | ||
const tcString = fidesEventToTcString(event); | ||
// Workaround for bug in base library https://github.com/IABTechLab/iabgpp-es/issues/35 | ||
cmpApi.setFieldValueBySectionId(TCF_SECTION_ID, "CmpId", CMP_ID); | ||
cmpApi.setSectionStringById(TCF_SECTION_ID, tcString ?? ""); | ||
cmpApi.fireSectionChange("tcfeuv2"); | ||
cmpApi.setSignalStatus(SignalStatus.READY); | ||
}); | ||
}; | ||
|
||
initializeGppCmpApi(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -368,7 +368,7 @@ export const initialize = async ({ | |
identity: cookie.identity, | ||
fides_string: cookie.fides_string, | ||
tcf_consent: cookie.tcf_consent, | ||
experience, | ||
experience: effectiveExperience, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a potentially consequential change—before, if the experience was not server side provided, then This basically makes it possible for the "FidesInitialized" listener in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks good. The return obj built here is only used to update the |
||
geolocation, | ||
options, | ||
initialized: true, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,11 +17,10 @@ import { | |
uniqueGvlVendorIds, | ||
} from "./tcf/vendors"; | ||
import { PrivacyExperience } from "./consent-types"; | ||
import { FIDES_SEPARATOR } from "./tcf/constants"; | ||
import { FidesEvent } from "./events"; | ||
import { ETHYCA_CMP_ID, FIDES_SEPARATOR } from "./tcf/constants"; | ||
import { fidesEventToTcString } from "./tcf/events"; | ||
|
||
// TCF | ||
const CMP_ID = 407; | ||
const CMP_VERSION = 1; | ||
const FORBIDDEN_LEGITIMATE_INTEREST_PURPOSE_IDS = [1, 3, 4, 5, 6]; | ||
|
||
|
@@ -70,7 +69,7 @@ export const generateFidesString = async ({ | |
// Some fields will not be populated until a GVL is loaded | ||
await tcModel.gvl.readyPromise; | ||
|
||
tcModel.cmpId = CMP_ID; | ||
tcModel.cmpId = ETHYCA_CMP_ID; | ||
tcModel.cmpVersion = CMP_VERSION; | ||
tcModel.consentScreen = 1; // todo- On which 'screen' consent was captured; this is a CMP proprietary number encoded into the TC string | ||
tcModel.isServiceSpecific = true; | ||
|
@@ -149,33 +148,14 @@ export const generateFidesString = async ({ | |
return Promise.resolve(encodedString); | ||
}; | ||
|
||
/** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moved to a separate file so gpp can also use this function |
||
* Extract just the TC string from a FidesEvent. This will also remove parts of the | ||
* TC string that we do not want to surface with our CMP API events, such as | ||
* `vendors_disclosed` and our own AC string addition. | ||
*/ | ||
const fidesEventToTcString = (event: FidesEvent) => { | ||
const { fides_string: cookieString } = event.detail; | ||
if (cookieString) { | ||
// Remove the AC portion which is separated by FIDES_SEPARATOR | ||
const [tcString] = cookieString.split(FIDES_SEPARATOR); | ||
// We only want to return the first part of the tcString, which is separated by '.' | ||
// This means Publisher TC is not sent either, which is okay for now since we do not set it. | ||
// However, if we do one day set it, we would have to decode the string and encode it again | ||
// without vendorsDisclosed | ||
return tcString.split(".")[0]; | ||
} | ||
return cookieString; | ||
}; | ||
|
||
/** | ||
* Initializes the CMP API, including setting up listeners on FidesEvents to update | ||
* the CMP API accordingly. | ||
*/ | ||
export const initializeTcfCmpApi = () => { | ||
makeStub(); | ||
const isServiceSpecific = true; // TODO: determine this from the backend? | ||
const cmpApi = new CmpApi(CMP_ID, CMP_VERSION, isServiceSpecific, { | ||
const cmpApi = new CmpApi(ETHYCA_CMP_ID, CMP_VERSION, isServiceSpecific, { | ||
// Add custom command to support adding `addtlConsent` per AC spec | ||
getTCData: (next, tcData: TCData, status) => { | ||
/* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { FidesEvent } from "../events"; | ||
import { FIDES_SEPARATOR } from "./constants"; | ||
|
||
/** | ||
* Extract just the TC string from a FidesEvent. This will also remove parts of the | ||
* TC string that we do not want to surface with our CMP API events, such as | ||
* `vendors_disclosed` and our own AC string addition. | ||
*/ | ||
export const fidesEventToTcString = (event: FidesEvent) => { | ||
const { fides_string: cookieString } = event.detail; | ||
if (cookieString) { | ||
// Remove the AC portion which is separated by FIDES_SEPARATOR | ||
const [tcString] = cookieString.split(FIDES_SEPARATOR); | ||
// We only want to return the first part of the tcString, which is separated by '.' | ||
// This means Publisher TC is not sent either, which is okay for now since we do not set it. | ||
// However, if we do one day set it, we would have to decode the string and encode it again | ||
// without vendorsDisclosed | ||
return tcString.split(".")[0]; | ||
} | ||
return cookieString; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need to know if the modal was closed without saving. gpp signals that it is not ready when the modal opens. once it saves, it signals it is ready again. but if you close the modal without saving, we'd be stuck in a "not ready" state