Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | 5x 5x 5x 5x 5x 5x 5x 18x 3x 3x 5x 6x 6x 6x 6x 6x 5x 5x 5x 4x 5x 5x 18x 18x 5x 6x 4x 4x 1x 1x 3x 3x 3x 3x 3x 3x 3x | import analytics from './segmentWrapper' /** * TCF Api Version to use * @type {number} */ const TCF_API_VERSION = 2 /** * List of purpose ids needed to be able to track with all info * @type {Array<number>} */ const NEEDED_PURPOSES = [8, 10] /** * Event that determines that the user has performed an action * @type {string} */ const TCF_EVENT_USER_ACTION_COMPLETE = 'useractioncomplete' /** * Event that determines that the user is seeing the UI to give consent * @type {string} */ const TCF_EVENT_SHOW_UI = 'cmpuishown' /** * State of user according to GDPR regarding tracking */ const USER_GDPR = { ACCEPTED: 'accepted', DECLINED: 'declined', UNKNOWN: 'unknown' } /** * Events info according * @type {{ [event: string]: [eventId: string, gdprValue: string]}} */ const EVENT_INFO = { [USER_GDPR.ACCEPTED]: ['Privacy Accepted', USER_GDPR.ACCEPTED], [USER_GDPR.DECLINED]: ['Privacy Declined', USER_GDPR.DECLINED], [USER_GDPR.UNKNOWN]: ['Privacy Impression', USER_GDPR.UNKNOWN] } /** * Define the user GDPR consents state. This value will be updated with new values * when the consents of the users changes. */ const gdprState = { _onChange: value => {}, value: USER_GDPR.UNKNOWN, onChange: callback => (gdprState._onChange = callback), get: () => gdprState.value, set: value => { gdprState.value = value gdprState._onChange(value) } } /** * Check if we're on client and tcfApi is available on window object * @returns {Boolean} */ const checkTcfIsAvailable = () => { // first check if we're on server, as this doesn't work on server-side const isClient = typeof window !== 'undefined' Iif (!isClient) return false // if we're on client, check if we have the tcfapi available const isTcfApiAvailable = !!window.__tcfapi !isTcfApiAvailable && console.warn( "[tcfTracking] window.__tcfapi is not available on client and TCF won't be tracked." ) return isTcfApiAvailable } /** * Check from a list of consents if user has accepted being tracked * @param {{[purposeId: string]: boolean}} userConsents * @returns {Boolean} */ const checkHasUserConsentedTracking = userConsents => NEEDED_PURPOSES.every(purposeId => userConsents[`${purposeId}`]) /** * Track a specific TCF event * @param {object} params * @param {string} params.eventId Event ID to be sent with the TCF Tracking * @param {string} params.gdprPrivacy Send a string telling if the gdpr has been accepted or reject * @return {Promise} */ const trackTcf = ({eventId, gdprPrivacy}) => analytics.track( 'Event Fired', { channel: 'GDPR', event_id: eventId }, { gdpr_privacy: gdprPrivacy } ) /** * Check if DMP is consented by the user using boros API * @return {Promise<boolean>} */ export const checkIsDMPReady = () => { return new Promise(resolve => { if (typeof window === 'undefined') return resolve() if (window.__borosTcf === undefined) return resolve() window.__borosTcf.push(api => { api('isDmpAccepted', ({success, value}) => { const isDMPReady = success && value return resolve(isDMPReady) }) }) }) } /** * Get if we have user consents * @return {Promise<string>} */ export const getGdprPrivacyValue = () => { // try to get the actual gdprPrivacyValue and just return it const gdprPrivacyValue = gdprState.get() return Promise.resolve(gdprPrivacyValue) // TODO: Disabled for now. It will be added on the next iteration // if (gdprPrivacyValue !== undefined) return Promise.resolve(gdprPrivacyValue) // // if we don't have a gdprPrivacyValue, then subscribe to it until we have a value // return new Promise(resolve => { // gdprPrivacyValueState.onChange = gdprPrivacyValue => // resolve(gdprPrivacyValue) // }) } /** * Check if gdprPrivacyValue is accepted * @return {boolean} */ export const checkGdprIsAccepted = gdprPrivacyValue => gdprPrivacyValue === USER_GDPR.ACCEPTED /** * Init TCF Tracking User Consents with Segment */ export default function initTcfTracking() { checkTcfIsAvailable() && window.__tcfapi( 'addEventListener', TCF_API_VERSION, ({eventStatus, purpose}, success) => { Iif (!success) return Promise.resolve() if (eventStatus === TCF_EVENT_SHOW_UI) { const [eventId, gdprPrivacy] = EVENT_INFO[USER_GDPR.UNKNOWN] return trackTcf({eventId, gdprPrivacy}) } Eif (eventStatus === TCF_EVENT_USER_ACTION_COMPLETE) { const {consents} = purpose const hasConsents = checkHasUserConsentedTracking(consents) // get the state key according to the gdprPrivacyValue const gdprStateKey = hasConsents ? USER_GDPR.ACCEPTED : USER_GDPR.DECLINED gdprState.set(gdprStateKey) // extract the eventId and gdprPrivacy string to send with the track const [eventId, gdprPrivacy] = EVENT_INFO[gdprStateKey] return trackTcf({eventId, gdprPrivacy}) } } ) } |