All files tcf.js

72.97% Statements 27/37
55% Branches 11/20
60% Functions 6/10
78.79% Lines 26/33

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            1x           1x           1x           1x           1x 4x 4x 4x               1x 3x         1x                   1x                         1x 3x                   1x                                   4x         3x   3x 1x 1x     2x 2x   2x   2x       2x 2x          
import analytics from './index'
 
/**
 * 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'
 
/**
 * Check if we're on client and tcfApi is available on window object
 * @returns {Boolean}
 */
const checkTcfIsAvailable = () => {
  const isAvailable = typeof window !== 'undefined' && !!window.__tcfapi
  !isAvailable && console.warn('[tcfTracking] window.__tcfapi is not available')
  return isAvailable
}
 
/**
 * 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}`])
 
/**
 * State of user according to GDPR regarding tracking
 */
const USER_GDPR = {
  ACCEPTED: 'ACCEPTED',
  DECLINED: 'DECLINED',
  UNKNOWN: 'UNKNOWN'
}
 
/**
 * Events info according
 * @type {{ [event: string]: [gdprValue: string, eventId: string]}}
 */
const EVENT_INFO = {
  [USER_GDPR.ACCEPTED]: ['Privacy Accepted', 'accepted'],
  [USER_GDPR.DECLINED]: ['Privacy Declined', 'declined'],
  [USER_GDPR.UNKNOWN]: ['Privacy Impression', 'declined']
}
 
/**
 * Track a specific TCF event
 * @param {object} params
 * @param {string} params.eventId
 * @param {string} params.gdprValue
 * @return {Promise}
 */
const trackTcf = ({eventId, gdprValue}) =>
  analytics.track('Event Fired', {
    channel: 'GDPR',
    event_id: eventId,
    gdpr_privacy: gdprValue
  })
 
/**
 * 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)
      })
    })
  })
}
 
/**
 * 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, gdprValue] = EVENT_INFO.UNKNOWN
          return trackTcf({eventId, gdprValue})
        }
 
        Eif (eventStatus === TCF_EVENT_USER_ACTION_COMPLETE) {
          const {consents} = purpose
 
          const hasConsents = checkHasUserConsentedTracking(consents)
 
          const userGdprState = hasConsents
            ? USER_GDPR.ACCEPTED
            : USER_GDPR.DECLINED
 
          const [eventId, gdprValue] = EVENT_INFO[userGdprState]
          return trackTcf({eventId, gdprValue})
        }
      }
    )
}