{"version":3,"sources":["webpack:///./node_modules/@financial-times/ads-legacy-o-ads/dist/index.js"],"names":["perfMark","name","performance","window","LUX","msPerformance","webkitPerformance","mozPerformance","mark","clearMarks","buildPerfmarkSuffix","eventDetailsObj","suffix","pos","size","creativeId","join","on","callback","target","document","body","documentElement","addEventListener","clearPerfMarks","metricsDefinitions","groupsToClear","getEntriesByType","relevantGroupsMarks","filter","group","includes","spoorAction","map","marks","eventsToClear","concat","forEach","eventName","match","messenger","post","message","source","JSON","stringify","arguments","top","postMessage","parse","e","breakpoints$1","current","getNearestBreakpoint","winner","dims","getSize","Object","keys","breakpoint","breakpointDims","width","height","fire","setCurrent","getCurrent","init$2","brps","cb","utils","isFunction","listenTo","log","type","argsIndex","indexOf","args","slice","call","isOn","console","apply","setThrottleInterval","hop","prototype","hasOwnProperty","is","object","toString","undefined","start","groupCollapsed","end","groupEnd","localStorage","getItem","location","search","info","warn","error","table","data","columns","attributeTable","item","val","isArray","isObject","key","value","obj","isString","isWindow","isPlainObject","nodeType","constructor","dehyphenise","string","replace","hyphen","letter","toUpperCase","metricsSampleThreshold","Math","random","off","removeEventListener","once","event","srcElement","broadcast","opts","bubbles","cancelable","detail","length","dispatchEvent","CustomEvent","responsive","isStorage","isNonEmptyString","str","Boolean","isElement","element","tagName","extend","options","src","copy","copyIsArray","clone","deep","i","hash","delimiter","pairing","pair","hashObj","split","idx","l","trim","attach","scriptUrl","async","errorcb","autoRemove","tag","createElement","node","getElementsByTagName","hasRun","processCallback","parentElement","removeChild","setAttribute","onreadystatechange","readyState","onload","onerror","parentNode","insertBefore","getReferrer","referrer","parseAttributeName","attribute","getLocation","href","getQueryString","substring","getQueryParamByName","url","results","RegExp","exec","decodeURIComponent","getTimestamp","now","Date","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","iframeToSlotName","iframeWindow","iframes","slotName","contentWindow","getAttribute","buildObjectFromArray","targetObject","reduce","prev","cookie","pop","getVersion","setupMetrics","definitions","disableSampling","Array","eDef","inSample","sampleSize","triggers","trigger","eMarkMap","listenOnInitialised","eventDetails","events","markNames","getEntriesByName","mName","pMarks","markName","round","startTime","mNameNoSuffix","pMarks2","getMarksForEvents","navigation","navMarks","desiredMarks","navMarksArray","getNavigationPerfMarks","assign","eventPayload","category","action","timings","advert","correlator","oAds","gpt","getCorrelator","creative","isEmpty","sendMetrics","multiple","sendMetricsOnEvent","this","markPageChange","defaults","formats","PartnerContent","sizes","MediumRectangle","Rectangle","WideSkyscraper","Leaderboard","SuperLeaderboard","HalfPage","Billboard","Portrait","AdhesionBanner","MicroBar","Button2","Responsive","extra","large","medium","small","flags","refresh","inview","displayLabelWithBorders","Config","store","access","k","v","result","clear","init","canonical","canonicalTag","querySelector","fetchCanonicalURL","from","querySelectorAll","script","innerHTML","fetchDeclaritiveConfig","config","config$1","bind","init$1","VALID_SIZE_STRINGS","VALID_COLLAPSE_MODES","attributeParsers","regex","test","push","parseInt","mapping","format","responsiveSizes","screenName","toLowerCase","responsiveFormats","lazyLoadThreshold","Number","targeting","base","collapseEmpty","convertLazyLoadBooleanToObject","lazyLoad","onChangeBreakpoint","slot","screensize","hasValidSize","uncollapse","collapse","Slot","container","initLazyLoading","cfg","slotConfig","outer","addContainer","inner","setName","server","defer","center","label","outOfPage","companion","outerEl","allowedLabels","adsLabelPos","modifier","classList","add","parseAttributeConfig","lazyLoadObserver","initLazyLoad","centerContainer","labelContainer","initResponsive","getSlotSizes","getSlotTargeting","params","entries","getSlotGPTSize","attributes","threshold","viewportMargin","getAttributes","observe","render","unobserve","maximise","floor","setFormatLoaded","addClass","className","remove","clearSlot","destroy","destroySlot","submitImpression","submitGptImpression","details","attrs","attr","insertAdjacentHTML","lastChild","Slots","invokeMethodOnSlots","names","method","slots","run","findFormatBySize","prop","s","onBreakpointChange","isCurrentlyResponsive","stillWantsResponsive","initSlot","getElementById","id","removeAttribute","initRefresh","refreshCount","time","max","clearInterval","setInterval","parseFloat","initRendered","breakpoints","initPostMessage","slotClass","flushLazyLoading","lazyLoadingObservers","observer","root","contains","lazyLoadingConfig","lazyLoadingObserver","find","rootMargin","IntersectionObserver","changes","a","intersectionRect","left","sort","b","change","fn","debug","row","unitName","lineItemId","debug$1","values","parameters","Targeting","get","methods","socialReferrer","getSocialReferrer","timestamp","socialFlow","OADS_VERSION","sf","socialflow","codedValue","lookup","google","socref","searchTerm","qs","keywords","q","query","queryText","searchField","unescape","kw","ts","res","SEARCH_PARAMS","filterNestedParams","nestedParams","keysToStrip","childParams","URLSearchParams","delete","DEFAULT_LAZY_LOAD","fetchMarginPercent","renderMarginPercent","mobileScaling","loadGPT","googletag","cmd","err","setup","gptConfig","nonPersonalized","pubads","onRenderEnded","companions","disableInitialLoad","companionAds","setRefreshUnfilledSlots","enableCompanions","rendering","enableSyncRendering","enableSingleRequest","enableAsyncRendering","setRenderingMode","setPageTargeting","mode","collapseEmptyDivs","setPageCollapseEmpty","lazyLoadConf","enableLazyLoad","filters","URL","param","searchParams","set","stripUrlParams","enableServices","setTargeting","setRequestNonPersonalizedAds","targetingData","String","onReady","slotMethods","defineSlot","addServices","setCollapseEmpty","setURL","display","onRender","onRefresh","onResize","iframe","gptSlotId","getSlotId","domId","getDomId","iframeId","getId","slotTargeting","getTargetingMap","serviceName","iFrameEl","setUnitName","defineOutOfPageSlot","defineSizeMapping","gptSlot","pubadsReady","updatePageTargeting","sizeMapping","addSize","build","destroySlots","network","site","zone","addService","setCollapseEmptyDiv","impressionURL","trackingUrlElement","dataset","oAdsImpressionUrl","getImpressionURL","override","updateCorrelator","clearPageTargeting","clearTargeting","clearPageTargetingForKey","hasGPTLoaded","apiReady","conf","Ads","initAll","configOptions","disableConsentCookie","consents","behavioral","programmatic","consentCookie","getConsents","Promise","resolve","initLibrary","updateTargeting","isInitialised","setItem","removeItem","version","ads","then"],"mappings":"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","file":"2.763224f2.js","sourcesContent":["import oViewport from '@financial-times/o-viewport';\n\n/**\n * Utility methods for o-ads events. Methods defined here are added to the utils object not the utils.event object.\n * @author Origami Advertising, origami.advertising@ft.com\n * @module utils/events\n * @see utils\n */\n// Creates a timestamp in the browser's performance entry buffer\n// for later use\nconst perfMark = name => {\n  /* istanbul ignore next */\n  const performance = window.LUX || window.performance || window.msPerformance || window.webkitPerformance || window.mozPerformance;\n\n  if (performance && performance.mark) {\n    performance.clearMarks(name);\n    performance.mark(name);\n  }\n}; // Creates a suffix for an event's performance mark based on some of the attributes on\n// the event payload which help identify unequivocally the slot that originated the event\n\nfunction buildPerfmarkSuffix(eventDetailsObj) {\n  let suffix = '';\n\n  if (eventDetailsObj && typeof eventDetailsObj === 'object' && 'pos' in eventDetailsObj && 'name' in eventDetailsObj) {\n    suffix = '__' + [eventDetailsObj.pos, eventDetailsObj.name, eventDetailsObj.size, eventDetailsObj.creativeId].join('__');\n  }\n\n  return suffix;\n}\n/**\n* Broadscasts an o-ads event\n* @param {string} name The name of the event\n* @param {object} data The data to send as event detail\n* @param {HTMLElement} target The element to attach the event listener to\n*/\n\nfunction broadcast(eventName, data, target) {\n  /* istanbul ignore next: ignore the final fallback as hard trigger */\n  target = target || document.body || document.documentElement;\n  eventName = `oAds.${eventName}`;\n  const opts = {\n    bubbles: true,\n    cancelable: true,\n    detail: data\n  };\n  const isSlotEvent = typeof data === 'object' && 'pos' in data;\n  const evDetails = isSlotEvent ? {\n    pos: data.pos,\n    name: data.name,\n    size: data.size && data.size.length ? data.size.toString() : '',\n    creativeId: data.creativeId\n  } : {};\n  const suffix = buildPerfmarkSuffix(evDetails);\n  const markName = eventName + suffix;\n  perfMark(markName);\n  target.dispatchEvent(new CustomEvent(eventName, opts));\n}\n/**\n* Sets an event listener for an oAds event\n* @param {string} name The name of the event\n* @param {EventListenerOrEventListenerObject} callback The function to execute on the event\n* @param {HTMLElement} [target] The element to attach the event listener to\n*/\n\nfunction on(name, callback, target) {\n  name = `oAds.${name}`;\n  /* istanbul ignore next: ignore the final fallback as hard trigger */\n\n  target = target || document.body || document.documentElement;\n  target.addEventListener(name, callback);\n}\n/**\n* Removes an event listener for an oAds event\n* @param {string} name The name of the event\n* @param {function} callback The function on the event to be removed\n* @param {HTMLElement} target The element the event listener is attached to\n*/\n\nfunction off(name, callback, target) {\n  name = `oAds.${name}`;\n  /* istanbul ignore next: ignore the final fallback as hard trigger */\n\n  target = target || document.body || document.documentElement;\n  target.removeEventListener(name, callback);\n}\n/**\n* Sets a one time event listener for an oAds event\n* @param {string} name The name of the event\n* @param {function} callback The function to execute on the event\n* @param {HTMLElement} [target] The element to attach the event listener to\n*/\n\nfunction once(name, callback, target) {\n  const handler = function (event) {\n    /* istanbul ignore next: ignore the final fallback as hard trigger */\n    const targ = event.target || event.srcElement;\n    targ.removeEventListener(name = `oAds.${name}`, callback);\n\n    if (callback) {\n      callback(event); // we set callback to null so if for some reason the listener isn't removed the callback will still only be called once\n\n      callback = null;\n    }\n  };\n\n  on(name, handler, target);\n}\n\nfunction getMarksForEvents(events, suffix) {\n  const markNames = events.map(eventName => 'oAds.' + eventName + suffix);\n\n  if (!performance || !performance.getEntriesByName) {\n    /* istanbul ignore next  */\n    return {};\n  }\n\n  const marks = {};\n  markNames.forEach(function (mName) {\n    const pMarks = performance.getEntriesByName(mName);\n    const markName = mName.replace('oAds.', '').replace(suffix, '');\n\n    if (pMarks && pMarks.length) {\n      // We don't need sub-millisecond precision\n      marks[markName] = Math.round(pMarks[0].startTime);\n      return;\n    } // If no mark has been found, we might be looking for a page-level\n    // mark name, i.e. one without a suffix\n\n\n    if (suffix) {\n      const mNameNoSuffix = mName.replace(suffix, '');\n      const pMarks2 = performance.getEntriesByName(mNameNoSuffix);\n\n      if (pMarks2 && pMarks2.length) {\n        marks[markName] = Math.round(pMarks2[0].startTime);\n      }\n    }\n  });\n  return marks;\n}\nfunction clearPerfMarks(metricsDefinitions, groupsToClear) {\n  if (!performance || !performance.getEntriesByType) {\n    return;\n  }\n\n  const relevantGroups = metricsDefinitions.filter(group => groupsToClear.includes(group.spoorAction));\n  const relevantGroupsMarks = relevantGroups.map(group => group.marks); // Because relevantGroupsMarks is a 2D array ...\n\n  const eventsToClear = [].concat(...relevantGroupsMarks);\n  const perfMarks = performance.getEntriesByType('mark');\n  perfMarks.forEach(({\n    name\n  }) => {\n    eventsToClear.forEach(eventName => {\n      if (name.match(`oAds.${eventName}`)) {\n        performance.clearMarks(name);\n      }\n    });\n  });\n}\n/* istanbul ignore next */\n\nfunction getNavigationPerfMarks(desiredMarks) {\n  if (!performance || !performance.getEntriesByType || !utils.isArray(desiredMarks)) {\n    /* istanbul ignore next  */\n    return {};\n  }\n\n  const navMarksArray = performance.getEntriesByType('navigation');\n  const navMarks = utils.isArray(navMarksArray) && navMarksArray[0] || {};\n  const marks = {};\n  desiredMarks.forEach(function (markName) {\n    marks[markName] = typeof navMarks[markName] === 'number' ? Math.round(navMarks[markName]) : 0;\n  });\n  return marks;\n}\n\nfunction setupMetrics(definitions, callback, disableSampling) {\n  if (!Array.isArray(definitions)) {\n    this.log.warn('Metrics definitions should be an array. o-Ads will not record any metrics.');\n    return;\n  }\n\n  definitions.forEach(function (eDef) {\n    if (disableSampling || utils.inSample(eDef.sampleSize)) {\n      const triggers = Array.isArray(eDef.triggers) ? eDef.triggers : [];\n      triggers.forEach(function (trigger) {\n        sendMetricsOnEvent('oAds.' + trigger, eDef, callback);\n      });\n    }\n  });\n}\n\nfunction sendMetricsOnEvent(eventName, eMarkMap, callback) {\n  document.addEventListener(eventName, function listenOnInitialised(event) {\n    sendMetrics(eMarkMap, event.detail, callback);\n\n    if (!eMarkMap.multiple) {\n      document.removeEventListener(eventName, listenOnInitialised);\n    }\n  });\n}\n\nfunction sendMetrics(eMarkMap, eventDetails, callback) {\n  const suffix = utils.buildPerfmarkSuffix(eventDetails);\n  const marks = getMarksForEvents(eMarkMap.marks, suffix);\n\n  if (eMarkMap.navigation) {\n    const navMarks = getNavigationPerfMarks(eMarkMap.navigation);\n    Object.assign(marks, navMarks);\n  }\n\n  const eventPayload = {\n    category: 'ads',\n    action: eMarkMap.spoorAction,\n    timings: {\n      marks: marks\n    }\n  };\n  eventPayload.advert = {\n    correlator: window.oAds.gpt.getCorrelator()\n  };\n\n  if (eventDetails && 'pos' in eventDetails) {\n    eventPayload.creative = {\n      name: eventDetails.name,\n      pos: eventDetails.pos,\n      size: eventDetails.size && eventDetails.size.toString(),\n      creativeId: eventDetails.creativeId || 0\n    };\n\n    if (typeof eventDetails.isEmpty === 'boolean') {\n      eventPayload.creative.isEmpty = eventDetails.isEmpty;\n    }\n  }\n\n  callback(eventPayload);\n}\n\nfunction markPageChange(definitions, groupsToClear) {\n  clearPerfMarks(definitions, groupsToClear);\n  utils.broadcast('pageChange');\n}\n\n/**\n * Utility methods for postMessage api.\n * @author Origami Advertising, origami.advertising@ft.com\n * @module utils\n */\nvar messenger = {\n  post: function (message, source) {\n    message = typeof message === 'string' ? message : JSON.stringify(message);\n    source = arguments[1] || window.top;\n    source.postMessage(message, '*');\n  },\n  parse: function (message) {\n    // Check whether the message looks like an object before trying to parse it\n    if (typeof message !== 'string' || message[0] !== '{') {\n      return message;\n    } // try returning the parsed object\n\n\n    try {\n      return JSON.parse(message);\n    } // return the original message\n    catch (e) {\n      return message;\n    }\n  }\n};\n\nlet callback;\nlet breakpoints$1;\nlet current;\n\nfunction getNearestBreakpoint() {\n  let winner;\n  const dims = oViewport.getSize(true);\n\n  function findCurrentBreakpoint(breakpoint) {\n    const breakpointDims = breakpoints$1[breakpoint];\n\n    if (dims.width >= breakpointDims[0] && dims.height >= breakpointDims[1]) {\n      if (!winner || breakpointDims[0] >= breakpoints$1[winner][0]) {\n        winner = breakpoint;\n      }\n    }\n  }\n\n  Object.keys(breakpoints$1).forEach(findCurrentBreakpoint);\n  return winner;\n}\n\nfunction fire() {\n  const winner = getNearestBreakpoint();\n\n  if (current !== winner) {\n    setCurrent(winner);\n    callback(winner);\n  }\n}\n\nfunction setCurrent(name) {\n  current = name;\n}\n\nfunction getCurrent() {\n  return current;\n}\nfunction init$2(brps, cb) {\n  if (!utils.isFunction(cb)) {\n    // must have a call back function\n    return false;\n  }\n\n  breakpoints$1 = brps;\n  callback = cb;\n  setCurrent(getNearestBreakpoint());\n  document.body.addEventListener('oViewport.orientation', fire);\n  document.body.addEventListener('oViewport.resize', fire);\n  oViewport.listenTo('orientation');\n  oViewport.listenTo('resize');\n  return getCurrent();\n}\noViewport.setThrottleInterval;\n\n/* eslint no-console: 0 */\n/**\n * Utility methods for logging.\n * @author Origami Advertising, origami.advertising@ft.com\n * @module utils/log\n * @see utils\n */\n\n/* jshint devel: true */\n\n/**\n * Safe logger for the browser\n * @exports utils/log\n * @param {string} type Sets the type of log message log, warn, error or info, if not set to one of these values log will be used\n * @param {any} args the arguments to be passed to console[type]\n */\n\nfunction log() {\n  let type;\n  let argsIndex;\n\n  if ('log warn error info'.indexOf(arguments[0]) === -1) {\n    type = 'log';\n    argsIndex = 0;\n  } else {\n    type = arguments[0];\n    argsIndex = 1;\n  }\n\n  const args = [].slice.call(arguments, argsIndex);\n\n  if (log.isOn(type)) {\n    window.console[type].apply(window.console, args);\n  }\n}\n/**\n * Determine if debug logging is on and if the type if supported\n * @param {string} type\n */\n\nconst isOn = function (type) {\n  /* istanbul ignore else  */\n  const debug = localStorage && localStorage.getItem('oAds') || location.search.indexOf('DEBUG=OADS') !== -1;\n  return debug && window.console && window.console[type];\n};\n/**\n * Log a warning message\n */\n\nconst warn = function () {\n  const args = ['warn'].concat([].slice.call(arguments, 0));\n  log.apply(null, args);\n};\n/**\n * Log an error message\n */\n\nconst error = function () {\n  const args = ['error'].concat([].slice.call(arguments, 0));\n  log.apply(null, args);\n};\n/**\n * Log an info message\n */\n\nconst info = function () {\n  const args = ['info'].concat([].slice.call(arguments, 0));\n  log.apply(null, args);\n};\n/**\n * Start a collapsed group\n * @param {string} group the name of the group, defaults to o-ads\n */\n\nconst start = function (group) {\n  if (!log.isOn('groupCollapsed')) {\n    return;\n  }\n\n  window.console.groupCollapsed(group || 'o-ads');\n};\n/**\n * End a collapsed group\n */\n\nconst end = function () {\n  if (!log.isOn('groupEnd')) {\n    return;\n  }\n\n  window.console.groupEnd();\n};\nconst table = function (data, columns) {\n  if (log.isOn('log') && window.console) {\n    if (console.table) {\n      console.table(data, columns);\n    } else {\n      console.log(data);\n    }\n  }\n};\nconst attributeTable = function (object, columns) {\n  if (log.isOn('log') && window.console) {\n    if (object && console.table) {\n      const data = Object.keys(object).map(item => {\n        let val;\n\n        if (isArray(object[item]) || isObject(object[item])) {\n          val = JSON.stringify(object[item]);\n        } else {\n          val = object[item];\n        }\n\n        return {\n          key: item,\n          value: val\n        };\n      });\n      console.table(data, columns);\n    } else {\n      console.log(object);\n    }\n  }\n};\n\n// generated by genversion\nvar version = '18.3.3';\n\n/**\n * Utility methods for the advertising library.\n * @author Origami Advertising, origami.advertising@ft.com\n * @module utils\n */\n\nconst hop = Object.prototype.hasOwnProperty;\ninit$2.getCurrent = getCurrent;\nlog.start = start;\nlog.end = end;\nlog.isOn = isOn;\nlog.info = info;\nlog.warn = warn;\nlog.error = error;\nlog.table = table;\nlog.attributeTable = attributeTable;\n/**\n * Uses object prototype toString method to get at the type of object we are dealing,\n * IE returns [object Object] for null and undefined so we need to filter those\n * http://es5.github.com/#x15.2.4.2\n * @private\n * @param {object} Any javascript object\n * @returns The type of the object e.g Array, String, Object\n */\n\nfunction is(object) {\n  const type = Object.prototype.toString.call(object).match(/^\\[object\\s(.*)\\]$/)[1];\n\n  if (object === null) {\n    return 'Null';\n  } else if (object === undefined) {\n    return 'Undefined';\n  } else {\n    return type;\n  }\n}\n/**\n * Test if an object is an Array\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is of type Array, otherwise false\n */\n\n\nconst isArray = function (obj) {\n  return is(obj) === 'Array';\n};\n/**\n * Test if an object is a String\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is of type String, otherwise false\n */\n\nconst isString = function (obj) {\n  return is(obj) === 'String';\n};\n/**\n * Test if an object is a Function\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is of type Function, otherwise false\n */\n\nconst isFunction = function (obj) {\n  return is(obj) === 'Function';\n};\n/**\n * Test if an object is a Storage object\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is of type Storage, otherwise false\n */\n\nconst isStorage = function (obj) {\n  return is(obj) === 'Storage';\n};\n/**\n * Test if an object is an Object\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is of type Object, otherwise false\n */\n\nconst isObject = function (obj) {\n  return is(obj) === 'Object';\n};\n/**\n * Test if an object is the global window object\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is the window obj, otherwise false\n */\n\nconst isWindow = function (obj) {\n  return obj && obj !== null && obj === window;\n};\n/**\n * Test if an object inherits from any other objects, used in extend\n * to protect against deep copies running out of memory and constructors\n * losing there prototypes when cloned\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is plain false otherwise\n */\n\nconst isPlainObject = function (obj) {\n  const hop = Object.prototype.hasOwnProperty; // Must be an Object.\n  // Because of IE, we also have to check the presence of the constructor property.\n  // Make sure that DOM nodes and window objects don't pass through, as well\n\n  if (!obj || !isObject(obj) || obj.nodeType || isWindow(obj)) {\n    return false;\n  }\n\n  try {\n    // Not own constructor property must be Object\n    if (obj.constructor && !hop.call(obj, 'constructor') && !hop.call(obj.constructor.prototype, 'isPrototypeOf')) {\n      return false;\n    }\n  } catch (e) {\n    /* istanbul ignore next  */\n    // IE8,9 Will throw exceptions on certain host objects\n    return false;\n  } // Own properties are enumerated firstly, so to speed up,\n  // if last one is own, then all properties are own.\n\n\n  let key;\n\n  for (key in obj) {// empty\n  }\n\n  return key === undefined || hop.call(obj, key);\n};\n/**\n * Test if an object is a string with a length\n * @param {object} str The object to be tested\n * @returns {boolean} true if the object is a string with a length greater than 0\n */\n\nconst isNonEmptyString = function (str) {\n  return isString(str) && Boolean(str.length);\n};\nconst isElement = function (element) {\n  return element && element.nodeType === 1 && element.tagName || false;\n};\nfunction extend() {\n  /* jshint forin: false */\n\n  /* when doing a deep copy we want to copy prototype properties */\n  let options;\n  let src;\n  let copy;\n  let copyIsArray;\n  let clone;\n  let target = arguments[0] || {};\n  const length = arguments.length;\n  let deep = false;\n  let i = 1; // Handle a deep copy situation\n\n  if (typeof target === 'boolean') {\n    deep = target;\n    target = arguments[1] || {}; // skip the boolean and the target\n\n    i = 2;\n  } // Handle case when target is a string or something (possible in deep copy)\n\n  /* istanbul ignore else  */\n\n\n  if (typeof target !== 'object' && !isFunction(target)) {\n    target = {};\n  } // do nothing if only one argument is passed (or 2 for a deep copy)\n\n  /* istanbul ignore else  */\n\n\n  if (length === i) {\n    return target;\n  }\n\n  for (; i < length; i++) {\n    // Only deal with non-null/undefined values\n    if ((options = arguments[i]) !== null) {\n      // Extend the base object\n      for (const name in options) {\n        /* istanbul ignore next */\n        if (options.hasOwnProperty(name)) {\n          src = target[name];\n          copy = options[name]; // Prevent never-ending loop\n\n          if (target === copy) {\n            continue;\n          } // Recurse if we're merging arrays\n\n\n          if (deep && copy && (isPlainObject(copy) || isArray(copy))) {\n            copyIsArray = isArray(copy);\n\n            if (copyIsArray) {\n              copyIsArray = false;\n              clone = src && isArray(src) ? src : [];\n            } else {\n              clone = src && isObject(src) ? src : {};\n            } // Never move original objects, clone them\n\n\n            target[name] = extend(deep, clone, copy); // Don't bring in undefined values\n          } else if (copy !== undefined) {\n            target[name] = copy;\n          }\n        }\n      }\n    }\n  } // Return the modified object\n\n\n  return target;\n}\n/**\n * Create an object hash from a delimited string\n * Beware all properties on the resulting object will have string values.\n * @param {string}        str       The string to transform\n * @param {string|regexp} delimiter The character that delimits each name/value pair\n * @param {string}        pairing   The character that separates the name from the value\n * @return {object}\n *\n */\n\nconst hash = function (str, delimiter, pairing) {\n  let pair;\n  let value;\n  const hashObj = {};\n\n  if (str && str.split) {\n    str = str.split(delimiter);\n\n    for (let idx = 0, l = str.length; idx < l; idx += 1) {\n      value = str[idx];\n      pair = value.split(pairing);\n\n      if (pair.length > 1) {\n        hashObj[pair[0].trim()] = pair.slice(1).join(pairing);\n      }\n    }\n  }\n\n  return hashObj;\n};\n/**\n * Takes a script URL as a string value, creates a new script element, sets the src and attaches to the page\n * The async value of the script can be set by the seccond parameter, which is a boolean\n * Note, we should use protocol-relative URL paths to ensure we don't run into http/https issues\n * @param {string} scriptUrl The url to the script file to be added\n * @param {boolean} async Set the async attribute on the script tag\n * @param {function} callback A function to run when the script loads\n * @param {function} errorcb A function to run if the script fails to load\n * @returns {HTMLElement} the created script tag\n */\n\nconst attach = function (scriptUrl, async, callback, errorcb, autoRemove) {\n  const tag = document.createElement('script');\n  const node = document.getElementsByTagName('script')[0];\n  let hasRun = false;\n\n  function processCallback(callback) {\n    /* istanbul ignore else  */\n    if (!hasRun) {\n      callback.call();\n      hasRun = true;\n      /* istanbul ignore else  */\n\n      if (autoRemove) {\n        tag.parentElement.removeChild(tag);\n      }\n    }\n  }\n\n  tag.setAttribute('src', scriptUrl);\n  tag.setAttribute('o-ads', '');\n  /* istanbul ignore else */\n\n  if (async) {\n    tag.async = 'true';\n  }\n  /* istanbul ignore else  */\n\n\n  if (isFunction(callback)) {\n    /* istanbul ignore if - legacy IE code, won't test */\n    if (hop.call(tag, 'onreadystatechange')) {\n      tag.onreadystatechange = function () {\n        if (tag.readyState === 'loaded') {\n          processCallback(callback);\n        }\n      };\n    } else {\n      tag.onload = function () {\n        processCallback(callback);\n      };\n    }\n  }\n  /* istanbul ignore else  */\n\n\n  if (isFunction(errorcb)) {\n    tag.onerror = function () {\n      processCallback(errorcb);\n    };\n  } // Use insert before, append child has issues with script tags in some browsers.\n\n\n  node.parentNode.insertBefore(tag, node);\n  return tag;\n};\n/**\n * return the current documents referrer or an empty string if non exists\n * This method enables us to mock the referrer in our tests reliably and doesn't really serve any other purpose\n * @returns {string} document.referrer\n */\n\n/* istanbul ignore next - cannot reliably test value of referer */\n\nconst getReferrer = function () {\n  return document.referrer || '';\n};\n/**\n * Remove hyphens from a string and upper case the following letter\n * @param {string} string the string to parse\n * @returns {string}\n */\n\nconst dehyphenise = function (string) {\n  return string.replace(/(-)([a-z])/g, function (match, hyphen, letter) {\n    return letter.toUpperCase();\n  });\n};\n/**\n * remove prefixes from o-ads data attributes and dehyphenise the name\n * @param {string|} name the name of the attribute to parse\n * @returns {string}\n */\n\nconst parseAttributeName = function (attribute) {\n  const name = isString(attribute) ? attribute : attribute.name;\n  return dehyphenise(name.replace(/(data-)?o-ads-/, ''));\n};\n/**\n * return the current documents url or an empty string if non exists\n * This method enables us to mock the document location string in our tests reliably and doesn't really serve any other purpose\n * @returns {string}\n */\n\n/* istanbul ignore next - cannot reliably test value of location */\n\nconst getLocation = function () {\n  return document.location.href || '';\n};\n/**\n * return the current documents search or an empty string if non exists\n * also strips the initial ? from the search string for easier parsing\n * This method enables us to mock the search string in our tests reliably and doesn't really serve any other purpose\n * @returns {string}\n */\n\nconst getQueryString = function () {\n  return document.location.search.substring(1) || '';\n};\n/**\n * Get a query string parameter by name from a url\n * @param name\n * @param url\n * @returns {string | null}\n */\n\nconst getQueryParamByName = function (name, url) {\n  url = url || window.location.href;\n  name = name.replace(/[[\\]]/g, '\\\\$&');\n  const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');\n  const results = regex.exec(url);\n\n  if (!results) {\n    return null;\n  }\n\n  if (!results[2]) {\n    return '';\n  }\n\n  return decodeURIComponent(results[2].replace(/\\+/g, ' '));\n};\n/**\n * returns a timestamp of the current date/time in the format YYYYMMDDHHMMSS\n * @returns {string}\n */\n\nconst getTimestamp = function () {\n  const now = new Date();\n  return [now.getFullYear(), `0${now.getMonth() + 1}`.slice(-2), `0${now.getDate()}`.slice(-2), `0${now.getHours()}`.slice(-2), `0${now.getMinutes()}`.slice(-2), `0${now.getSeconds()}`.slice(-2)].join('');\n};\n/**\n * Given the window object of an iframe this method returns the o-ads slot name\n * that rendered the iframe, if the iframe was not rendered by o-ads this will\n * return false\n * @param {window}  a window object\n * @returns {String|Boolean}\n */\n\nconst iframeToSlotName = function (iframeWindow) {\n  // capture all iframes in the page in a live node list\n  const iframes = document.getElementsByTagName('iframe');\n  let slotName;\n  let node;\n  let i = iframes.length; // Figure out which iframe DOM node we have the window for\n\n  while (i--) {\n    /* istanbul ignore else  */\n    if (iframes[i].contentWindow === iframeWindow) {\n      node = iframes[i];\n      break;\n    }\n  }\n  /* istanbul ignore else  */\n\n\n  if (node) {\n    // find the closest parent with a data-o-ads-name attribute, that's our slot name\n    while (node.parentNode) {\n      slotName = node.getAttribute('data-o-ads-name');\n      /* istanbul ignore else  */\n\n      if (slotName) {\n        return slotName;\n      }\n\n      node = node.parentNode;\n    }\n  }\n\n  return false;\n};\nconst buildObjectFromArray = function buildObjectFromArray(targetObject) {\n  return targetObject.reduce((prev, data) => {\n    prev[data.key] = data.value;\n    return prev;\n  }, {});\n};\nconst cookie = function (name) {\n  const val = document.cookie.match(`(^|;)\\\\s*${name}\\\\s*=\\\\s*([^;]+)`);\n  return val ? val.pop() : null;\n};\nconst getVersion = () => version ;\nconst metricsSampleThreshold = Math.random();\nfunction inSample(sampleSize) {\n  return typeof sampleSize === 'undefined' || sampleSize > metricsSampleThreshold;\n}\nvar utils = {\n  on,\n  off,\n  once,\n  broadcast,\n  messenger,\n  responsive: init$2,\n  log,\n  isArray,\n  isString,\n  isFunction,\n  isStorage,\n  isObject,\n  isWindow,\n  isPlainObject,\n  isNonEmptyString,\n  isElement,\n  extend,\n  hash,\n  attach,\n  getReferrer,\n  dehyphenise,\n  parseAttributeName,\n  getLocation,\n  getQueryString,\n  getQueryParamByName,\n  getTimestamp,\n  iframeToSlotName,\n  buildObjectFromArray,\n  cookie,\n  getVersion,\n  setupMetrics,\n  clearPerfMarks,\n  markPageChange,\n  inSample,\n  perfMark,\n  buildPerfmarkSuffix\n};\n\n//TODO remove all ft.com specific stuff so we can remove this as a global\n/**\n* Default configuration set in the constructor.\n*/\n\nconst defaults = {\n  formats: {\n    PartnerContent: {\n      sizes: ['fluid']\n    },\n    MediumRectangle: {\n      sizes: [300, 250]\n    },\n    Rectangle: {\n      sizes: [180, 50]\n    },\n    WideSkyscraper: {\n      sizes: [160, 600]\n    },\n    Leaderboard: {\n      sizes: [728, 90]\n    },\n    SuperLeaderboard: {\n      sizes: [[970, 90], [970, 66]]\n    },\n    HalfPage: {\n      sizes: [300, 600]\n    },\n    Billboard: {\n      sizes: [970, 250]\n    },\n    Portrait: {\n      sizes: [300, 1050]\n    },\n    AdhesionBanner: {\n      sizes: [320, 50]\n    },\n    MicroBar: {\n      sizes: [88, 31]\n    },\n    Button2: {\n      sizes: [120, 60]\n    },\n    Responsive: {\n      sizes: [2, 2]\n    }\n  },\n  responsive: {\n    extra: [1025, 0],\n    //Reasonable width to show a Billboard (desktop)\n    large: [1000, 0],\n    //reasonable width to show SuperLeaderboard (tablet landscape)\n    medium: [760, 0],\n    //reasonable width to show a leaderboard (tablet portrait)\n    small: [0, 0] //Mobile\n\n  },\n  flags: {\n    refresh: true,\n    inview: true\n  },\n  displayLabelWithBorders: false\n};\n\nfunction fetchDeclaritiveConfig() {\n  let results = {};\n  const scripts = Array.from(document.querySelectorAll('script[data-o-ads-config]'));\n  scripts.forEach(script => {\n    results = window.JSON ? utils.extend(results, JSON.parse(script.innerHTML)) : 'UNSUPPORTED';\n  });\n  return results;\n}\n/**\n* @private\n* @function\n* fetchCanonicalURL Grabs the canonical URL from the page meta if it exists.\n*/\n\n\nfunction fetchCanonicalURL() {\n  let canonical;\n  const canonicalTag = document.querySelector('link[rel=\"canonical\"]');\n\n  if (canonicalTag) {\n    canonical = canonicalTag.href;\n  }\n\n  return {\n    canonical: canonical\n  };\n}\n/**\n* Defines a store for configuration information and returns a getter/setter method for access.\n* @class\n* @constructor\n*/\n\n\nfunction Config() {\n  this.store = {};\n}\n\nConfig.prototype.access = function (k, v) {\n  let result;\n\n  if (utils.isPlainObject(k)) {\n    utils.extend(true, this.store, k);\n    result = this.store;\n  } else if (typeof v === 'undefined') {\n    if (typeof k === 'undefined') {\n      result = this.store;\n    } else {\n      result = this.store[k];\n    }\n  } else {\n    this.store[k] = v;\n    result = v;\n  }\n\n  return result;\n};\n\nConfig.prototype.clear = function (key) {\n  if (key) {\n    delete this.store[key];\n  } else {\n    this.store = {};\n  }\n};\n\nConfig.prototype.init = function () {\n  this.store = utils.extend(true, {}, defaults, fetchCanonicalURL(), fetchDeclaritiveConfig());\n  return this.store;\n};\n\nconst config = new Config();\nvar config$1 = config.access.bind(config);\nconst init$1 = config.init.bind(config);\nconst clear = config.clear.bind(config);\n\nconst VALID_SIZE_STRINGS = ['fluid'];\nconst VALID_COLLAPSE_MODES = ['before', 'after', 'never'];\nconst attributeParsers = {\n  sizes: function (value, sizes) {\n    if (value === false || value === 'false') {\n      return false;\n    }\n    /* istanbul ignore else  */\n    else if (utils.isArray(sizes)) {\n      const regex = /(\\d+)x(\\d+)/;\n      value.split(',').filter(size => size.length).forEach(size => {\n        if (regex.test(size)) {\n          size.replace(regex, function (match, width, height) {\n            sizes.push([parseInt(width, 10), parseInt(height, 10)]);\n          });\n        } else if (VALID_SIZE_STRINGS.indexOf(size) >= 0) {\n          sizes.push(size);\n        }\n      });\n    }\n\n    return sizes;\n  },\n  formats: function (value, sizes) {\n    if (value === false || value === 'false') {\n      sizes = false;\n    } else {\n      const mapping = config$1().formats;\n      const formats = utils.isArray(value) ? value : value.split(',');\n      formats.forEach(format => {\n        if (mapping && mapping[format]) {\n          format = mapping[format];\n\n          if (utils.isArray(format.sizes[0]) || VALID_SIZE_STRINGS.indexOf(format.sizes[0]) >= 0) {\n            format.sizes.forEach(size => {\n              sizes.push(size);\n            });\n          } else {\n            sizes.push(format.sizes);\n          }\n        } else {\n          utils.log.error(`Slot configured with unknown format ${format}`);\n        }\n      });\n    }\n\n    return sizes;\n  },\n  responsiveSizes: function (name, value, sizes) {\n    const screenName = name.replace(/^sizes/, '').toLowerCase();\n    /* istanbul ignore else\t*/\n\n    if (!utils.isPlainObject(sizes)) {\n      sizes = {};\n    }\n\n    sizes[screenName] = attributeParsers.sizes(value, sizes[screenName] || []);\n    return sizes;\n  },\n  responsiveFormats: function (name, value, sizes) {\n    const screenName = name.replace(/^formats/, '').toLowerCase();\n    /* istanbul ignore else\t*/\n\n    if (!utils.isPlainObject(sizes)) {\n      sizes = {};\n    }\n\n    sizes[screenName] = attributeParsers.formats(value, []);\n    return sizes;\n  },\n  lazyLoadThreshold: function (value) {\n    return value.split(',').map(Number);\n  },\n  targeting: function (value, targeting) {\n    value = utils.hash(value, ';', '=');\n    utils.extend(targeting, value);\n    return targeting;\n  },\n  base: function (value) {\n    /* istanbul ignore else\t*/\n    if (value === '' || value === 'true') {\n      value = true;\n    } else if (value === 'false') {\n      value = false;\n    }\n\n    return value;\n  },\n  collapseEmpty: function (value) {\n    const isUnknownAttribute = VALID_COLLAPSE_MODES.indexOf(value) === -1;\n\n    if (isUnknownAttribute) {\n      utils.log.warn(`Invalid attribute ${value} used for collapse-empty attribute, please use 'before', 'after' or 'never'`);\n      return undefined;\n    }\n\n    return value;\n  }\n};\n\nconst convertLazyLoadBooleanToObject = obj => {\n  if (obj.lazyLoad === true) {\n    obj.lazyLoad = {};\n  }\n};\n\nconst onChangeBreakpoint = event => {\n  const slot = event.detail.slot;\n  slot.screensize = event.detail.screensize;\n\n  if (slot.hasValidSize()) {\n    slot.uncollapse();\n  } else {\n    slot.collapse();\n    slot.clear();\n  }\n};\n/**\n * The Slot class.\n * @class\n * @constructor\n */\n\n\nfunction Slot(container, screensize, initLazyLoading) {\n  const renderEvent = 'slotRenderStart';\n  const cfg = config$1();\n  let slotConfig = config$1('slots') || {}; // store the container\n\n  this.container = container; // the current responsive screensize\n\n  /* istanbul ignore else\t*/\n\n  if (screensize) {\n    this.screensize = screensize;\n  } // init slot dom structure\n\n\n  this.outer = this.addContainer(container, {\n    'class': 'o-ads__outer',\n    'aria-hidden': 'true',\n    'tabindex': '-1'\n  });\n  this.inner = this.addContainer(this.outer, {\n    'class': 'o-ads__inner'\n  }); // make sure the slot has a name\n\n  this.setName();\n  slotConfig = slotConfig[this.name] || {}; // default configuration properties\n\n  this.server = 'gpt';\n  this.defer = false; // global slots configuration\n\n  this.targeting = slotConfig.targeting || {};\n  this.sizes = slotConfig.sizes || [];\n  this.center = slotConfig.center || false;\n  this.label = slotConfig.label || false;\n  this.outOfPage = slotConfig.outOfPage || false;\n  this.companion = slotConfig.companion === false ? false : true;\n  this.collapseEmpty = slotConfig.collapseEmpty;\n  /* istanbul ignore else */\n\n  if (utils.isArray(slotConfig.formats)) {\n    attributeParsers.formats(slotConfig.formats, this.sizes);\n  } else if (utils.isPlainObject(slotConfig.formats)) {\n    this.sizes = {};\n    Object.keys(slotConfig.formats).forEach(screenName => {\n      this.sizes[screenName] = attributeParsers.formats(slotConfig.formats[screenName], []);\n    });\n  }\n\n  if (typeof slotConfig.lazyLoad !== 'undefined') {\n    this.lazyLoad = slotConfig.lazyLoad;\n  } else {\n    this.lazyLoad = config$1('lazyLoad') || false;\n  }\n\n  const outerEl = container.querySelector('.o-ads__outer');\n\n  if (outerEl && cfg.displayLabelWithBorders && this.container.getAttribute('data-o-ads-label')) {\n    const allowedLabels = ['left', 'center', 'right'];\n    const adsLabelPos = this.container.getAttribute('data-o-ads-label');\n    utils.once(renderEvent, () => {\n      const modifier = allowedLabels.indexOf(adsLabelPos) ? adsLabelPos : \"left\";\n      outerEl.classList.add('o-ads--label-with-borders', `o-ads--label-with-borders--${modifier}`);\n    });\n  } // extend with imperative configuration options\n\n\n  this.parseAttributeConfig();\n  /* istanbul ignore else\t*/\n\n  if (!this.sizes.length && !utils.isPlainObject(this.sizes)) {\n    utils.log.error('slot %s has no configured sizes!', this.name);\n    return false;\n  } // Either retrieve the existing IntersectionObserver, or tell slots.js to create a new one.\n\n\n  this.lazyLoadObserver = initLazyLoading(this.lazyLoad);\n  this.initLazyLoad();\n  this.centerContainer();\n  this.labelContainer();\n  this.initResponsive();\n}\n/**\n * parse slot attribute config\n */\n\n\nSlot.prototype.parseAttributeConfig = function () {\n  Array.from(this.container.attributes).forEach(attribute => {\n    const name = utils.parseAttributeName(attribute.name);\n    const value = attribute.value;\n\n    if (name === 'formats') {\n      this[name] = attributeParsers[name](value, this.sizes);\n    } else if (name === 'collapseEmpty') {\n      this.collapseEmpty = attributeParsers.collapseEmpty(value);\n    } else if (name === 'lazyLoadThreshold' && this.lazyLoad) {\n      convertLazyLoadBooleanToObject(this);\n      this.lazyLoad.threshold = attributeParsers.lazyLoadThreshold(value);\n    } else if (name === 'lazyLoadViewportMargin' && this.lazyLoad) {\n      convertLazyLoadBooleanToObject(this);\n      this.lazyLoad.viewportMargin = attributeParsers.base(value);\n    } else if (attributeParsers[name]) {\n      this[name] = attributeParsers[name](value, this[name]);\n    } else if (/^formats\\w*/.test(name)) {\n      this.sizes = attributeParsers.responsiveFormats(name, value, this.sizes);\n    } else if (/^sizes\\w*/.test(name)) {\n      this.sizes = attributeParsers.responsiveSizes(name, value, this.sizes);\n    } else if (this.hasOwnProperty(name)) {\n      this[name] = attributeParsers.base(value);\n    }\n  });\n};\n\nSlot.prototype.getAttributes = function () {\n  const attributes = {};\n  Array.from(this.container.attributes).forEach(attribute => {\n    attributes[utils.parseAttributeName(attribute)] = attribute.value;\n  });\n  this.attributes = attributes;\n  return this;\n};\n/**\n *\tLoad a slot when it appears in the viewport\n */\n\n\nSlot.prototype.initLazyLoad = function () {\n  /* istanbul ignore else  */\n  if (this.lazyLoadObserver && this.lazyLoad) {\n    this.defer = true;\n    this.lazyLoadObserver.observe(this.container); //Master/Companion ads don't work with lazy loading, so if a master ad loads trigger\n\n    /* istanbul ignore else */\n\n    if (this.companion) {\n      utils.once('masterLoaded', () => {\n        if (this.hasValidSize()) {\n          this.render();\n        }\n      }, this.container);\n    }\n  }\n\n  return this;\n};\n\nSlot.prototype.render = function () {\n  this.fire('slotCanRender');\n  /* istanbul ignore else  */\n\n  if (this.lazyLoadObserver) {\n    this.lazyLoadObserver.unobserve(this.container);\n  }\n};\n/**\n *\tListen to responsive breakpoints and collapse slots\n * where the configured size is set to false\n */\n\n\nSlot.prototype.initResponsive = function () {\n  /* istanbul ignore else */\n  if (utils.isPlainObject(this.sizes)) {\n    /* istanbul ignore else */\n    if (!this.hasValidSize()) {\n      this.collapse();\n    }\n\n    utils.on('breakpoint', onChangeBreakpoint, this.container);\n  }\n\n  return this;\n};\n/**\n * Maximise the slot when size is 100x100\n */\n\n\nSlot.prototype.maximise = function (size) {\n  if (size && Number(size[0]) === 100 && Number(size[1]) === 100) {\n    this.fire('resize', {\n      size: ['100%', '100%']\n    });\n  }\n};\n/**\n *\tIf the slot doesn't have a name give it one\n */\n\n\nSlot.prototype.setName = function () {\n  this.name = this.container.getAttribute('data-o-ads-name') || this.container.getAttribute('o-ads-name');\n\n  if (!this.name) {\n    this.name = `o-ads-slot-${Math.floor(Math.random() * 10000)}`;\n    this.container.setAttribute('data-o-ads-name', this.name);\n  }\n\n  return this;\n};\n/**\n * add the empty class to the slot\n */\n\n\nSlot.prototype.collapse = function () {\n  this.container.classList.add('o-ads--empty');\n  this.setFormatLoaded(false);\n  document.body.classList.add(`o-ads-no-${this.name}`);\n  utils.broadcast('collapsed', this);\n  return this;\n};\n/**\n * add the additional class to the slot\n */\n\n\nSlot.prototype.addClass = function (className) {\n  this.container.classList.add(`o-ads-${className}`);\n  utils.broadcast('slotClassAdded', this);\n  return this;\n};\n/**\n * sets a classname of the format\n */\n\n\nSlot.prototype.setFormatLoaded = function (format) {\n  this.container.setAttribute('data-o-ads-loaded', format);\n  return this;\n};\n/**\n * remove the empty class from the slot\n */\n\n\nSlot.prototype.uncollapse = function () {\n  this.container.classList.remove('o-ads--empty');\n  document.body.classList.remove(`o-ads-no-${this.name}`);\n  return this;\n};\n/**\n * call the ad server clear method on the slot if one exists\n */\n\n\nSlot.prototype.clear = function () {\n  /* istanbul ignore else  */\n  if (utils.isFunction(this['clearSlot'])) {\n    this.clearSlot();\n  }\n\n  return this;\n};\n/**\n * call the ad server destroySlot method on the slot if one exists\n */\n\n\nSlot.prototype.destroy = function () {\n  /* istanbul ignore else  */\n  if (utils.isFunction(this['destroySlot'])) {\n    utils.off('breakpoint', onChangeBreakpoint, this.container);\n    this.destroySlot();\n\n    if (this.outer.parentElement === this.container) {\n      this.container.removeChild(this.outer);\n    } else {\n      console.error('Error destroying ad slot. The parent node has already been removed.'); // eslint-disable-line no-console\n    }\n  }\n\n  return this;\n};\n/**\n * call the ad server impression URL for an out of page slot if it has been configured correctly for delayed impressions\n */\n\n\nSlot.prototype.submitImpression = function () {\n  /* istanbul ignore else  */\n  if (utils.isFunction(this['submitGptImpression'])) {\n    this.submitGptImpression();\n  }\n\n  return this;\n};\n/**\n *\tfire an event on the slot\n */\n\n\nSlot.prototype.fire = function (name, data) {\n  const gpt = this.gpt || {};\n  const details = {\n    name: this.name || '',\n    pos: this.targeting && this.targeting.pos || '',\n    size: gpt.size || '',\n    creativeId: gpt.creativeId || '',\n    slot: this\n  };\n\n  if (typeof gpt.isEmpty === 'boolean') {\n    details.isEmpty = gpt.isEmpty;\n  }\n\n  if (utils.isPlainObject(data)) {\n    utils.extend(details, data);\n  }\n\n  utils.broadcast(name, details, this.container);\n  return this;\n};\n/**\n *\tadd a div tag into the current slot container\n **/\n\n\nSlot.prototype.addContainer = function (node, attrs) {\n  let container = '<div ';\n  /* istanbul ignore else  */\n\n  if (attrs) {\n    Object.keys(attrs).forEach(function (attr) {\n      const value = attrs[attr];\n      container += `${attr}=${value} `;\n    });\n  }\n\n  container += '></div>';\n  node.insertAdjacentHTML('beforeend', container);\n  return node.lastChild;\n};\n\nSlot.prototype.hasValidSize = function (screensize) {\n  screensize = screensize || this.screensize;\n\n  if (screensize && utils.isPlainObject(this.sizes)) {\n    return this.sizes[screensize] !== false;\n  }\n\n  return true;\n};\n/**\n * Add a center class to the main container\n */\n\n\nSlot.prototype.centerContainer = function () {\n  if (this.center) {\n    this.container.classList.add('o-ads--center');\n  }\n\n  return this;\n};\n/**\n * Add a label class to the main container\n */\n\n\nSlot.prototype.labelContainer = function () {\n  let className;\n\n  if (this.label === true || this.label === 'left') {\n    className = 'label-left';\n  } else if (this.label === 'right') {\n    className = 'label-right';\n  }\n\n  if (className && !config$1('displayLabelWithBorders')) {\n    this.container.classList.add(`o-ads--${className}`);\n  }\n\n  return this;\n};\n\n/** @typedef {import(\"$typings/index\")} Advertising */\n\n/**\n * @param {Advertising.Slot} slot\n * @returns {string}\n */\nfunction getSlotSizes(slot) {\n  if (!Array.isArray(slot.sizes)) return \"responsive slot\";\n  const sizes = [];\n\n  for (const size of slot.sizes) {\n    sizes.push(Array.isArray(size) ? size.join(\"×\") : size);\n  }\n\n  return sizes.join(\", \");\n}\n/**\n * @param {Advertising.Slot} slot\n * @returns {string}\n */\n\n\nfunction getSlotTargeting({\n  targeting\n}) {\n  const params = [];\n\n  for (const [key, val] of Object.entries(targeting)) {\n    params.push(`${key}=${val}`);\n  }\n\n  return params.join(\", \");\n}\n/**\n * @param {Advertising.Slot} slot\n * @returns {string}\n */\n\n\nfunction getSlotGPTSize({\n  gpt\n}) {\n  if (gpt.isEmpty) return \"empty\";\n  if (!Array.isArray(gpt.size)) return \"N/A\";\n  return gpt.size.join(\"×\");\n}\n/**\n * Use a type predicate to distinguish between the `Slots` instance's properties\n * @type {(o: Advertising.Slot | IntersectionObserver) => o is Advertising.Slot }\n */\n\n\nconst isSlot = o => \"name\" in o;\n/**\n * @param {(Advertising.Slot | IntersectionObserver)[]} slots\n */\n\n\nfunction debug$1(slots) {\n  const data = [];\n\n  for (const slot of slots) {\n    if (isSlot(slot)) {\n      const row = {\n        name: slot.name,\n        \"unit name\": slot.gpt.unitName,\n        \"creative id\": slot.gpt.creativeId || \"N/A\",\n        \"line item id\": slot.gpt.lineItemId || \"N/A\",\n        size: getSlotGPTSize(slot),\n        sizes: getSlotSizes(slot),\n        targeting: getSlotTargeting(slot)\n      };\n      data.push(row);\n    }\n  }\n\n  console.group(\"Creatives\");\n  console.table(data);\n  console.groupEnd();\n  return data;\n}\n\n/* eslint no-inner-declarations: 1 */\nlet screensize = null;\n/**\n * The Slots instance tracks all ad slots on the page\n * configures global page events used by a slot and\n * provides utlity methods that act on all slots\n * @constructor\n */\n\nfunction Slots() {//eslint-disable-line no-empty\n}\n\nfunction invokeMethodOnSlots(names, method, callback) {\n  let slots = [];\n  names = names || Object.keys(this);\n  /* istanbul ignore else\t*/\n\n  if (utils.isNonEmptyString(names)) {\n    slots.push(names);\n  } else if (utils.isArray(names)) {\n    slots = names;\n  }\n\n  slots.forEach(run.bind(null, this, method));\n\n  if (utils.isFunction(callback)) {\n    callback.call(this, slots);\n  }\n\n  return this;\n}\n/*\n * Either run a method or fire an event on the named slot.\n * @private\n * @param slots the slots object\n */\n\n\nfunction run(slots, action, name) {\n  const slot = slots[name];\n\n  if (slot) {\n    if (utils.isFunction(slot[action])) {\n      slot[action]();\n    } else {\n      if (utils.isFunction(slot.fire)) {\n        slot.fire(action);\n      } else {\n        utils.log.warn(\"Attempted to %s on a non-slot %s\", action, name);\n      }\n    }\n  } else {\n    utils.log.warn(\"Attempted to %s non-existant slot %s\", action, name);\n  }\n}\n\nfunction findFormatBySize(size) {\n  if (!size) {\n    return false;\n  }\n\n  const formats = config$1(\"formats\");\n\n  for (const prop in formats) {\n    /* istanbul ignore else\t*/\n    if (formats.hasOwnProperty(prop)) {\n      let sizes = formats[prop].sizes;\n      sizes = utils.isArray(sizes[0]) ? sizes : [sizes];\n      const match = sizes.filter(function (s) {\n        return s[0] === parseInt(size[0], 10) && s[1] === parseInt(size[1], 10);\n      });\n\n      if (match.length) {\n        return prop;\n      }\n    }\n  }\n}\n/**\n * Given a slot name or an array of slot names will collapse the slots using the collapse method on the slot\n */\n\n\nSlots.prototype.collapse = function (names) {\n  return invokeMethodOnSlots.call(this, names, \"collapse\");\n};\n/**\n * Given a slot name or an array of slot names will uncollapse the slots using the uncollapse method on the slot\n */\n\n\nSlots.prototype.uncollapse = function (names) {\n  return invokeMethodOnSlots.call(this, names, \"uncollapse\");\n};\n/**\n * Given a slot name or an array of slot names of slotnames will refresh the slots using the refresh method on the slot\n */\n\n\nSlots.prototype.refresh = function (names) {\n  return invokeMethodOnSlots.call(this, names, \"refresh\");\n};\n/**\n * Given a slot name or an array of slot names will clear the slots using the clear method on the slot\n */\n\n\nSlots.prototype.clear = function (names) {\n  return invokeMethodOnSlots.call(this, names, \"clear\");\n};\n/**\n * Given a slot name or an array of slot names will destroy the slots using the destroySlot method on the slot and remove the reference to the slot\n */\n\n\nSlots.prototype.destroy = function (names) {\n  return invokeMethodOnSlots.call(this, names, \"destroy\", function (names) {\n    names.forEach(name => {\n      this[name] = null;\n      delete this[name];\n    });\n  });\n};\n/**\n * Given a slot name will submit a delayed impression for the slot\n */\n\n\nSlots.prototype.submitImpression = function (name) {\n  return invokeMethodOnSlots.call(this, name, \"submitImpression\");\n};\n/**\n * Confirms a container in the page exists and creates a Slot object\n */\n\n\nSlots.prototype.initSlot = function (container) {\n  // if container is a string this is a legacy implementation using ids\n  // find the element and remove the ID in favour of a data attribute\n  if (utils.isString(container)) {\n    container = document.getElementById(container) || document.querySelector(`[data-o-ads-name=\"${container}\"]`);\n\n    if (container && container.id) {\n      container.setAttribute(\"data-o-ads-name\", container.id);\n      container.removeAttribute(\"id\");\n    }\n  } // if not an element or we can't find it in the DOM exit\n\n\n  if (!utils.isElement(container)) {\n    utils.log.error(\"slot container must be an element!\", container);\n    return false;\n  } // add the aria hidden attribute\n\n\n  container.setAttribute(\"aria-hidden\", \"true\"); // pass the method to retrieve or create the single IntersectionObserver instance\n\n  const slot = new Slot(container, screensize, this.initLazyLoading.bind(this));\n  /* istanbul ignore else\t*/\n\n  if (slot && !this[slot.name]) {\n    this[slot.name] = slot;\n    slot.fire(\"slotReady\");\n  } else if (this[slot.name]) {\n    utils.log.error(\"slot %s is already defined!\", slot.name);\n  }\n\n  return slot;\n};\n\nSlots.prototype.initRefresh = function () {\n  if (config$1(\"flags\").refresh && config$1(\"refresh\")) {\n    const data = config$1(\"refresh\");\n    this.refreshCount = 0;\n    /* istanbul ignore else\t*/\n\n    if (data.time && !data.inview) {\n      const refresh = () => {\n        /* istanbul ignore else */\n        if (!data.max || this.refreshCount++ < data.max) {\n          this.refresh();\n        } else if (this.refreshCount >= data.max) {\n          clearInterval(refresh);\n        }\n      };\n\n      setInterval(refresh, (parseFloat(data.time) || 1) * 1000);\n    }\n  }\n\n  return this;\n};\n/*\n *\tlistens for the rendered event from a slot and fires the slotExpand event,\n * after extending the slot with information from the server.\n */\n\n\nSlots.prototype.initRendered = function () {\n  utils.on(\"slotRenderStart\", function (slots, event) {\n    const slot = slots[event.detail.name];\n    /* istanbul ignore else\t*/\n\n    if (slot) {\n      utils.extend(slot[slot.server], event.detail[slot.server]);\n      const size = event.detail.gpt.size;\n      const format = findFormatBySize(size);\n      slot.setFormatLoaded(format);\n      slot.maximise(size);\n      slot.fire(\"slotExpand\", event.detail);\n    }\n  }.bind(null, this));\n  return this;\n};\n/*\n * if responsive configuration exists listen for breakpoint changes\n */\n\n\nSlots.prototype.initResponsive = function () {\n  const breakpoints = config$1(\"responsive\");\n  /* istanbul ignore else\t*/\n\n  if (utils.isObject(breakpoints)) {\n    screensize = utils.responsive(breakpoints, onBreakpointChange.bind(null, this));\n  }\n\n  return this;\n};\n/*\n * called when a responsive breakpoint is crossed though window resizing or orientation change.\n */\n\n\nfunction onBreakpointChange(slots, screensize) {\n  slots.forEach(function (slot) {\n    /* istanbul ignore else\t*/\n    if (slot) {\n      // ADS-766 if format name is Responsive then we have requested a responsive creative and do not want to request new ads at different breakpoints\n\n      /* istanbul ignore else\t*/\n      const isCurrentlyResponsive = slot.container && slot.container.getAttribute(\"data-o-ads-loaded\") === \"Responsive\";\n      const stillWantsResponsive = slot.sizes[screensize] && slot.sizes[screensize].filter(size => findFormatBySize(size) === \"Responsive\").length > 0;\n\n      if (isCurrentlyResponsive && stillWantsResponsive) {\n        return false;\n      }\n\n      slot.screensize = screensize;\n      slot.fire(\"breakpoint\", {\n        screensize: screensize\n      });\n    }\n  });\n}\n/*\n * Initialise the postMessage API\n */\n\n\nSlots.prototype.initPostMessage = function () {\n  // Listen for messages coming from ads\n  window.addEventListener(\"message\", pmHandler.bind(null, this), false);\n\n  function pmHandler(slots, event) {\n    const data = utils.messenger.parse(event.data);\n    /* istanbul ignore else\tdon't process messages with a non oAds type*/\n\n    if (data.type && (/^oAds\\./.test(data.type) || /^touch/.test(data.type))) {\n      const type = data.type.replace(\"oAds.\", \"\"); // Make sure the message is coming from an identified ad slot\n\n      const slotName = utils.iframeToSlotName(event.source.window);\n      const slot = slots[slotName] || false;\n\n      if (!slot) {\n        utils.log.error(\"Message received from unidentified slot\");\n        return;\n      } // TODO: Remove adIframeLoaded once we can tag onto GPTs `slotRenderEnded` event\n\n\n      if (type === \"adIframeLoaded\") {\n        slot.fire(\"slotRenderEnded\");\n      } else if (type === \"slotClass\" && data.slotClass) {\n        slot.addClass(data.slotClass);\n      } // Received message to Collapse ad slot.\n      else if (type === \"collapse\") {\n        slot.fire(\"slotCollapsed\");\n        slot.collapse();\n      } // Received touch events from ad slot iframe\n\n      /* istanbul ignore else*/\n      else if (/^touch/.test(data.type)) {\n        slot.fire(\"touch\", data);\n      } else {\n        utils.log.error(\"Unknown message received from o-ads-embed\");\n      }\n    }\n  }\n}; // remove any observers tied to elements no longer in the DOM\n// e.g. app page has been swiped out from the gallery\n\n\nSlots.prototype.flushLazyLoading = function () {\n  this.lazyLoadingObservers = this.lazyLoadingObservers.filter(observer => {\n    return Boolean(!observer.root || document.contains(observer.root));\n  });\n};\n\nSlots.prototype.initLazyLoading = function (slotConfig) {\n  const lazyLoadingConfig = config$1(\"lazyLoad\") || slotConfig | {};\n  this.lazyLoadingObservers = this.lazyLoadingObservers || [];\n  this.flushLazyLoading(); // find any pre-existing observers\n\n  let lazyLoadingObserver = this.lazyLoadingObservers.find(observer => {\n    // deliberately double-equals to match null and undefined where the viewport is being observed\n    return lazyLoadingConfig.root == observer.root; // eslint-disable-line eqeqeq\n  });\n\n  function onChange(changes) {\n    //Execute the changes in the order they appear on the page. This is because the top slot often determines what the lower slots display.\n\n    /* istanbul ignore next */\n    changes.filter(a => a.intersectionRect.height || a.intersectionRect.width || a.intersectionRect.top || a.intersectionRect.left).sort((a, b) => a.intersectionRect.top - b.intersectionRect.top).forEach(change => {\n      const slotName = change.target.getAttribute(\"data-o-ads-name\");\n      /* istanbul ignore else */\n\n      if (slotName) {\n        invokeMethodOnSlots.call(this, slotName, \"render\");\n      }\n    });\n  } // If we don't already have an instance of the observer, and it is enabled globally or on a slot (force), then create one.\n\n  /* istanbul ignore else\t*/\n\n\n  if (\"IntersectionObserver\" in window && !lazyLoadingObserver && Boolean(lazyLoadingConfig)) {\n    const options = {};\n    /* istanbul ignore else\t*/\n\n    if (typeof lazyLoadingConfig === \"object\") {\n      /* istanbul ignore else\t*/\n      if (lazyLoadingConfig.viewportMargin) {\n        options.rootMargin = lazyLoadingConfig.viewportMargin;\n      }\n      /* istanbul ignore else\t*/\n\n\n      if (lazyLoadingConfig.threshold) {\n        options.threshold = lazyLoadingConfig.threshold;\n      }\n\n      options.root = lazyLoadingConfig.root || null;\n    }\n\n    lazyLoadingObserver = new IntersectionObserver(onChange.bind(this), options);\n    this.lazyLoadingObservers.push(lazyLoadingObserver);\n  }\n\n  return lazyLoadingObserver;\n};\n\nSlots.prototype.forEach = function (fn) {\n  Object.keys(this).forEach(name => {\n    const slot = this[name];\n    /* istanbul ignore else\t*/\n\n    if (slot instanceof Slot) {\n      fn.call(this, slot);\n    }\n  });\n  return this;\n};\n/*\n * Initialise slots\n */\n\n\nSlots.prototype.init = function () {\n  this.initRefresh();\n  this.initRendered();\n  this.initResponsive();\n  this.initPostMessage();\n  this.initLazyLoading();\n};\n\nSlots.prototype.debug = function () {\n  debug$1(Object.values(this));\n};\n\nvar slots = new Slots();\n\nlet parameters = {};\n\nfunction Targeting() {} //eslint-disable-line no-empty-function\n\n\nTargeting.prototype.get = function () {\n  const methods = {\n    socialReferrer: this.getSocialReferrer,\n    timestamp: this.timestamp,\n    responsive: this.responsive\n  };\n  utils.extend(parameters, this.socialFlow(), this.getVersion());\n\n  for (const item in methods) {\n    /* istanbul ignore else  */\n    if (methods.hasOwnProperty(item)) {\n      utils.extend(parameters, methods[item]());\n    }\n  }\n\n  return parameters;\n};\n\nTargeting.prototype.add = function (obj) {\n  /* istanbul ignore else  */\n  if (utils.isPlainObject(obj)) {\n    utils.extend(parameters, obj);\n  }\n};\n\nTargeting.prototype.remove = function (key) {\n  /* istanbul ignore else */\n  if (parameters[key]) {\n    delete parameters[key];\n  }\n};\n\nTargeting.prototype.clear = function () {\n  parameters = {};\n};\n\nTargeting.prototype.getVersion = function () {\n  if (config$1('passOAdsVersion')) {\n    return {\n      OADS_VERSION: utils.getVersion()\n    };\n  }\n};\n/**\n * If there is a query parameter called socialflow=xxx, we need to add it\n * as a tag\n */\n\n\nTargeting.prototype.socialFlow = function () {\n  const sf = utils.getQueryParamByName('socialflow');\n\n  if (sf) {\n    return {\n      socialflow: sf\n    };\n  }\n};\n\nTargeting.prototype.getSocialReferrer = function () {\n  let codedValue;\n  const referrer = utils.getReferrer(); // TODO: add on.ft.com\n\n  const lookup = {\n    't.co': 'twi',\n    'facebook.com': 'fac',\n    'linkedin.com': 'lin',\n    'drudgereport.com': 'dru',\n    'dianomi.com': 'dia',\n    google: 'goo'\n  };\n  Object.keys(lookup).forEach(url => {\n    const refererRegex = new RegExp(`^http(|s)://(www.)*(${url})`);\n    /* istanbul ignore else  */\n\n    if (refererRegex.test(referrer)) {\n      codedValue = lookup[url];\n    }\n  });\n  return codedValue && {\n    socref: codedValue\n  } || {};\n};\n\nTargeting.prototype.searchTerm = function () {\n  const qs = utils.hash(utils.getQueryString(), /&|;/, '=');\n  let keywords = qs.q || qs.s || qs.query || qs.queryText || qs.searchField || undefined;\n  /* istanbul ignore else\t*/\n\n  if (keywords && keywords !== '') {\n    keywords = unescape(keywords).toLowerCase().replace(/[';^+]/g, ' ').replace(/\\s+/g, ' ').trim();\n  }\n\n  return {\n    kw: keywords\n  };\n};\n\nTargeting.prototype.timestamp = function () {\n  return {\n    ts: utils.getTimestamp()\n  };\n};\n\nTargeting.prototype.responsive = function () {\n  return config$1('responsive') ? {\n    res: utils.responsive.getCurrent()\n  } : {};\n};\n\nTargeting.prototype.debug = function () {\n  const log = utils.log;\n  const parameters = this.get();\n  /* istanbul ignore else  */\n\n  if (Object.keys(parameters).length !== 0) {\n    log.start('Targeting');\n    log.attributeTable(this.get());\n    log.end();\n  }\n};\n\nvar targeting = new Targeting();\n\nconst SEARCH_PARAMS = ['q', 'kw'];\n/**\n * @typedef {{ [key: string]: string[] }} FilterDict\n */\n\n/**\n * Remove unwanted params from nested query strings\n *\n * @param   {string}   nestedParams the URIencoded nested params\n * @param   {string[]} keysToStrip  the parameters to remove\n *\n * @return  {string}               [return description]\n */\n\nfunction filterNestedParams(nestedParams, keysToStrip) {\n  if (!keysToStrip || keysToStrip.length < 1) {\n    return nestedParams;\n  }\n\n  const childParams = new URLSearchParams(nestedParams);\n\n  for (const key of keysToStrip) {\n    childParams.delete(key);\n  }\n\n  return childParams.toString();\n}\n/**\n * Purge a URL of sensitive data in query strings\n *\n * Given the URL\n * ```url\n * https://www.ft.com/search?q=goog&cust_params=a%3D1%26b%3D2%26c%3D3%26d%3D4\n * ```\n * Supplying an object in the form\n * ```\n * {\n *   root: ['q', 'kw'],\n *   cust_params: ['a', 'c']\n * }\n * ```\n * will remove `q` from the main query string and `a`, `c` from the nested params\n * under `cust_params`:\n * ```url\n * https://www.ft.com/search?cust_params=b=2%26d%3D4\n * ```\n *\n * @param   {Object}  params\n * @param   {string | Location}  params.href     The base URL or `window.location`\n * @param   {FilterDict}         params.filters  The dictionary of params to be removed\n *\n * @return  {string}              A URL that has been stripped of the supplied params\n */\n\nfunction stripUrlParams({\n  href,\n  filters\n}) {\n  // @ts-ignore: URL absolutely accepts Location!\n  const url = new URL(href);\n\n  for (const [param, filter] of Object.entries(filters)) {\n    if (param === 'root') {\n      // Strip parameters from the main query string\n      for (const key of filter) {\n        url.searchParams.delete(key);\n      }\n    } else {\n      // Handle nested parameters\n      const nestedParams = url.searchParams.get(param);\n\n      if (nestedParams) {\n        url.searchParams.set(param, filterNestedParams(nestedParams, filter));\n      }\n    }\n  }\n\n  return url.href;\n}\n\n/*globals googletag: true */\nconst DEFAULT_LAZY_LOAD = {\n  fetchMarginPercent: 500,\n  renderMarginPercent: 200,\n  mobileScaling: 2.0\n};\nconst DEFAULT_COLLAPSE_MODE = 'never';\nlet breakpoints = false;\n/*\n//###########################\n// Initialisation handlers ##\n//###########################\n*/\n\n/*\n * Initialise Google publisher tags functionality\n */\n\nfunction init() {\n  const gptConfig = config$1('gpt') || {};\n  breakpoints = config$1('responsive');\n  loadGPT();\n  utils.on('slotReady', onReady.bind(null, slotMethods));\n  utils.on('slotCanRender', onRender);\n  utils.on('refresh', onRefresh);\n  utils.on('resize', onResize);\n  googletag.cmd.push(setup.bind(null, gptConfig));\n}\n/*\n * initalise the googletag global namespace and add the google publish tags library to the page\n */\n\n\nfunction loadGPT() {\n  if (!window.googletag) {\n    // set up a place holder for the gpt code downloaded from google\n    window.googletag = {}; // this is a command queue used by GPT any methods added to it will be\n    // executed when GPT code is available, if GPT is already available they\n    // will be executed immediately\n\n    window.googletag.cmd = [];\n  }\n\n  utils.attach('//securepubads.g.doubleclick.net/tag/js/gpt.js', true, () => {\n    utils.broadcast('serverScriptLoaded');\n  }, err => {\n    utils.broadcast('adServerLoadError', err);\n  });\n}\n/*\n//#################################\n// Global configuration handlers ##\n//#################################\n*/\n\n/*\n * Configure the GPT library for the current page\n * this method is pushed onto the googletag command queue and run\n * when the library is available\n */\n\n\nfunction setup(gptConfig) {\n  const nonPersonalized = config$1('nonPersonalized') ? 1 : 0;\n  googletag.pubads().addEventListener('slotRenderEnded', onRenderEnded);\n  enableCompanions(gptConfig);\n  setRenderingMode(gptConfig);\n  setPageTargeting(targeting.get());\n  setPageCollapseEmpty();\n\n  if (gptConfig.hasOwnProperty('enableLazyLoad')) {\n    enableLazyLoad(gptConfig.enableLazyLoad);\n  }\n\n  const url = stripUrlParams({\n    href: window.location.href,\n    filters: {\n      root: SEARCH_PARAMS\n    }\n  });\n  googletag.enableServices();\n  googletag.pubads().setTargeting('url', url);\n  googletag.pubads().setRequestNonPersonalizedAds(nonPersonalized);\n  return true;\n}\n/**\n * Enables GPT's Lazy Loading for serving ads only when it's necessary.\n * \t\tThe lazy load config ooptions are:\n *\n * \t\t\t- fetchMarginPercent,\t\tminimum distance from the current viewport a slot\n * \t\t\t\t\tmust be before we fetch the ad as a percentage of viewport size.\n * \t\t\t\t\t0 means \"when the slot enters the viewport\",\n * \t\t\t\t\t100 means \"when the ad is 1 viewport away\"\n *\n * \t\t\t- renderMarginPercent,\tminimum distance from the current viewport a slot\n * \t\t\t\t\tmust be before we render an ad.\n * \t\t\t\t\tThis allows for prefetching the ad, but waiting to render and\n * \t\t\t\t\tdownload other subresources. The value works just like\n * \t\t\t\t\tfetchMarginPercent as a percentage of viewport.\n *\n * \t\t\t- mobileScaling,\t\t\t\ta multiplier applied to margins on mobile devices.\n * \t\t\t\t\tThis allows varying margins on mobile vs. desktop. For example,\n * \t\t\t\t\ta mobileScaling of 2.0 will multiply all margins by 2 on mobile\n * \t\t\t\t\tdevices, increasing the minimum distance a slot can be before\n * \t\t\t\t\tfetching and rendering.\n *\n * @param {object|boolean} lazyLoadConf The lazy load config object or a boolean.\n * @returns {boolean} true if the object is of type Array, otherwise false\n */\n\n\nfunction enableLazyLoad(lazyLoadConf) {\n  if (lazyLoadConf && (typeof lazyLoadConf === 'object' || typeof lazyLoadConf === 'boolean')) {\n    const opts = Object.assign({}, DEFAULT_LAZY_LOAD, typeof lazyLoadConf === 'object' ? lazyLoadConf : {});\n    window.googletag.pubads().enableLazyLoad(opts);\n  } else {\n    utils.log.warn('lazyLoadConf must be either an object or a boolean', lazyLoadConf);\n  }\n}\n/*\n * set the gpt rendering mode to either sync or async\n * default is async\n */\n\n\nfunction setRenderingMode(gptConfig) {\n  const rendering = gptConfig.rendering;\n\n  if (rendering === 'sync') {\n    googletag.pubads().enableSyncRendering();\n  } else if (rendering === 'sra') {\n    googletag.pubads().enableSingleRequest();\n  } else {\n    googletag.pubads().enableAsyncRendering();\n  }\n}\n/**\n * Adds page targeting to GPT ad calls\n * @name setPageTargeting\n * @memberof GPT\n * @lends GPT\n */\n\n\nfunction setPageTargeting(targetingData) {\n  if (utils.isPlainObject(targetingData)) {\n    googletag.cmd.push(() => {\n      const pubads = googletag.pubads();\n      Object.keys(targetingData).forEach(key => {\n        // Convert to string as boolean values are invalid arguments for GPT setTargeting()\n        pubads.setTargeting(key, String(targetingData[key]));\n      });\n    });\n  } else {\n    /* istanbul ignore next  */\n    utils.log.warn('invalid targeting object passed', targetingData);\n  }\n\n  return targetingData;\n}\n/**\n * Removes page targeting for a specified key from GPT ad calls\n */\n\n\nfunction clearPageTargetingForKey(key) {\n  if (!window.googletag) {\n    utils.log.warn('Attempting to clear page targeting before the GPT library has initialized');\n    return;\n  }\n\n  if (!key) {\n    utils.log.warn('Refusing to unset all keys - a key must be specified');\n    return;\n  }\n\n  googletag.cmd.push(() => {\n    googletag.pubads().clearTargeting(key);\n  });\n}\n/**\n * Sets behaviour of empty slots can be 'after', 'before' or 'never'\n * * 'after' collapse slots that return an empty ad\n * * 'before' collapses all slots and only displays them when an ad is found\n * * 'never' does not collapse any empty slot, the collapseEmptyDivs method is not called in that case\n */\n\n\nfunction setPageCollapseEmpty() {\n  const mode = config$1('collapseEmpty');\n\n  if (mode === 'before') {\n    googletag.pubads().collapseEmptyDivs(true);\n  }\n\n  if (mode === 'after') {\n    googletag.pubads().collapseEmptyDivs(false);\n  }\n}\n/**\n * When companions are enabled we delay the rendering of ad slots until\n * either a master is returned or all slots are returned without a master\n */\n\n\nfunction enableCompanions(gptConfig) {\n  if (gptConfig.companions) {\n    googletag.pubads().disableInitialLoad();\n    googletag.companionAds().setRefreshUnfilledSlots(true);\n  }\n}\n/*\n//##################\n// Event handlers ##\n//##################\n*/\n\n/*\n * Event handler for when a slot is ready for an ad to rendered\n */\n\n\nfunction onReady(slotMethods, event) {\n  const slot = event.detail.slot;\n  /* istanbul ignore else  */\n\n  if (slot.server === 'gpt') {\n    slot.gpt = {}; // extend the slot with gpt methods\n\n    utils.extend(slot, slotMethods); // setup the gpt configuration the ad\n\n    googletag.cmd.push(() => {\n      slot.defineSlot().addServices().setCollapseEmpty().setTargeting().setURL();\n\n      if (!slot.defer && slot.hasValidSize()) {\n        slot.display();\n      }\n    });\n  }\n}\n/*\n * Render is called when a slot is not rendered when the ready event fires\n */\n\n\nfunction onRender(event) {\n  const slot = event.detail.slot;\n  /* istanbul ignore else  */\n\n  if (utils.isFunction(slot.display)) {\n    slot.display();\n  }\n}\n/*\n * refresh is called when a slot requests the ad be flipped\n */\n\n\nfunction onRefresh(event) {\n  window.googletag.cmd.push(() => {\n    const targeting = event.detail.targeting;\n\n    if (utils.isPlainObject(targeting)) {\n      Object.keys(targeting).forEach(name => {\n        event.detail.slot.gpt.slot.setTargeting(name, targeting[name]);\n      });\n    }\n\n    googletag.pubads().refresh([event.detail.slot.gpt.slot]);\n  });\n  return this;\n}\n\nfunction onResize(event) {\n  const iframe = event.detail.slot.gpt.iframe;\n  const size = event.detail.size;\n  iframe.width = size[0];\n  iframe.height = size[1];\n}\n/*\n * function passed to the gpt library that is run when an ad completes rendering\n */\n\n\nfunction onRenderEnded(event) {\n  const data = {\n    gpt: {}\n  };\n  const gptSlotId = event.slot.getSlotId();\n  const domId = gptSlotId.getDomId().split('-');\n  const iframeId = `google_ads_iframe_${gptSlotId.getId()}`;\n  data.type = domId.pop();\n  data.name = domId.join('-');\n  data.size = event.size && event.size.length ? event.size.join() : '';\n  data.creativeId = event.creativeId;\n  const slotTargeting = event.slot.getTargetingMap && event.slot.getTargetingMap();\n\n  if (slotTargeting && slotTargeting.pos) {\n    data.pos = slotTargeting.pos.length ? slotTargeting.pos.join() : '';\n  }\n\n  const detail = data.gpt;\n  detail.isEmpty = event.isEmpty;\n  detail.size = event.size;\n  detail.creativeId = event.creativeId;\n  detail.lineItemId = event.lineItemId;\n  detail.serviceName = event.serviceName;\n  const iFrameEl = document.getElementById(iframeId);\n\n  if (iFrameEl) {\n    iFrameEl.setAttribute('tabindex', '-1');\n    iFrameEl.setAttribute('aria-hidden', 'true');\n    iFrameEl.setAttribute('role', 'presentation');\n    iFrameEl.setAttribute('title', 'Advertisement');\n    detail.iframe = iFrameEl;\n  } else {\n    /* istanbul ignore next */\n    utils.log.warn('No iFrame found matching GPT SlotID');\n  }\n\n  utils.broadcast('slotRenderStart', data);\n}\n/*\n//################\n// Slot methods ##\n//################\n* Set of methods extended on to the slot constructor for GPT served slots\n*/\n\n\nconst slotMethods = {\n  /**\n   * define a GPT slot\n   */\n  defineSlot: function () {\n    window.googletag.cmd.push(() => {\n      this.gpt.id = `${this.name}-gpt`;\n      this.inner.setAttribute('id', this.gpt.id);\n      this.setUnitName();\n\n      if (!this.outOfPage) {\n        if (breakpoints && utils.isObject(this.sizes)) {\n          this.initResponsive();\n          this.gpt.slot = googletag.defineSlot(this.gpt.unitName, [0, 0], this.gpt.id).defineSizeMapping(this.gpt.sizes);\n        } else {\n          this.gpt.slot = googletag.defineSlot(this.gpt.unitName, this.sizes, this.gpt.id);\n        }\n      } else {\n        this.gpt.slot = googletag.defineOutOfPageSlot(this.gpt.unitName, this.gpt.id);\n      }\n    });\n    return this;\n  },\n  clearSlot: function (gptSlot) {\n    if (window.googletag.pubadsReady && window.googletag.pubads) {\n      gptSlot = gptSlot || this.gpt.slot;\n      return googletag.pubads().clear([gptSlot]);\n    } else {\n      return false;\n    }\n  },\n  initResponsive: function () {\n    window.googletag.cmd.push(() => {\n      utils.on('breakpoint', event => {\n        const slot = event.detail.slot;\n        const screensize = event.detail.screensize;\n        updatePageTargeting({\n          res: screensize\n        });\n\n        if (slot.hasValidSize(screensize)) {\n          /* istanbul ignore else  */\n          if (slot.gpt.iframe) {\n            slot.fire('refresh');\n          } else if (!this.defer) {\n            slot.display();\n          }\n        }\n      }, this.container);\n      const mapping = googletag.sizeMapping();\n      Object.keys(breakpoints).forEach(breakpoint => {\n        if (this.sizes[breakpoint]) {\n          mapping.addSize(breakpoints[breakpoint], this.sizes[breakpoint]);\n        }\n      });\n      this.gpt.sizes = mapping.build();\n    });\n    return this;\n  },\n\n  /**\n   * Tell gpt to destroy the slot and its metadata\n   */\n  destroySlot: function (gptSlot) {\n    if (window.googletag.pubadsReady && window.googletag.pubads) {\n      gptSlot = gptSlot || this.gpt.slot;\n      return googletag.destroySlots([gptSlot]);\n    } else {\n      return false;\n    }\n  },\n\n  /*\n   *\tTell gpt to request an ad\n   */\n  display: function () {\n    window.googletag.cmd.push(() => {\n      this.fire('slotGoRender');\n      googletag.display(this.gpt.id);\n    });\n    return this;\n  },\n\n  /**\n   * Set the DFP unit name for the slot.\n   */\n  setUnitName: function () {\n    window.googletag.cmd.push(() => {\n      let unitName;\n      const gpt = config$1('gpt') || {};\n      const attr = this.container.getAttribute('data-o-ads-gpt-unit-name');\n\n      if (utils.isNonEmptyString(attr)) {\n        unitName = attr;\n      } else if (utils.isNonEmptyString(gpt.unitName)) {\n        unitName = gpt.unitName;\n      } else {\n        const network = gpt.network;\n        const site = gpt.site;\n        const zone = gpt.zone;\n        unitName = `/${network}`;\n        unitName += utils.isNonEmptyString(site) ? `/${site}` : '';\n        unitName += utils.isNonEmptyString(zone) ? `/${zone}` : '';\n      }\n\n      this.gpt.unitName = unitName;\n    });\n    return this;\n  },\n\n  /**\n   * Add the slot to the pub ads service and add a companion service if configured\n   */\n  addServices: function (gptSlot) {\n    window.googletag.cmd.push(() => {\n      const gpt = config$1('gpt') || {};\n      gptSlot = gptSlot || this.gpt.slot;\n      gptSlot.addService(googletag.pubads());\n\n      if (gpt.companions && this.companion !== false) {\n        gptSlot.addService(googletag.companionAds());\n      }\n    });\n    return this;\n  },\n\n  /**\n   * Sets the GPT collapse empty mode for a given slot\n   * values can be 'after', 'before', 'never'\n   */\n  setCollapseEmpty: function () {\n    window.googletag.cmd.push(() => {\n      const mode = this.collapseEmpty || config$1('collapseEmpty') || DEFAULT_COLLAPSE_MODE;\n\n      if (mode === 'before') {\n        this.gpt.slot.setCollapseEmptyDiv(true, true);\n      } else if (mode === 'after') {\n        this.gpt.slot.setCollapseEmptyDiv(true);\n      } else if (mode === 'never') {\n        this.gpt.slot.setCollapseEmptyDiv(false);\n      }\n    });\n    return this;\n  },\n  submitGptImpression: function () {\n    /* istanbul ignore next  */\n    function getImpressionURL(iframe) {\n      const trackingUrlElement = iframe.contentWindow.document.querySelector('[data-o-ads-impression-url]');\n\n      if (trackingUrlElement) {\n        return trackingUrlElement.dataset.oAdsImpressionUrl;\n      } else {\n        utils.log.warn('Impression URL not found, this is set via a creative template.');\n        return false;\n      }\n    }\n\n    if (this.outOfPage && this.gpt.iframe) {\n      const impressionURL = getImpressionURL(this.gpt.iframe);\n      /* istanbul ignore next  */\n\n      if (impressionURL) {\n        utils.attach(impressionURL, true, () => {\n          utils.log.info('Impression Url requested');\n        }, () => {\n          utils.log.info('CORS request to submit an impression failed');\n        }, true);\n      }\n    } else {\n      utils.log.warn('Attempting to call submitImpression on a non-oop slot');\n    }\n  },\n\n  /**\n   * Sets page url to be sent to google\n   * prevents later url changes via javascript from breaking the ads\n   */\n  setURL: function (gptSlot) {\n    window.googletag.cmd.push(() => {\n      gptSlot = gptSlot || this.gpt.slot;\n      const canonical = config$1('canonical');\n      gptSlot.set('page_url', canonical ? canonical : utils.getLocation());\n    });\n    return this;\n  },\n\n  /**\n   * Adds key values from a given object to the slot targeting\n   */\n  setTargeting: function (gptSlot) {\n    window.googletag.cmd.push(() => {\n      gptSlot = gptSlot || this.gpt.slot;\n      /* istanbul ignore else  */\n\n      if (utils.isPlainObject(this.targeting)) {\n        Object.keys(this.targeting).forEach(param => {\n          gptSlot.setTargeting(param, this.targeting[param]);\n        });\n      }\n    });\n    return this;\n  }\n};\n/*\n//####################\n// External methods ##\n//####################\n*/\n\n/**\n * The correlator is a random number added to ad calls.\n * It is used by the ad server to determine which impressions where served to the same page\n * Updating is used to tell the ad server to treat subsequent ad calls as being on a new page\n */\n\nfunction updateCorrelator() {\n  utils.log.warn('[DEPRECATED]: Updatecorrelator is being phased out by google and removed from o-ads in future releases.');\n  googletag.cmd.push(() => {\n    googletag.pubads().updateCorrelator();\n  });\n}\n\nfunction getCorrelator() {\n  if (window.googletag && window.googletag.pubads) {\n    return googletag.pubads().getCorrelator();\n  }\n}\n\nfunction clearPageTargeting() {\n  if (window.googletag) {\n    googletag.cmd.push(() => {\n      googletag.pubads().clearTargeting();\n    });\n  } else {\n    utils.log.warn('Attempting to clear page targeting before the GPT library has initialized');\n  }\n}\n\nfunction updatePageTargeting(override) {\n  if (window.googletag) {\n    const params = utils.isPlainObject(override) ? override : targeting.get();\n    setPageTargeting(params);\n  } else {\n    utils.log.warn('Attempting to set page targeting before the GPT library has initialized');\n  }\n} //https://developers.google.com/doubleclick-gpt/common_implementation_mistakes#scenario-2:-checking-the-googletag-object-to-know-whether-gpt-is-ready\n\n\nfunction hasGPTLoaded() {\n  if (window.googletag && window.googletag.apiReady) {\n    return true;\n  } else {\n    return false;\n  }\n}\n\nfunction debug() {\n  const log = utils.log;\n  const conf = config$1('gpt');\n\n  if (!conf) {\n    return;\n  }\n\n  log.start('gpt');\n  log.attributeTable(conf);\n  log.end();\n}\n\nvar gpt = {\n  init,\n  setup,\n  updateCorrelator,\n  getCorrelator,\n  updatePageTargeting,\n  clearPageTargeting,\n  clearPageTargetingForKey,\n  hasGPTLoaded,\n  loadGPT,\n  debug\n};\n\n/* eslint valid-jsdoc: 0 */\n\nfunction Ads() {\n  addDOMEventListener();\n\n  if (window && !window.oAds) {\n    window.oAds = this;\n  }\n}\n\nconfig$1.init = init$1;\nconfig$1.clear = clear; // bung all our modules on the protoype\n\nAds.prototype.config = config$1;\nAds.prototype.slots = slots;\nAds.prototype.gpt = gpt;\nAds.prototype.targeting = targeting;\nAds.prototype.utils = utils;\n/**\n* Initialises the ads library and all sub modules\n* @param options {object} a JSON object containing configuration for the current page\n*/\n\nAds.prototype.init = function (options) {\n  options = options || {};\n  this.config.init();\n  const configOptions = Object.assign(options, {\n    nonPersonalized: !options.disableConsentCookie\n  });\n  this.config(configOptions);\n\n  if (options.disableConsentCookie) {\n    this.consents = {\n      behavioral: true\n    };\n  } else {\n    this.consents = getConsents();\n  }\n\n  if (this.consents.behavioral) {\n    this.utils.broadcast('consentBehavioral');\n  }\n\n  if (this.consents.programmatic) {\n    this.utils.broadcast('consentProgrammatic');\n  }\n\n  this.utils.broadcast('initialising');\n  this.targeting.add(this.config().targeting);\n  return Promise.resolve(this.initLibrary());\n};\n/**\n * Update page level targeting data in o-ads and GPT\n */\n\n\nAds.prototype.updateTargeting = function (data) {\n  this.targeting.add(data);\n  this.gpt.updatePageTargeting(this.targeting.get());\n};\n\nAds.prototype.initLibrary = function () {\n  this.slots.init();\n\n  if (this.consents.programmatic) {\n    this.config({\n      'nonPersonalized': false\n    });\n    this.targeting.add({\n      \"cc\": \"y\"\n    });\n  }\n\n  this.gpt.init();\n  this.utils.on('debug', this.debug.bind(this));\n  this.isInitialised = true;\n  this.utils.broadcast('initialised', this);\n  removeDOMEventListener();\n  return this;\n};\n\nAds.prototype.debug = function () {\n  let remove = true;\n\n  if (localStorage.getItem('oAds')) {\n    remove = false;\n  } else {\n    localStorage.setItem('oAds', true);\n  }\n\n  this.gpt.debug();\n  this.slots.debug();\n  this.targeting.debug();\n\n  if (remove) {\n    localStorage.removeItem('oAds');\n  }\n};\n\nAds.prototype.version = function () {\n  this.utils.log.warn('DEPRECATION NOTICE: Ads.version() will be deprecated in favour of Ads.getVersion()');\n  this.utils.log(`o-ads version: ${this.utils.getVersion()}`);\n};\n\nAds.prototype.getVersion = function () {\n  return this.utils.getVersion();\n};\n\nconst initAll = function () {\n  return ads.init().then(() => {\n    const slots = Array.from(document.querySelectorAll('.o-ads, [data-o-ads-name]'));\n    slots.forEach(ads.slots.initSlot.bind(ads.slots));\n  });\n};\n\nAds.prototype.initAll = initAll;\n\nfunction getConsents() {\n  // derive consent options from ft consent cookie\n  const re = /FTConsent=([^;]+)/;\n  const match = document.cookie.match(re);\n\n  if (!match) {\n    // cookie stasis or no consent cookie found\n    return {\n      behavioral: false,\n      programmatic: false\n    };\n  }\n\n  const consentCookie = decodeURIComponent(match[1]);\n  return {\n    behavioral: consentCookie.indexOf('behaviouraladsOnsite:on') !== -1,\n    programmatic: consentCookie.indexOf('programmaticadsOnsite:on') !== -1\n  };\n}\n\nfunction addDOMEventListener() {\n  document.addEventListener('o.DOMContentLoaded', initAll);\n}\n\nfunction removeDOMEventListener() {\n  document.removeEventListener('o.DOMContentLoaded', initAll);\n}\n\nconst ads = new Ads();\n\nexport { ads as default };\n"],"sourceRoot":""}