src/lib/cmp.ts (56 lines of code) (raw):

import { generateId, timeout } from './messenger'; interface ConsentState { dateCreated: string; gpcEnabled: boolean; newUser: boolean; uspString: string; } interface CmpReturn { __cmpReturn: { returnValue: ConsentState; callId: string; success: boolean; }; } const isReplyFromCMP = (json: unknown): json is CmpReturn => { const reply = json as CmpReturn; return '__cmpReturn' in reply && typeof reply.__cmpReturn === 'object'; }; const decodeReply = (e: MessageEvent<string>): CmpReturn | void => { try { const json: unknown = JSON.parse(e.data); if (isReplyFromCMP(json)) { return json; } return; } catch (_) { return; } }; const isCcpaOptedOut = (consentState: ConsentState) => { return consentState.uspString[2] === 'Y'; }; const getUSPData = async (): Promise<ConsentState | void> => timeout( new Promise((resolve) => { const callId = generateId(); const message = { __cmpCall: { command: 'getUSPData', version: 1, callId, }, }; const listener = (e: MessageEvent<string>) => { const decoded = decodeReply(e); if (decoded && decoded.__cmpReturn.callId === callId) { resolve(decoded.__cmpReturn.returnValue); window.removeEventListener('message', listener); } }; window.addEventListener('message', listener); window.top?.postMessage(JSON.stringify(message), '*'); }), 3000, ); export { getUSPData, isCcpaOptedOut };