All files syncPixels.js

90.38% Statements 47/52
81.82% Branches 18/22
93.33% Functions 14/15
93.62% Lines 44/47

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      3x         3x 5x   3x 4x             3x 5x             3x 6x 6x 6x 6x 6x 6x   6x                           3x 3x   3x 3x 3x                 3x 3x   3x 3x 3x               3x 4x             3x   31x     20x 20x     5x     5x   4x     4x 3x   15x     3x                                 3x 4x   4x   1x       3x 3x    
import {getConfig} from './config'
import {storage} from './storage'
 
export const SYNC_PIXEL_PERSISTANCE_KEY = 'segment-wrapper:sync-pixels'
 
/**
 * @param {String} mcvid Marketing Cloud Visitor Id
 */
const persist = mcvid =>
  storage({method: 'setItem', key: SYNC_PIXEL_PERSISTANCE_KEY, value: mcvid})
 
const cleanPersistency = () =>
  storage({method: 'removeItem', key: SYNC_PIXEL_PERSISTANCE_KEY})
 
/**
 * Create the URL of Demdex with a specified Marketing Cloud Visitor Id
 * @param {String} mcvid Marketing Cloud Visitor Id
 * @return {String} URL
 */
const createSyncPixelsUrl = mcvid =>
  `https://mpispain.demdex.net/event?d_mid=${mcvid}&d_orgid=05FF6243578784B37F000101%40AdobeOrg&d_rtbd=json&d_full=1&d_cts=2`
 
/**
 * Create a pixel by using a image src and log the info with the used ids
 * @param {{ ids: number[], pixelName: String, src: String}} params
 * @return {Promise}
 */
const createPixel = ({ids, pixelName, src}) => {
  const img = new window.Image()
  img.src = src
  return new Promise((resolve, reject) => {
    img.onload = () => {
      console.info(`Create segment in ${pixelName}`, ids)
      resolve()
    }
    img.onerror = () => {
      const err = `Error creating segments in ${pixelName}`
      console.error(err)
      reject(err)
    }
  })
}
 
/**
 * Sync with Facebook Ads Pixel
 * @param {string} pixelId
 * @param {number[]} ids
 * @return {Promise}
 */
const syncWithFacebook = (pixelId, ids) => {
  Iif (!pixelId) return Promise.resolve()
 
  const qs = ids.join(',')
  const src = `https://www.facebook.com/tr/?id=${pixelId}&ev=Adobe-Audience-Manager-Segment&cd[segID]=${qs}&noscript=1`
  return createPixel({ids, pixelName: 'Facebook Ads', src})
}
 
/**
 * Sync with Google Ads Pixel
 * @param {string} pixelId
 * @param {number[]} ids
 * @return {Promise}
 */
const syncWithGoogle = (pixelId, ids) => {
  Iif (!pixelId) return Promise.resolve()
 
  const qs = ids.join(';aam=')
  const src = `https://googleads.g.doubleclick.net/pagead/viewthroughconversion/${pixelId}/?guid=ON&script=0&data=aam=${qs}&value=0`
  return createPixel({ids, pixelName: 'Google Ads', src})
}
 
/**
 * Extract Ids from Demdex API response
 * @param {object} json
 * @return {String}
 */
const extractStringIds = json =>
  (json.stuff && json.stuff[0] && json.stuff[0].cv) || ''
 
/**
 * Retrieve ids from Demdex API and
 * @param {String} mcvid Marketing Cloud Visitor Id
 * @return {Promise}
 */
export const syncPixels = mcvid => {
  // check if we have a Marketing Cloud Visitor Id before continuing
  if (!mcvid) return Promise.resolve()
 
  // check if pixels ids are configured before continuing
  const {facebookPixelId, googleAdsPixelId} = getConfig() || {}
  if (!facebookPixelId && !googleAdsPixelId) return Promise.resolve()
 
  // save the data to be able to recover if cancelled any time
  persist(mcvid)
 
  // if we have a MCVID and pixels are configured, proceed to sync pixels
  return window
    .fetch(createSyncPixelsUrl(mcvid))
    .then(res => res.json())
    .then(extractStringIds)
    .then(stringIds => {
      if (stringIds) {
        const ids = stringIds
          .split(/(\d+)/)
          .map(str => +str)
          .filter(Boolean)
 
        return Promise.all([
          syncWithGoogle(googleAdsPixelId, ids),
          syncWithFacebook(facebookPixelId, ids)
        ])
      }
    })
    .then(cleanPersistency)
}
 
/**
 * Retries pixel sync that did not work.
 * Every time we sync pixels, we persist the mcvid in the localStorage
 * if it works, we cleanup removing this entry in the localStorage
 * if it doesn't work, it is not cleaned up so we do retry every time this script loads
 * Main issue behind this is the fact that most errors while syncing the pixels is
 * caused by the browser cancelling the request on a page reload
 */
export const retryPixelsSync = () => {
  const mcvid = storage({key: SYNC_PIXEL_PERSISTANCE_KEY})
 
  if (!mcvid) return
 
  return syncPixels(mcvid)
}
 
// Code executed when the script loads.
Eif (typeof window !== 'undefined') {
  retryPixelsSync()
}