-
Notifications
You must be signed in to change notification settings - Fork 72
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
Dispatch Fides.js lifecycle events on window (FidesInitialized, FidesUpdated) and cross-publish to Fides.gtm() integration #3454
Changes from all commits
dda542d
42ecd36
ef71ffd
1cdcee3
ad40ffe
dcd59de
ec83a36
43db5a2
9c76708
01f1f82
9913a9a
8f62f17
95e6855
49c19f4
b80a825
6033535
f52d09c
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,19 +1,56 @@ | ||
import { CookieKeyConsent } from "../lib/cookie"; | ||
import { FidesEventDetail } from "../lib/events"; | ||
|
||
declare global { | ||
interface Window { | ||
dataLayer?: any[]; | ||
} | ||
} | ||
|
||
/** | ||
* Call Fides.gtm to configure Google Tag Manager. The user's consent choices will be | ||
* pushed into GTM's `dataLayer` under `Fides.consent`. | ||
* Defines the structure of the Fides variable pushed to the GTM data layer | ||
*/ | ||
export const gtm = () => { | ||
interface FidesVariable { | ||
consent: CookieKeyConsent; | ||
} | ||
|
||
// Helper function to push the Fides variable to the GTM data layer from a FidesEvent | ||
const pushFidesVariableToGTM = (fidesEvent: { | ||
type: string; | ||
detail: FidesEventDetail; | ||
}) => { | ||
// Initialize the dataLayer object, just in case we run before GTM is initialized | ||
const dataLayer = window.dataLayer ?? []; | ||
window.dataLayer = dataLayer; | ||
dataLayer.push({ | ||
Fides: { | ||
consent: window.Fides.consent, | ||
}, | ||
}); | ||
|
||
// Construct the Fides variable that will be pushed to GTM | ||
const Fides: FidesVariable = { | ||
consent: fidesEvent.detail.consent, | ||
}; | ||
|
||
// Push to the GTM dataLayer | ||
dataLayer.push({ event: fidesEvent.type, Fides }); | ||
}; | ||
|
||
/** | ||
* Call Fides.gtm() to configure the Fides <> Google Tag Manager integration. | ||
* The user's consent choices will automatically be pushed into GTM's | ||
* `dataLayer` under `Fides.consent` variable. | ||
*/ | ||
export const gtm = () => { | ||
// Listen for Fides events and cross-publish them to GTM | ||
window.addEventListener("FidesInitialized", (event) => | ||
pushFidesVariableToGTM(event) | ||
); | ||
window.addEventListener("FidesUpdated", (event) => | ||
pushFidesVariableToGTM(event) | ||
); | ||
|
||
// If Fides was already initialized, publish a synthetic event immediately | ||
if (window.Fides?.initialized) { | ||
pushFidesVariableToGTM({ | ||
type: "FidesInitialized", | ||
detail: { consent: window.Fides.consent }, | ||
}); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,8 @@ const applyOptions = (options: ShopifyOptions) => { | |
* Call Fides.shopify to configure Shopify customer privacy. Currently the only consent option | ||
* Shopify allows to be configured is user tracking. | ||
* | ||
* DEFER: Update this integration to support async Fides events | ||
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. Add follow-up issue |
||
* | ||
* @example | ||
* Fides.shopify({ tracking: Fides.consent.data_sales }) | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { FidesCookie } from "./cookie"; | ||
|
||
/** | ||
* Defines the available event names: | ||
* - FidesInitialized: dispatched when initialization is complete, from Fides.init() | ||
* - FidesUpdated: dispatched when preferences are updated, from updateConsentPreferences() or Fides.init() | ||
*/ | ||
export type FidesEventType = "FidesInitialized" | "FidesUpdated"; | ||
|
||
// Bonus points: update the WindowEventMap interface with our custom event types | ||
declare global { | ||
interface WindowEventMap { | ||
FidesInitialized: FidesEvent; | ||
FidesUpdated: FidesEvent; | ||
} | ||
} | ||
|
||
/** | ||
* Defines the properties available on event.detail. As of now, these are an | ||
* explicit subset of properties from the Fides cookie | ||
* TODO: add identity and meta? | ||
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. Decide on this - I think it makes sense to include these in the event, I could see a listener wanting a bit of information about the identity when processing the preferences, etc. 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. Will facebook / shopify need identity or other metadata? 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. Nothing needs it yet, but I'm wondering what a developer might need when integrating consent into their app via these events... |
||
*/ | ||
export type FidesEventDetail = Pick<FidesCookie, "consent">; | ||
|
||
export type FidesEvent = CustomEvent<FidesEventDetail>; | ||
|
||
/** | ||
* Dispatch a custom event on the window object, providing the current Fides | ||
* state on the "detail" property of the event. | ||
* | ||
* Example usage: | ||
* ``` | ||
* window.addEventListener("FidesUpdated", (evt) => console.log("Fides.consent updated:", evt.detail.consent)); | ||
* ``` | ||
* | ||
* The snippet above will print a console log whenever consent preferences are initialized/updated, like: | ||
* ``` | ||
* Fides.consent updated: { data_sales_and_sharing: true } | ||
* ``` | ||
*/ | ||
export const dispatchFidesEvent = ( | ||
type: FidesEventType, | ||
cookie: FidesCookie | ||
) => { | ||
if (typeof window !== "undefined" && typeof CustomEvent !== "undefined") { | ||
// Pick a subset of the Fides cookie properties to provide as event detail | ||
const { consent }: FidesEventDetail = cookie; | ||
const detail: FidesEventDetail = { consent }; | ||
const event = new CustomEvent(type, { detail }); | ||
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. Ah this is cool, learned about |
||
window.dispatchEvent(event); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ import { | |
} from "./consent-types"; | ||
import { debugLog, transformUserPreferenceToBoolean } from "./consent-utils"; | ||
import { CookieKeyConsent, FidesCookie, saveFidesCookie } from "./cookie"; | ||
import { dispatchFidesEvent } from "./events"; | ||
import { patchUserPreferenceToFidesServer } from "../services/fides/api"; | ||
|
||
/** | ||
|
@@ -49,6 +50,10 @@ export const updateConsentPreferences = ({ | |
}); | ||
}); | ||
|
||
// Update the cookie object | ||
// eslint-disable-next-line no-param-reassign | ||
cookie.consent = consentCookieKey; | ||
Comment on lines
+53
to
+55
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 mutates the provided 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 fine. It's the same pattern we use in the |
||
|
||
// 1. Save preferences to Fides API | ||
debugLog(debug, "Saving preferences to Fides API"); | ||
const privacyPreferenceCreate: PrivacyPreferencesRequest = { | ||
|
@@ -67,9 +72,12 @@ export const updateConsentPreferences = ({ | |
|
||
// 2. Update the window.Fides.consent object | ||
debugLog(debug, "Updating window.Fides"); | ||
window.Fides.consent = consentCookieKey; | ||
window.Fides.consent = cookie.consent; | ||
|
||
// 3. Save preferences to the cookie | ||
debugLog(debug, "Saving preferences to cookie"); | ||
saveFidesCookie({ ...cookie, consent: consentCookieKey }); | ||
saveFidesCookie(cookie); | ||
|
||
// 4. Dispatch a "FidesUpdated" event | ||
dispatchFidesEvent("FidesUpdated", cookie); | ||
}; |
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.
Add follow-up issue