@adhese/sdk 1.12.1 → 1.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @adhese/sdk
2
2
 
3
+ ## 1.12.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 67afd86: Fix a slot writing its creative more than once, which stacked duplicate banners for slots using `renderMode: "inline"`.
8
+
9
+ Several things can ask a slot to render at roughly the same moment, and `render()` wrote the creative again every time it was called. `renderIframe` replaces the element's contents, so this stayed invisible there, but `renderInline` appends: each extra render added another copy of the creative to the slot, re-ran the creative's own scripts and fired the `onRender` hook again.
10
+
11
+ These repeated renders were being masked until now. Two requests racing for the same slot used to leave one of them waiting on a response it never received, which silently stalled the render that would have followed it. Sharing the in-flight request (1.12.1) let both sides continue, so the second render started happening for real.
12
+
13
+ A slot now skips writing its creative when that exact ad is already rendered into that exact element. A newly requested ad, an ad passed explicitly to `render()`, or a new element to render into — after an SPA re-mount, for example — all still render as before.
14
+
3
15
  ## 1.12.1
4
16
 
5
17
  ### Patch Changes
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const name = "@adhese/sdk";
4
- const version = "1.12.1";
4
+ const version = "1.12.2";
5
5
  exports.name = name;
6
6
  exports.version = version;
7
7
  //# sourceMappingURL=package.json.cjs.map
@@ -221,6 +221,8 @@ function createSlot(slotOptions) {
221
221
  additionalTrackingPixelElement.value.remove();
222
222
  });
223
223
  let inFlightRequest = null;
224
+ let renderedAd = null;
225
+ let renderedElement = null;
224
226
  async function request() {
225
227
  if ((inFlightRequest == null ? void 0 : inFlightRequest.name) === name.value)
226
228
  return inFlightRequest.promise;
@@ -290,6 +292,7 @@ function createSlot(slotOptions) {
290
292
  }
291
293
  }
292
294
  const hadAdBeforeBeforeRenderHook = Boolean(renderAd);
295
+ const sourceAd = renderAd;
293
296
  renderAd = renderAd && await runOnBeforeRender(renderAd);
294
297
  renderMode = (renderAd == null ? void 0 : renderAd.renderMode) ?? renderMode;
295
298
  if (!element.value && renderMode !== "none") {
@@ -312,6 +315,10 @@ function createSlot(slotOptions) {
312
315
  status.value = "rendered";
313
316
  return element.value;
314
317
  }
318
+ if (sourceAd && sdkShared.toRaw(sourceAd) === renderedAd && element.value === renderedElement) {
319
+ status.value = "rendered";
320
+ return element.value;
321
+ }
315
322
  if (typeof (renderAd == null ? void 0 : renderAd.tag) !== "string" && renderMode !== "none") {
316
323
  const error = `Could not render slot for slot ${name.value}. A valid tag doesn't exist or is not HTML string.`;
317
324
  throw new Error(error);
@@ -325,6 +332,8 @@ function createSlot(slotOptions) {
325
332
  element.value
326
333
  );
327
334
  }
335
+ renderedAd = sourceAd && sdkShared.toRaw(sourceAd);
336
+ renderedElement = element.value;
328
337
  logger.logger.debug(`Slot rendered ${name.value}`, {
329
338
  renderedElement: element,
330
339
  location: context.location,
@@ -368,6 +377,8 @@ function createSlot(slotOptions) {
368
377
  return;
369
378
  element.value.innerHTML = "";
370
379
  element.value.style.position = "";
380
+ renderedAd = null;
381
+ renderedElement = null;
371
382
  }
372
383
  function dispose() {
373
384
  cleanElement();
@@ -1 +1 @@
1
- {"version":3,"file":"slot.cjs","sources":["../../../src/slot/slot.ts"],"sourcesContent":["import type { AdheseAd } from '@adhese/sdk';\nimport type {\n AdheseSlot,\n AdheseSlotContext,\n AdheseSlotOptions,\n RenderMode,\n} from './slot.types';\nimport {\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n omit,\n pick,\n reactive,\n type Ref,\n ref,\n renderIframe,\n renderInline,\n type RenderOptions,\n shallowRef,\n uniqueId,\n type UnwrapRef,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<\n RenderMode,\n (ad: RenderOptions, element: HTMLElement) => void\n> = {\n iframe: renderIframe,\n inline: renderInline,\n none: doNothing,\n};\n\nconst defaultOptions = {\n renderMode: 'iframe',\n type: 'normal',\n} satisfies Partial<AdheseSlotOptions>;\n\n/**\n * Create a new slot instance. This slot instance can be used to request and render ads.\n *\n * @param slotOptions {AdheseSlotOptions} The options to create the slot with.\n *\n * @return AdheseSlot The created slot instance.\n */\nexport function createSlot(slotOptions: AdheseSlotOptions): AdheseSlot {\n const scope = effectScope();\n\n return scope.run(() => {\n const slotContext = ref<AdheseSlotContext | null>(null);\n const options = slotOptions.context.hooks.runOnSlotCreate({\n ...defaultOptions,\n ...(Object.fromEntries(\n Object.entries(slotOptions).filter(([, value]) => value !== undefined),\n ) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n type = 'normal',\n } = options;\n\n let { renderMode = 'iframe' } = options;\n\n const id = uniqueId();\n const {\n runOnBeforeRender,\n runOnRender,\n runOnBeforeRequest,\n runOnRequest,\n runOnInit,\n runOnDispose,\n runOnEmpty,\n runOnError,\n runOnImpressionTracked,\n runOnViewableTracked,\n ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(\n new Map(Object.entries(options.parameters ?? {})),\n );\n\n const [device, disposeQueryDetector] = useQueryDetector(\n context,\n typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(\n options.format.map(item => [item.format, item.query]),\n ),\n );\n\n const format = computed(() =>\n typeof options.format === 'string' ? options.format : device.value,\n );\n\n const data = ref<AdheseAd | null>(null) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const isEmpty = ref(false);\n // Ad stashed by `processOnEmpty(ad)` when `onRequest` identifies an ad's creative as empty. `request()`\n // rescues it into `data`/`originalData` so tracking pixels are still available once the slot renders.\n let emptyAdForTracking: AdheseAd | null = null;\n const name = computed(() =>\n generateName(options.context.location, format.value, options.slot),\n );\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch(name, async (newName, oldName) => {\n if (newName === oldName)\n return;\n\n const newAd = await slotContext.value?.request();\n\n if (!newAd)\n return;\n\n slotContext.value?.cleanElement();\n\n data.value = newAd;\n originalData.value = newAd;\n });\n\n const isDomLoaded = useDomLoaded(context);\n\n const element = shallowRef<HTMLElement | null>(null);\n\n function getElement(): HTMLElement | null {\n if (\n !(\n typeof options.containingElement === 'string'\n || !options.containingElement\n )\n ) {\n return options.containingElement;\n }\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(\n `#${options.containingElement}`,\n );\n }\n\n watch(element, async (newElement, oldElement) => {\n if (\n status.value === 'empty'\n || status.value === 'error'\n || status.value === 'loading'\n ) {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (\n newElement === oldElement\n || (oldElement === null && newElement === null)\n ) {\n return;\n }\n if (!context.options.eagerRendering && !oldElement) {\n return;\n }\n if (status.value === 'rendering' || status.value === 'rendered') {\n return;\n }\n await render();\n });\n\n const domObserver = new MutationObserver(() => {\n element.value = getElement();\n });\n\n domObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n watch(\n isDomLoaded,\n () => {\n element.value = getElement();\n },\n { immediate: true, deep: true },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n watch(\n isInViewport,\n async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered' && status.value !== 'rendering')\n await slotContext.value?.render();\n },\n { immediate: true },\n );\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n let viewabilityPixel;\n if (slotContext.value?.data?.origin === undefined) {\n context.logger.warn(\n `Origin not found for ${slotContext.value?.name}`,\n );\n return;\n }\n switch (slotContext.value?.data?.origin) {\n case 'DALE': {\n // @ts-expect-error - Data structure is not typed and very messy to type\n const seatbid = slotContext.value?.data?.originData?.seatbid;\n const bid = seatbid ? seatbid[0]?.bid[0] : undefined;\n viewabilityPixel = bid\n ? bid.ext?.adhese?.viewableImpressionCounter\n : undefined;\n break;\n }\n case 'JERLICIA':\n viewabilityPixel\n = slotContext.value?.data?.viewableImpressionCounter;\n break;\n }\n if (viewabilityPixel) {\n trackingPixel.value = addTrackingPixel(viewabilityPixel);\n context.logger.debug(\n `Viewability tracking pixel fired for ${slotContext.value?.name}`,\n );\n runOnViewableTracked(slotContext.value?.data);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const additionalTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n const isAdditionalTracked = ref(false);\n\n const impressionTrackedAd = ref<AdheseAd | null>(null);\n const additionalTrackedAd = ref<AdheseAd | null>(null);\n\n watch(\n [status, isInViewport, data],\n ([newStatus, newIsInViewport, newData]) => {\n if (newStatus !== 'rendered' || !newIsInViewport)\n return;\n\n if (\n newData?.impressionCounter\n && impressionTrackedAd.value !== newData\n ) {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = addTrackingPixel(\n newData.impressionCounter,\n );\n impressionTrackedAd.value = newData;\n runOnImpressionTracked(newData);\n isImpressionTracked.value = true;\n context.logger.debug(\n `Impression tracking pixel fired for ${slotContext.value?.name}`,\n );\n }\n if (\n newData?.additionalTracker\n && additionalTrackedAd.value !== newData\n ) {\n additionalTrackingPixelElement.value?.remove();\n additionalTrackingPixelElement.value = addTrackingPixel(\n newData.additionalTracker,\n );\n additionalTrackedAd.value = newData;\n isAdditionalTracked.value = true;\n context.logger.debug(\n `Additional Impression tracking pixel fired for ${slotContext.value?.name}`,\n );\n }\n },\n { immediate: true },\n );\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n if (additionalTrackingPixelElement.value)\n additionalTrackingPixelElement.value.remove();\n });\n\n // The request currently in flight, if any. Several things can ask a slot for its ad at roughly the\n // same moment - the viewport and element watchers, `onInit`, or an app calling `render()` while the\n // initial request is still running - and `render()` starts a request of its own whenever it finds no\n // ad yet. Without this they each fire their own call to the ad server for the same slot. Keyed by\n // name so that a format (and therefore name) change still results in a genuinely new request.\n let inFlightRequest: { name: string; promise: Promise<AdheseAd | null> } | null = null;\n\n async function request(): Promise<AdheseAd | null> {\n if (inFlightRequest?.name === name.value)\n return inFlightRequest.promise;\n\n const promise = fetchAd();\n inFlightRequest = { name: name.value, promise };\n\n try {\n return await promise;\n }\n finally {\n if (inFlightRequest?.promise === promise)\n inFlightRequest = null;\n }\n }\n\n async function fetchAd(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\n isEmpty.value = false;\n emptyAdForTracking = null;\n\n let response = await runOnBeforeRequest(null);\n\n if (!response) {\n response = await extRequestAd({\n slot: {\n name: name.value,\n parameters,\n },\n context,\n });\n }\n\n if (response)\n response = await runOnRequest(response);\n\n if (!response && emptyAdForTracking) {\n // `onRequest` identified the ad as empty via `processOnEmpty(ad)`. Keep the original ad around so\n // it still reaches `render()`, where the position is tracked even though no creative is shown.\n response = emptyAdForTracking;\n }\n\n data.value = response;\n\n if (!originalData.value)\n originalData.value = response;\n\n status.value = response ? 'loaded' : 'empty';\n\n if (!response)\n cleanElement();\n\n if (response && context.options.eagerRendering && element.value)\n await render(response);\n\n return response;\n }\n catch (error) {\n processOnError(error as string);\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n if (\n status.value === 'empty'\n || status.value === 'error'\n || status.value === 'initializing'\n ) {\n return null;\n }\n\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'rendering';\n await waitForDomLoad();\n element.value = getElement();\n\n if (adToRender) {\n // An explicit ad was passed in, overriding whatever the slot previously fetched. Don't carry over an\n // `isEmpty` flag from an earlier, unrelated ad.\n isEmpty.value = false;\n }\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? null;\n if (!renderAd) {\n renderAd = await request();\n if ((status.value as UnwrapRef<AdheseSlot>['status']) === 'rendered') {\n return element.value;\n }\n }\n\n const hadAdBeforeBeforeRenderHook = Boolean(renderAd);\n\n renderAd = renderAd && (await runOnBeforeRender(renderAd));\n\n renderMode = renderAd?.renderMode ?? renderMode;\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(\n `Could not render slot for format ${format.value}. No element found.`,\n slotContext.value,\n );\n\n return null;\n }\n\n if (!renderAd) {\n if (hadAdBeforeBeforeRenderHook) {\n // The ad was identified as empty by the `onBeforeRender` hook itself. The position is still\n // tracked as rendered, but no creative is written to the element. Whatever the app already put\n // in the element (e.g. a fallback rendered from `onEmpty`) is left untouched.\n markEmpty();\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n logger.debug(`Slot ${name.value} identified as empty by the onBeforeRender hook`, slotContext.value);\n\n return element.value;\n }\n\n return null;\n }\n\n if (isEmpty.value) {\n // The ad was already identified as empty earlier, typically via `processOnEmpty(ad)` from the\n // `onRequest` hook. The position is tracked as rendered, but no creative is written to the element.\n // Whatever the app already put in the element (e.g. a fallback rendered from `onEmpty`) is left\n // untouched.\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n\n return element.value;\n }\n\n if (typeof renderAd?.tag !== 'string' && renderMode !== 'none') {\n const error = `Could not render slot for slot ${name.value}. A valid tag doesn't exist or is not HTML string.`;\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode](\n {\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions,\n element.value,\n );\n }\n\n logger.debug(`Slot rendered ${name.value}`, {\n renderedElement: element,\n location: context.location,\n format,\n containingElement,\n });\n\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n catch (error) {\n processOnError(error as string);\n return null;\n }\n }\n\n function markEmpty(): void {\n if (isEmpty.value)\n return;\n\n isEmpty.value = true;\n runOnEmpty();\n }\n\n function processOnEmpty(ad?: AdheseAd): void {\n markEmpty();\n\n if (ad) {\n // An ad was returned, but its creative was identified as empty (e.g. a no-fill/house banner). Stash\n // it so `request()` can keep it alive for tracking once the slot renders, instead of treating this\n // as \"no ad returned at all\".\n emptyAdForTracking = ad;\n return;\n }\n\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n }\n\n function processOnError(error: string): void {\n if (status.value !== 'error') {\n status.value = 'error';\n logger.error(error);\n runOnError(new Error(error, {\n cause: error,\n }));\n }\n }\n\n function cleanElement(): void {\n if (!element.value || renderMode === 'none')\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n }\n\n function dispose(): void {\n cleanElement();\n\n element.value = null;\n\n data.value = null;\n originalData.value = null;\n\n domObserver.disconnect();\n\n runOnDispose();\n\n isDisposed.value = true;\n\n scope.stop();\n }\n\n const state = reactive({\n location: context.location ?? '',\n lazyLoading: options.lazyLoading ?? false,\n type,\n slot,\n parameters,\n format,\n name,\n data,\n isViewabilityTracked,\n isImpressionTracked,\n isEmpty,\n status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n processOnEmpty,\n processOnError,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(\n state,\n (newState) => {\n slotContext.value = newState;\n },\n {\n deep: true,\n immediate: true,\n },\n );\n\n context.hooks.onInit(async () => {\n await runOnInit();\n\n if (status.value === 'empty' || status.value === 'error') {\n return;\n }\n\n if (initialData) {\n status.value = 'loaded';\n isEmpty.value = false;\n emptyAdForTracking = null;\n\n data.value = initialData;\n\n let response = await runOnRequest(initialData);\n\n if (!response && emptyAdForTracking) {\n // `onRequest` identified the ad as empty via `processOnEmpty(ad)`. Keep the original ad around so\n // it still reaches `render()`, where the position is tracked even though no creative is shown.\n response = emptyAdForTracking;\n }\n\n data.value = response;\n // eslint-disable-next-line require-atomic-updates\n status.value = response ? 'loaded' : 'empty';\n\n return;\n }\n\n status.value = 'initialized';\n\n if (options.lazyLoading) {\n return;\n }\n\n data.value = (await slotContext.value?.request()) ?? null;\n });\n\n return state;\n })!;\n}\n"],"names":["renderIframe","renderInline","doNothing","effectScope","ref","uniqueId","useSlotHooks","reactive","useQueryDetector","computed","generateName","watch","useDomLoaded","shallowRef","useRenderIntersectionObserver","useViewabilityObserver","addTrackingPixel","extRequestAd","waitForDomLoad","logger","pick","omit"],"mappings":"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"}
1
+ {"version":3,"file":"slot.cjs","sources":["../../../src/slot/slot.ts"],"sourcesContent":["import type { AdheseAd } from '@adhese/sdk';\nimport type {\n AdheseSlot,\n AdheseSlotContext,\n AdheseSlotOptions,\n RenderMode,\n} from './slot.types';\nimport {\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n omit,\n pick,\n reactive,\n type Ref,\n ref,\n renderIframe,\n renderInline,\n type RenderOptions,\n shallowRef,\n toRaw,\n uniqueId,\n type UnwrapRef,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<\n RenderMode,\n (ad: RenderOptions, element: HTMLElement) => void\n> = {\n iframe: renderIframe,\n inline: renderInline,\n none: doNothing,\n};\n\nconst defaultOptions = {\n renderMode: 'iframe',\n type: 'normal',\n} satisfies Partial<AdheseSlotOptions>;\n\n/**\n * Create a new slot instance. This slot instance can be used to request and render ads.\n *\n * @param slotOptions {AdheseSlotOptions} The options to create the slot with.\n *\n * @return AdheseSlot The created slot instance.\n */\nexport function createSlot(slotOptions: AdheseSlotOptions): AdheseSlot {\n const scope = effectScope();\n\n return scope.run(() => {\n const slotContext = ref<AdheseSlotContext | null>(null);\n const options = slotOptions.context.hooks.runOnSlotCreate({\n ...defaultOptions,\n ...(Object.fromEntries(\n Object.entries(slotOptions).filter(([, value]) => value !== undefined),\n ) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n type = 'normal',\n } = options;\n\n let { renderMode = 'iframe' } = options;\n\n const id = uniqueId();\n const {\n runOnBeforeRender,\n runOnRender,\n runOnBeforeRequest,\n runOnRequest,\n runOnInit,\n runOnDispose,\n runOnEmpty,\n runOnError,\n runOnImpressionTracked,\n runOnViewableTracked,\n ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(\n new Map(Object.entries(options.parameters ?? {})),\n );\n\n const [device, disposeQueryDetector] = useQueryDetector(\n context,\n typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(\n options.format.map(item => [item.format, item.query]),\n ),\n );\n\n const format = computed(() =>\n typeof options.format === 'string' ? options.format : device.value,\n );\n\n const data = ref<AdheseAd | null>(null) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const isEmpty = ref(false);\n // Ad stashed by `processOnEmpty(ad)` when `onRequest` identifies an ad's creative as empty. `request()`\n // rescues it into `data`/`originalData` so tracking pixels are still available once the slot renders.\n let emptyAdForTracking: AdheseAd | null = null;\n const name = computed(() =>\n generateName(options.context.location, format.value, options.slot),\n );\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch(name, async (newName, oldName) => {\n if (newName === oldName)\n return;\n\n const newAd = await slotContext.value?.request();\n\n if (!newAd)\n return;\n\n slotContext.value?.cleanElement();\n\n data.value = newAd;\n originalData.value = newAd;\n });\n\n const isDomLoaded = useDomLoaded(context);\n\n const element = shallowRef<HTMLElement | null>(null);\n\n function getElement(): HTMLElement | null {\n if (\n !(\n typeof options.containingElement === 'string'\n || !options.containingElement\n )\n ) {\n return options.containingElement;\n }\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(\n `#${options.containingElement}`,\n );\n }\n\n watch(element, async (newElement, oldElement) => {\n if (\n status.value === 'empty'\n || status.value === 'error'\n || status.value === 'loading'\n ) {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (\n newElement === oldElement\n || (oldElement === null && newElement === null)\n ) {\n return;\n }\n if (!context.options.eagerRendering && !oldElement) {\n return;\n }\n if (status.value === 'rendering' || status.value === 'rendered') {\n return;\n }\n await render();\n });\n\n const domObserver = new MutationObserver(() => {\n element.value = getElement();\n });\n\n domObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n watch(\n isDomLoaded,\n () => {\n element.value = getElement();\n },\n { immediate: true, deep: true },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n watch(\n isInViewport,\n async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered' && status.value !== 'rendering')\n await slotContext.value?.render();\n },\n { immediate: true },\n );\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n let viewabilityPixel;\n if (slotContext.value?.data?.origin === undefined) {\n context.logger.warn(\n `Origin not found for ${slotContext.value?.name}`,\n );\n return;\n }\n switch (slotContext.value?.data?.origin) {\n case 'DALE': {\n // @ts-expect-error - Data structure is not typed and very messy to type\n const seatbid = slotContext.value?.data?.originData?.seatbid;\n const bid = seatbid ? seatbid[0]?.bid[0] : undefined;\n viewabilityPixel = bid\n ? bid.ext?.adhese?.viewableImpressionCounter\n : undefined;\n break;\n }\n case 'JERLICIA':\n viewabilityPixel\n = slotContext.value?.data?.viewableImpressionCounter;\n break;\n }\n if (viewabilityPixel) {\n trackingPixel.value = addTrackingPixel(viewabilityPixel);\n context.logger.debug(\n `Viewability tracking pixel fired for ${slotContext.value?.name}`,\n );\n runOnViewableTracked(slotContext.value?.data);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const additionalTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n const isAdditionalTracked = ref(false);\n\n const impressionTrackedAd = ref<AdheseAd | null>(null);\n const additionalTrackedAd = ref<AdheseAd | null>(null);\n\n watch(\n [status, isInViewport, data],\n ([newStatus, newIsInViewport, newData]) => {\n if (newStatus !== 'rendered' || !newIsInViewport)\n return;\n\n if (\n newData?.impressionCounter\n && impressionTrackedAd.value !== newData\n ) {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = addTrackingPixel(\n newData.impressionCounter,\n );\n impressionTrackedAd.value = newData;\n runOnImpressionTracked(newData);\n isImpressionTracked.value = true;\n context.logger.debug(\n `Impression tracking pixel fired for ${slotContext.value?.name}`,\n );\n }\n if (\n newData?.additionalTracker\n && additionalTrackedAd.value !== newData\n ) {\n additionalTrackingPixelElement.value?.remove();\n additionalTrackingPixelElement.value = addTrackingPixel(\n newData.additionalTracker,\n );\n additionalTrackedAd.value = newData;\n isAdditionalTracked.value = true;\n context.logger.debug(\n `Additional Impression tracking pixel fired for ${slotContext.value?.name}`,\n );\n }\n },\n { immediate: true },\n );\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n if (additionalTrackingPixelElement.value)\n additionalTrackingPixelElement.value.remove();\n });\n\n // The request currently in flight, if any. Several things can ask a slot for its ad at roughly the\n // same moment - the viewport and element watchers, `onInit`, or an app calling `render()` while the\n // initial request is still running - and `render()` starts a request of its own whenever it finds no\n // ad yet. Without this they each fire their own call to the ad server for the same slot. Keyed by\n // name so that a format (and therefore name) change still results in a genuinely new request.\n let inFlightRequest: { name: string; promise: Promise<AdheseAd | null> } | null = null;\n\n // What was last written to the DOM, so that a repeat render for an unchanged ad can be skipped.\n // Cleared whenever the element's contents are dropped, so the creative is written again after that.\n let renderedAd: AdheseAd | null = null;\n let renderedElement: HTMLElement | null = null;\n\n async function request(): Promise<AdheseAd | null> {\n if (inFlightRequest?.name === name.value)\n return inFlightRequest.promise;\n\n const promise = fetchAd();\n inFlightRequest = { name: name.value, promise };\n\n try {\n return await promise;\n }\n finally {\n if (inFlightRequest?.promise === promise)\n inFlightRequest = null;\n }\n }\n\n async function fetchAd(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\n isEmpty.value = false;\n emptyAdForTracking = null;\n\n let response = await runOnBeforeRequest(null);\n\n if (!response) {\n response = await extRequestAd({\n slot: {\n name: name.value,\n parameters,\n },\n context,\n });\n }\n\n if (response)\n response = await runOnRequest(response);\n\n if (!response && emptyAdForTracking) {\n // `onRequest` identified the ad as empty via `processOnEmpty(ad)`. Keep the original ad around so\n // it still reaches `render()`, where the position is tracked even though no creative is shown.\n response = emptyAdForTracking;\n }\n\n data.value = response;\n\n if (!originalData.value)\n originalData.value = response;\n\n status.value = response ? 'loaded' : 'empty';\n\n if (!response)\n cleanElement();\n\n if (response && context.options.eagerRendering && element.value)\n await render(response);\n\n return response;\n }\n catch (error) {\n processOnError(error as string);\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n if (\n status.value === 'empty'\n || status.value === 'error'\n || status.value === 'initializing'\n ) {\n return null;\n }\n\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'rendering';\n await waitForDomLoad();\n element.value = getElement();\n\n if (adToRender) {\n // An explicit ad was passed in, overriding whatever the slot previously fetched. Don't carry over an\n // `isEmpty` flag from an earlier, unrelated ad.\n isEmpty.value = false;\n }\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? null;\n if (!renderAd) {\n renderAd = await request();\n if ((status.value as UnwrapRef<AdheseSlot>['status']) === 'rendered') {\n return element.value;\n }\n }\n\n const hadAdBeforeBeforeRenderHook = Boolean(renderAd);\n // Kept before `onBeforeRender` runs, since that hook is free to return a freshly built ad object\n // every time it's called, which would make the \"already rendered\" check above never match.\n const sourceAd = renderAd;\n\n renderAd = renderAd && (await runOnBeforeRender(renderAd));\n\n renderMode = renderAd?.renderMode ?? renderMode;\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(\n `Could not render slot for format ${format.value}. No element found.`,\n slotContext.value,\n );\n\n return null;\n }\n\n if (!renderAd) {\n if (hadAdBeforeBeforeRenderHook) {\n // The ad was identified as empty by the `onBeforeRender` hook itself. The position is still\n // tracked as rendered, but no creative is written to the element. Whatever the app already put\n // in the element (e.g. a fallback rendered from `onEmpty`) is left untouched.\n markEmpty();\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n logger.debug(`Slot ${name.value} identified as empty by the onBeforeRender hook`, slotContext.value);\n\n return element.value;\n }\n\n return null;\n }\n\n if (isEmpty.value) {\n // The ad was already identified as empty earlier, typically via `processOnEmpty(ad)` from the\n // `onRequest` hook. The position is tracked as rendered, but no creative is written to the element.\n // Whatever the app already put in the element (e.g. a fallback rendered from `onEmpty`) is left\n // untouched.\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n\n return element.value;\n }\n\n if (sourceAd && toRaw(sourceAd) === renderedAd && element.value === renderedElement) {\n // This exact ad is already written into this exact element. Several things can ask a slot to\n // render at roughly the same moment, and writing the creative again is not harmless:\n // `renderInline` appends, so the creative stacks up, and the creative's own scripts and the\n // `onRender` hook run again. A new ad, or a new element, still re-renders below.\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n\n return element.value;\n }\n\n if (typeof renderAd?.tag !== 'string' && renderMode !== 'none') {\n const error = `Could not render slot for slot ${name.value}. A valid tag doesn't exist or is not HTML string.`;\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode](\n {\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions,\n element.value,\n );\n }\n\n // Stored raw: the same ad reaches `render()` either as the plain object `request()` resolved with\n // or as the reactive proxy `data` wrapped it in, and those are not identical by reference.\n renderedAd = sourceAd && toRaw(sourceAd);\n renderedElement = element.value;\n\n logger.debug(`Slot rendered ${name.value}`, {\n renderedElement: element,\n location: context.location,\n format,\n containingElement,\n });\n\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n catch (error) {\n processOnError(error as string);\n return null;\n }\n }\n\n function markEmpty(): void {\n if (isEmpty.value)\n return;\n\n isEmpty.value = true;\n runOnEmpty();\n }\n\n function processOnEmpty(ad?: AdheseAd): void {\n markEmpty();\n\n if (ad) {\n // An ad was returned, but its creative was identified as empty (e.g. a no-fill/house banner). Stash\n // it so `request()` can keep it alive for tracking once the slot renders, instead of treating this\n // as \"no ad returned at all\".\n emptyAdForTracking = ad;\n return;\n }\n\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n }\n\n function processOnError(error: string): void {\n if (status.value !== 'error') {\n status.value = 'error';\n logger.error(error);\n runOnError(new Error(error, {\n cause: error,\n }));\n }\n }\n\n function cleanElement(): void {\n if (!element.value || renderMode === 'none')\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n\n renderedAd = null;\n renderedElement = null;\n }\n\n function dispose(): void {\n cleanElement();\n\n element.value = null;\n\n data.value = null;\n originalData.value = null;\n\n domObserver.disconnect();\n\n runOnDispose();\n\n isDisposed.value = true;\n\n scope.stop();\n }\n\n const state = reactive({\n location: context.location ?? '',\n lazyLoading: options.lazyLoading ?? false,\n type,\n slot,\n parameters,\n format,\n name,\n data,\n isViewabilityTracked,\n isImpressionTracked,\n isEmpty,\n status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n processOnEmpty,\n processOnError,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(\n state,\n (newState) => {\n slotContext.value = newState;\n },\n {\n deep: true,\n immediate: true,\n },\n );\n\n context.hooks.onInit(async () => {\n await runOnInit();\n\n if (status.value === 'empty' || status.value === 'error') {\n return;\n }\n\n if (initialData) {\n status.value = 'loaded';\n isEmpty.value = false;\n emptyAdForTracking = null;\n\n data.value = initialData;\n\n let response = await runOnRequest(initialData);\n\n if (!response && emptyAdForTracking) {\n // `onRequest` identified the ad as empty via `processOnEmpty(ad)`. Keep the original ad around so\n // it still reaches `render()`, where the position is tracked even though no creative is shown.\n response = emptyAdForTracking;\n }\n\n data.value = response;\n // eslint-disable-next-line require-atomic-updates\n status.value = response ? 'loaded' : 'empty';\n\n return;\n }\n\n status.value = 'initialized';\n\n if (options.lazyLoading) {\n return;\n }\n\n data.value = (await slotContext.value?.request()) ?? null;\n });\n\n return state;\n })!;\n}\n"],"names":["renderIframe","renderInline","doNothing","effectScope","ref","uniqueId","useSlotHooks","reactive","useQueryDetector","computed","generateName","watch","useDomLoaded","shallowRef","useRenderIntersectionObserver","useViewabilityObserver","addTrackingPixel","extRequestAd","waitForDomLoad","logger","toRaw","pick","omit"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  const name = "@adhese/sdk";
2
- const version = "1.12.1";
2
+ const version = "1.12.2";
3
3
  export {
4
4
  name,
5
5
  version
package/dist/slot/slot.js CHANGED
@@ -1,4 +1,4 @@
1
- import { effectScope, ref, uniqueId, reactive, computed, generateName, watch, shallowRef, addTrackingPixel, waitForDomLoad, doNothing, renderInline, renderIframe, pick, omit } from "@adhese/sdk-shared";
1
+ import { effectScope, ref, uniqueId, reactive, computed, generateName, watch, shallowRef, addTrackingPixel, waitForDomLoad, toRaw, doNothing, renderInline, renderIframe, pick, omit } from "@adhese/sdk-shared";
2
2
  import { logger } from "../logger/logger.js";
3
3
  import { useQueryDetector } from "../queryDetector/queryDetector.js";
4
4
  import { requestAd } from "../requestAds/requestAds.js";
@@ -219,6 +219,8 @@ function createSlot(slotOptions) {
219
219
  additionalTrackingPixelElement.value.remove();
220
220
  });
221
221
  let inFlightRequest = null;
222
+ let renderedAd = null;
223
+ let renderedElement = null;
222
224
  async function request() {
223
225
  if ((inFlightRequest == null ? void 0 : inFlightRequest.name) === name.value)
224
226
  return inFlightRequest.promise;
@@ -288,6 +290,7 @@ function createSlot(slotOptions) {
288
290
  }
289
291
  }
290
292
  const hadAdBeforeBeforeRenderHook = Boolean(renderAd);
293
+ const sourceAd = renderAd;
291
294
  renderAd = renderAd && await runOnBeforeRender(renderAd);
292
295
  renderMode = (renderAd == null ? void 0 : renderAd.renderMode) ?? renderMode;
293
296
  if (!element.value && renderMode !== "none") {
@@ -310,6 +313,10 @@ function createSlot(slotOptions) {
310
313
  status.value = "rendered";
311
314
  return element.value;
312
315
  }
316
+ if (sourceAd && toRaw(sourceAd) === renderedAd && element.value === renderedElement) {
317
+ status.value = "rendered";
318
+ return element.value;
319
+ }
313
320
  if (typeof (renderAd == null ? void 0 : renderAd.tag) !== "string" && renderMode !== "none") {
314
321
  const error = `Could not render slot for slot ${name.value}. A valid tag doesn't exist or is not HTML string.`;
315
322
  throw new Error(error);
@@ -323,6 +330,8 @@ function createSlot(slotOptions) {
323
330
  element.value
324
331
  );
325
332
  }
333
+ renderedAd = sourceAd && toRaw(sourceAd);
334
+ renderedElement = element.value;
326
335
  logger.debug(`Slot rendered ${name.value}`, {
327
336
  renderedElement: element,
328
337
  location: context.location,
@@ -366,6 +375,8 @@ function createSlot(slotOptions) {
366
375
  return;
367
376
  element.value.innerHTML = "";
368
377
  element.value.style.position = "";
378
+ renderedAd = null;
379
+ renderedElement = null;
369
380
  }
370
381
  function dispose() {
371
382
  cleanElement();
@@ -1 +1 @@
1
- {"version":3,"file":"slot.js","sources":["../../src/slot/slot.ts"],"sourcesContent":["import type { AdheseAd } from '@adhese/sdk';\nimport type {\n AdheseSlot,\n AdheseSlotContext,\n AdheseSlotOptions,\n RenderMode,\n} from './slot.types';\nimport {\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n omit,\n pick,\n reactive,\n type Ref,\n ref,\n renderIframe,\n renderInline,\n type RenderOptions,\n shallowRef,\n uniqueId,\n type UnwrapRef,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<\n RenderMode,\n (ad: RenderOptions, element: HTMLElement) => void\n> = {\n iframe: renderIframe,\n inline: renderInline,\n none: doNothing,\n};\n\nconst defaultOptions = {\n renderMode: 'iframe',\n type: 'normal',\n} satisfies Partial<AdheseSlotOptions>;\n\n/**\n * Create a new slot instance. This slot instance can be used to request and render ads.\n *\n * @param slotOptions {AdheseSlotOptions} The options to create the slot with.\n *\n * @return AdheseSlot The created slot instance.\n */\nexport function createSlot(slotOptions: AdheseSlotOptions): AdheseSlot {\n const scope = effectScope();\n\n return scope.run(() => {\n const slotContext = ref<AdheseSlotContext | null>(null);\n const options = slotOptions.context.hooks.runOnSlotCreate({\n ...defaultOptions,\n ...(Object.fromEntries(\n Object.entries(slotOptions).filter(([, value]) => value !== undefined),\n ) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n type = 'normal',\n } = options;\n\n let { renderMode = 'iframe' } = options;\n\n const id = uniqueId();\n const {\n runOnBeforeRender,\n runOnRender,\n runOnBeforeRequest,\n runOnRequest,\n runOnInit,\n runOnDispose,\n runOnEmpty,\n runOnError,\n runOnImpressionTracked,\n runOnViewableTracked,\n ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(\n new Map(Object.entries(options.parameters ?? {})),\n );\n\n const [device, disposeQueryDetector] = useQueryDetector(\n context,\n typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(\n options.format.map(item => [item.format, item.query]),\n ),\n );\n\n const format = computed(() =>\n typeof options.format === 'string' ? options.format : device.value,\n );\n\n const data = ref<AdheseAd | null>(null) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const isEmpty = ref(false);\n // Ad stashed by `processOnEmpty(ad)` when `onRequest` identifies an ad's creative as empty. `request()`\n // rescues it into `data`/`originalData` so tracking pixels are still available once the slot renders.\n let emptyAdForTracking: AdheseAd | null = null;\n const name = computed(() =>\n generateName(options.context.location, format.value, options.slot),\n );\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch(name, async (newName, oldName) => {\n if (newName === oldName)\n return;\n\n const newAd = await slotContext.value?.request();\n\n if (!newAd)\n return;\n\n slotContext.value?.cleanElement();\n\n data.value = newAd;\n originalData.value = newAd;\n });\n\n const isDomLoaded = useDomLoaded(context);\n\n const element = shallowRef<HTMLElement | null>(null);\n\n function getElement(): HTMLElement | null {\n if (\n !(\n typeof options.containingElement === 'string'\n || !options.containingElement\n )\n ) {\n return options.containingElement;\n }\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(\n `#${options.containingElement}`,\n );\n }\n\n watch(element, async (newElement, oldElement) => {\n if (\n status.value === 'empty'\n || status.value === 'error'\n || status.value === 'loading'\n ) {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (\n newElement === oldElement\n || (oldElement === null && newElement === null)\n ) {\n return;\n }\n if (!context.options.eagerRendering && !oldElement) {\n return;\n }\n if (status.value === 'rendering' || status.value === 'rendered') {\n return;\n }\n await render();\n });\n\n const domObserver = new MutationObserver(() => {\n element.value = getElement();\n });\n\n domObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n watch(\n isDomLoaded,\n () => {\n element.value = getElement();\n },\n { immediate: true, deep: true },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n watch(\n isInViewport,\n async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered' && status.value !== 'rendering')\n await slotContext.value?.render();\n },\n { immediate: true },\n );\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n let viewabilityPixel;\n if (slotContext.value?.data?.origin === undefined) {\n context.logger.warn(\n `Origin not found for ${slotContext.value?.name}`,\n );\n return;\n }\n switch (slotContext.value?.data?.origin) {\n case 'DALE': {\n // @ts-expect-error - Data structure is not typed and very messy to type\n const seatbid = slotContext.value?.data?.originData?.seatbid;\n const bid = seatbid ? seatbid[0]?.bid[0] : undefined;\n viewabilityPixel = bid\n ? bid.ext?.adhese?.viewableImpressionCounter\n : undefined;\n break;\n }\n case 'JERLICIA':\n viewabilityPixel\n = slotContext.value?.data?.viewableImpressionCounter;\n break;\n }\n if (viewabilityPixel) {\n trackingPixel.value = addTrackingPixel(viewabilityPixel);\n context.logger.debug(\n `Viewability tracking pixel fired for ${slotContext.value?.name}`,\n );\n runOnViewableTracked(slotContext.value?.data);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const additionalTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n const isAdditionalTracked = ref(false);\n\n const impressionTrackedAd = ref<AdheseAd | null>(null);\n const additionalTrackedAd = ref<AdheseAd | null>(null);\n\n watch(\n [status, isInViewport, data],\n ([newStatus, newIsInViewport, newData]) => {\n if (newStatus !== 'rendered' || !newIsInViewport)\n return;\n\n if (\n newData?.impressionCounter\n && impressionTrackedAd.value !== newData\n ) {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = addTrackingPixel(\n newData.impressionCounter,\n );\n impressionTrackedAd.value = newData;\n runOnImpressionTracked(newData);\n isImpressionTracked.value = true;\n context.logger.debug(\n `Impression tracking pixel fired for ${slotContext.value?.name}`,\n );\n }\n if (\n newData?.additionalTracker\n && additionalTrackedAd.value !== newData\n ) {\n additionalTrackingPixelElement.value?.remove();\n additionalTrackingPixelElement.value = addTrackingPixel(\n newData.additionalTracker,\n );\n additionalTrackedAd.value = newData;\n isAdditionalTracked.value = true;\n context.logger.debug(\n `Additional Impression tracking pixel fired for ${slotContext.value?.name}`,\n );\n }\n },\n { immediate: true },\n );\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n if (additionalTrackingPixelElement.value)\n additionalTrackingPixelElement.value.remove();\n });\n\n // The request currently in flight, if any. Several things can ask a slot for its ad at roughly the\n // same moment - the viewport and element watchers, `onInit`, or an app calling `render()` while the\n // initial request is still running - and `render()` starts a request of its own whenever it finds no\n // ad yet. Without this they each fire their own call to the ad server for the same slot. Keyed by\n // name so that a format (and therefore name) change still results in a genuinely new request.\n let inFlightRequest: { name: string; promise: Promise<AdheseAd | null> } | null = null;\n\n async function request(): Promise<AdheseAd | null> {\n if (inFlightRequest?.name === name.value)\n return inFlightRequest.promise;\n\n const promise = fetchAd();\n inFlightRequest = { name: name.value, promise };\n\n try {\n return await promise;\n }\n finally {\n if (inFlightRequest?.promise === promise)\n inFlightRequest = null;\n }\n }\n\n async function fetchAd(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\n isEmpty.value = false;\n emptyAdForTracking = null;\n\n let response = await runOnBeforeRequest(null);\n\n if (!response) {\n response = await extRequestAd({\n slot: {\n name: name.value,\n parameters,\n },\n context,\n });\n }\n\n if (response)\n response = await runOnRequest(response);\n\n if (!response && emptyAdForTracking) {\n // `onRequest` identified the ad as empty via `processOnEmpty(ad)`. Keep the original ad around so\n // it still reaches `render()`, where the position is tracked even though no creative is shown.\n response = emptyAdForTracking;\n }\n\n data.value = response;\n\n if (!originalData.value)\n originalData.value = response;\n\n status.value = response ? 'loaded' : 'empty';\n\n if (!response)\n cleanElement();\n\n if (response && context.options.eagerRendering && element.value)\n await render(response);\n\n return response;\n }\n catch (error) {\n processOnError(error as string);\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n if (\n status.value === 'empty'\n || status.value === 'error'\n || status.value === 'initializing'\n ) {\n return null;\n }\n\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'rendering';\n await waitForDomLoad();\n element.value = getElement();\n\n if (adToRender) {\n // An explicit ad was passed in, overriding whatever the slot previously fetched. Don't carry over an\n // `isEmpty` flag from an earlier, unrelated ad.\n isEmpty.value = false;\n }\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? null;\n if (!renderAd) {\n renderAd = await request();\n if ((status.value as UnwrapRef<AdheseSlot>['status']) === 'rendered') {\n return element.value;\n }\n }\n\n const hadAdBeforeBeforeRenderHook = Boolean(renderAd);\n\n renderAd = renderAd && (await runOnBeforeRender(renderAd));\n\n renderMode = renderAd?.renderMode ?? renderMode;\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(\n `Could not render slot for format ${format.value}. No element found.`,\n slotContext.value,\n );\n\n return null;\n }\n\n if (!renderAd) {\n if (hadAdBeforeBeforeRenderHook) {\n // The ad was identified as empty by the `onBeforeRender` hook itself. The position is still\n // tracked as rendered, but no creative is written to the element. Whatever the app already put\n // in the element (e.g. a fallback rendered from `onEmpty`) is left untouched.\n markEmpty();\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n logger.debug(`Slot ${name.value} identified as empty by the onBeforeRender hook`, slotContext.value);\n\n return element.value;\n }\n\n return null;\n }\n\n if (isEmpty.value) {\n // The ad was already identified as empty earlier, typically via `processOnEmpty(ad)` from the\n // `onRequest` hook. The position is tracked as rendered, but no creative is written to the element.\n // Whatever the app already put in the element (e.g. a fallback rendered from `onEmpty`) is left\n // untouched.\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n\n return element.value;\n }\n\n if (typeof renderAd?.tag !== 'string' && renderMode !== 'none') {\n const error = `Could not render slot for slot ${name.value}. A valid tag doesn't exist or is not HTML string.`;\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode](\n {\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions,\n element.value,\n );\n }\n\n logger.debug(`Slot rendered ${name.value}`, {\n renderedElement: element,\n location: context.location,\n format,\n containingElement,\n });\n\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n catch (error) {\n processOnError(error as string);\n return null;\n }\n }\n\n function markEmpty(): void {\n if (isEmpty.value)\n return;\n\n isEmpty.value = true;\n runOnEmpty();\n }\n\n function processOnEmpty(ad?: AdheseAd): void {\n markEmpty();\n\n if (ad) {\n // An ad was returned, but its creative was identified as empty (e.g. a no-fill/house banner). Stash\n // it so `request()` can keep it alive for tracking once the slot renders, instead of treating this\n // as \"no ad returned at all\".\n emptyAdForTracking = ad;\n return;\n }\n\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n }\n\n function processOnError(error: string): void {\n if (status.value !== 'error') {\n status.value = 'error';\n logger.error(error);\n runOnError(new Error(error, {\n cause: error,\n }));\n }\n }\n\n function cleanElement(): void {\n if (!element.value || renderMode === 'none')\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n }\n\n function dispose(): void {\n cleanElement();\n\n element.value = null;\n\n data.value = null;\n originalData.value = null;\n\n domObserver.disconnect();\n\n runOnDispose();\n\n isDisposed.value = true;\n\n scope.stop();\n }\n\n const state = reactive({\n location: context.location ?? '',\n lazyLoading: options.lazyLoading ?? false,\n type,\n slot,\n parameters,\n format,\n name,\n data,\n isViewabilityTracked,\n isImpressionTracked,\n isEmpty,\n status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n processOnEmpty,\n processOnError,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(\n state,\n (newState) => {\n slotContext.value = newState;\n },\n {\n deep: true,\n immediate: true,\n },\n );\n\n context.hooks.onInit(async () => {\n await runOnInit();\n\n if (status.value === 'empty' || status.value === 'error') {\n return;\n }\n\n if (initialData) {\n status.value = 'loaded';\n isEmpty.value = false;\n emptyAdForTracking = null;\n\n data.value = initialData;\n\n let response = await runOnRequest(initialData);\n\n if (!response && emptyAdForTracking) {\n // `onRequest` identified the ad as empty via `processOnEmpty(ad)`. Keep the original ad around so\n // it still reaches `render()`, where the position is tracked even though no creative is shown.\n response = emptyAdForTracking;\n }\n\n data.value = response;\n // eslint-disable-next-line require-atomic-updates\n status.value = response ? 'loaded' : 'empty';\n\n return;\n }\n\n status.value = 'initialized';\n\n if (options.lazyLoading) {\n return;\n }\n\n data.value = (await slotContext.value?.request()) ?? null;\n });\n\n return state;\n })!;\n}\n"],"names":["extRequestAd"],"mappings":"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"}
1
+ {"version":3,"file":"slot.js","sources":["../../src/slot/slot.ts"],"sourcesContent":["import type { AdheseAd } from '@adhese/sdk';\nimport type {\n AdheseSlot,\n AdheseSlotContext,\n AdheseSlotOptions,\n RenderMode,\n} from './slot.types';\nimport {\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n omit,\n pick,\n reactive,\n type Ref,\n ref,\n renderIframe,\n renderInline,\n type RenderOptions,\n shallowRef,\n toRaw,\n uniqueId,\n type UnwrapRef,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<\n RenderMode,\n (ad: RenderOptions, element: HTMLElement) => void\n> = {\n iframe: renderIframe,\n inline: renderInline,\n none: doNothing,\n};\n\nconst defaultOptions = {\n renderMode: 'iframe',\n type: 'normal',\n} satisfies Partial<AdheseSlotOptions>;\n\n/**\n * Create a new slot instance. This slot instance can be used to request and render ads.\n *\n * @param slotOptions {AdheseSlotOptions} The options to create the slot with.\n *\n * @return AdheseSlot The created slot instance.\n */\nexport function createSlot(slotOptions: AdheseSlotOptions): AdheseSlot {\n const scope = effectScope();\n\n return scope.run(() => {\n const slotContext = ref<AdheseSlotContext | null>(null);\n const options = slotOptions.context.hooks.runOnSlotCreate({\n ...defaultOptions,\n ...(Object.fromEntries(\n Object.entries(slotOptions).filter(([, value]) => value !== undefined),\n ) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n type = 'normal',\n } = options;\n\n let { renderMode = 'iframe' } = options;\n\n const id = uniqueId();\n const {\n runOnBeforeRender,\n runOnRender,\n runOnBeforeRequest,\n runOnRequest,\n runOnInit,\n runOnDispose,\n runOnEmpty,\n runOnError,\n runOnImpressionTracked,\n runOnViewableTracked,\n ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(\n new Map(Object.entries(options.parameters ?? {})),\n );\n\n const [device, disposeQueryDetector] = useQueryDetector(\n context,\n typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(\n options.format.map(item => [item.format, item.query]),\n ),\n );\n\n const format = computed(() =>\n typeof options.format === 'string' ? options.format : device.value,\n );\n\n const data = ref<AdheseAd | null>(null) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const isEmpty = ref(false);\n // Ad stashed by `processOnEmpty(ad)` when `onRequest` identifies an ad's creative as empty. `request()`\n // rescues it into `data`/`originalData` so tracking pixels are still available once the slot renders.\n let emptyAdForTracking: AdheseAd | null = null;\n const name = computed(() =>\n generateName(options.context.location, format.value, options.slot),\n );\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch(name, async (newName, oldName) => {\n if (newName === oldName)\n return;\n\n const newAd = await slotContext.value?.request();\n\n if (!newAd)\n return;\n\n slotContext.value?.cleanElement();\n\n data.value = newAd;\n originalData.value = newAd;\n });\n\n const isDomLoaded = useDomLoaded(context);\n\n const element = shallowRef<HTMLElement | null>(null);\n\n function getElement(): HTMLElement | null {\n if (\n !(\n typeof options.containingElement === 'string'\n || !options.containingElement\n )\n ) {\n return options.containingElement;\n }\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(\n `#${options.containingElement}`,\n );\n }\n\n watch(element, async (newElement, oldElement) => {\n if (\n status.value === 'empty'\n || status.value === 'error'\n || status.value === 'loading'\n ) {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (\n newElement === oldElement\n || (oldElement === null && newElement === null)\n ) {\n return;\n }\n if (!context.options.eagerRendering && !oldElement) {\n return;\n }\n if (status.value === 'rendering' || status.value === 'rendered') {\n return;\n }\n await render();\n });\n\n const domObserver = new MutationObserver(() => {\n element.value = getElement();\n });\n\n domObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n watch(\n isDomLoaded,\n () => {\n element.value = getElement();\n },\n { immediate: true, deep: true },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n watch(\n isInViewport,\n async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered' && status.value !== 'rendering')\n await slotContext.value?.render();\n },\n { immediate: true },\n );\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n let viewabilityPixel;\n if (slotContext.value?.data?.origin === undefined) {\n context.logger.warn(\n `Origin not found for ${slotContext.value?.name}`,\n );\n return;\n }\n switch (slotContext.value?.data?.origin) {\n case 'DALE': {\n // @ts-expect-error - Data structure is not typed and very messy to type\n const seatbid = slotContext.value?.data?.originData?.seatbid;\n const bid = seatbid ? seatbid[0]?.bid[0] : undefined;\n viewabilityPixel = bid\n ? bid.ext?.adhese?.viewableImpressionCounter\n : undefined;\n break;\n }\n case 'JERLICIA':\n viewabilityPixel\n = slotContext.value?.data?.viewableImpressionCounter;\n break;\n }\n if (viewabilityPixel) {\n trackingPixel.value = addTrackingPixel(viewabilityPixel);\n context.logger.debug(\n `Viewability tracking pixel fired for ${slotContext.value?.name}`,\n );\n runOnViewableTracked(slotContext.value?.data);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const additionalTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n const isAdditionalTracked = ref(false);\n\n const impressionTrackedAd = ref<AdheseAd | null>(null);\n const additionalTrackedAd = ref<AdheseAd | null>(null);\n\n watch(\n [status, isInViewport, data],\n ([newStatus, newIsInViewport, newData]) => {\n if (newStatus !== 'rendered' || !newIsInViewport)\n return;\n\n if (\n newData?.impressionCounter\n && impressionTrackedAd.value !== newData\n ) {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = addTrackingPixel(\n newData.impressionCounter,\n );\n impressionTrackedAd.value = newData;\n runOnImpressionTracked(newData);\n isImpressionTracked.value = true;\n context.logger.debug(\n `Impression tracking pixel fired for ${slotContext.value?.name}`,\n );\n }\n if (\n newData?.additionalTracker\n && additionalTrackedAd.value !== newData\n ) {\n additionalTrackingPixelElement.value?.remove();\n additionalTrackingPixelElement.value = addTrackingPixel(\n newData.additionalTracker,\n );\n additionalTrackedAd.value = newData;\n isAdditionalTracked.value = true;\n context.logger.debug(\n `Additional Impression tracking pixel fired for ${slotContext.value?.name}`,\n );\n }\n },\n { immediate: true },\n );\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n if (additionalTrackingPixelElement.value)\n additionalTrackingPixelElement.value.remove();\n });\n\n // The request currently in flight, if any. Several things can ask a slot for its ad at roughly the\n // same moment - the viewport and element watchers, `onInit`, or an app calling `render()` while the\n // initial request is still running - and `render()` starts a request of its own whenever it finds no\n // ad yet. Without this they each fire their own call to the ad server for the same slot. Keyed by\n // name so that a format (and therefore name) change still results in a genuinely new request.\n let inFlightRequest: { name: string; promise: Promise<AdheseAd | null> } | null = null;\n\n // What was last written to the DOM, so that a repeat render for an unchanged ad can be skipped.\n // Cleared whenever the element's contents are dropped, so the creative is written again after that.\n let renderedAd: AdheseAd | null = null;\n let renderedElement: HTMLElement | null = null;\n\n async function request(): Promise<AdheseAd | null> {\n if (inFlightRequest?.name === name.value)\n return inFlightRequest.promise;\n\n const promise = fetchAd();\n inFlightRequest = { name: name.value, promise };\n\n try {\n return await promise;\n }\n finally {\n if (inFlightRequest?.promise === promise)\n inFlightRequest = null;\n }\n }\n\n async function fetchAd(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\n isEmpty.value = false;\n emptyAdForTracking = null;\n\n let response = await runOnBeforeRequest(null);\n\n if (!response) {\n response = await extRequestAd({\n slot: {\n name: name.value,\n parameters,\n },\n context,\n });\n }\n\n if (response)\n response = await runOnRequest(response);\n\n if (!response && emptyAdForTracking) {\n // `onRequest` identified the ad as empty via `processOnEmpty(ad)`. Keep the original ad around so\n // it still reaches `render()`, where the position is tracked even though no creative is shown.\n response = emptyAdForTracking;\n }\n\n data.value = response;\n\n if (!originalData.value)\n originalData.value = response;\n\n status.value = response ? 'loaded' : 'empty';\n\n if (!response)\n cleanElement();\n\n if (response && context.options.eagerRendering && element.value)\n await render(response);\n\n return response;\n }\n catch (error) {\n processOnError(error as string);\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n if (\n status.value === 'empty'\n || status.value === 'error'\n || status.value === 'initializing'\n ) {\n return null;\n }\n\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'rendering';\n await waitForDomLoad();\n element.value = getElement();\n\n if (adToRender) {\n // An explicit ad was passed in, overriding whatever the slot previously fetched. Don't carry over an\n // `isEmpty` flag from an earlier, unrelated ad.\n isEmpty.value = false;\n }\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? null;\n if (!renderAd) {\n renderAd = await request();\n if ((status.value as UnwrapRef<AdheseSlot>['status']) === 'rendered') {\n return element.value;\n }\n }\n\n const hadAdBeforeBeforeRenderHook = Boolean(renderAd);\n // Kept before `onBeforeRender` runs, since that hook is free to return a freshly built ad object\n // every time it's called, which would make the \"already rendered\" check above never match.\n const sourceAd = renderAd;\n\n renderAd = renderAd && (await runOnBeforeRender(renderAd));\n\n renderMode = renderAd?.renderMode ?? renderMode;\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(\n `Could not render slot for format ${format.value}. No element found.`,\n slotContext.value,\n );\n\n return null;\n }\n\n if (!renderAd) {\n if (hadAdBeforeBeforeRenderHook) {\n // The ad was identified as empty by the `onBeforeRender` hook itself. The position is still\n // tracked as rendered, but no creative is written to the element. Whatever the app already put\n // in the element (e.g. a fallback rendered from `onEmpty`) is left untouched.\n markEmpty();\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n logger.debug(`Slot ${name.value} identified as empty by the onBeforeRender hook`, slotContext.value);\n\n return element.value;\n }\n\n return null;\n }\n\n if (isEmpty.value) {\n // The ad was already identified as empty earlier, typically via `processOnEmpty(ad)` from the\n // `onRequest` hook. The position is tracked as rendered, but no creative is written to the element.\n // Whatever the app already put in the element (e.g. a fallback rendered from `onEmpty`) is left\n // untouched.\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n\n return element.value;\n }\n\n if (sourceAd && toRaw(sourceAd) === renderedAd && element.value === renderedElement) {\n // This exact ad is already written into this exact element. Several things can ask a slot to\n // render at roughly the same moment, and writing the creative again is not harmless:\n // `renderInline` appends, so the creative stacks up, and the creative's own scripts and the\n // `onRender` hook run again. A new ad, or a new element, still re-renders below.\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n\n return element.value;\n }\n\n if (typeof renderAd?.tag !== 'string' && renderMode !== 'none') {\n const error = `Could not render slot for slot ${name.value}. A valid tag doesn't exist or is not HTML string.`;\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode](\n {\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions,\n element.value,\n );\n }\n\n // Stored raw: the same ad reaches `render()` either as the plain object `request()` resolved with\n // or as the reactive proxy `data` wrapped it in, and those are not identical by reference.\n renderedAd = sourceAd && toRaw(sourceAd);\n renderedElement = element.value;\n\n logger.debug(`Slot rendered ${name.value}`, {\n renderedElement: element,\n location: context.location,\n format,\n containingElement,\n });\n\n // eslint-disable-next-line require-atomic-updates\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n catch (error) {\n processOnError(error as string);\n return null;\n }\n }\n\n function markEmpty(): void {\n if (isEmpty.value)\n return;\n\n isEmpty.value = true;\n runOnEmpty();\n }\n\n function processOnEmpty(ad?: AdheseAd): void {\n markEmpty();\n\n if (ad) {\n // An ad was returned, but its creative was identified as empty (e.g. a no-fill/house banner). Stash\n // it so `request()` can keep it alive for tracking once the slot renders, instead of treating this\n // as \"no ad returned at all\".\n emptyAdForTracking = ad;\n return;\n }\n\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n }\n\n function processOnError(error: string): void {\n if (status.value !== 'error') {\n status.value = 'error';\n logger.error(error);\n runOnError(new Error(error, {\n cause: error,\n }));\n }\n }\n\n function cleanElement(): void {\n if (!element.value || renderMode === 'none')\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n\n renderedAd = null;\n renderedElement = null;\n }\n\n function dispose(): void {\n cleanElement();\n\n element.value = null;\n\n data.value = null;\n originalData.value = null;\n\n domObserver.disconnect();\n\n runOnDispose();\n\n isDisposed.value = true;\n\n scope.stop();\n }\n\n const state = reactive({\n location: context.location ?? '',\n lazyLoading: options.lazyLoading ?? false,\n type,\n slot,\n parameters,\n format,\n name,\n data,\n isViewabilityTracked,\n isImpressionTracked,\n isEmpty,\n status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n processOnEmpty,\n processOnError,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(\n state,\n (newState) => {\n slotContext.value = newState;\n },\n {\n deep: true,\n immediate: true,\n },\n );\n\n context.hooks.onInit(async () => {\n await runOnInit();\n\n if (status.value === 'empty' || status.value === 'error') {\n return;\n }\n\n if (initialData) {\n status.value = 'loaded';\n isEmpty.value = false;\n emptyAdForTracking = null;\n\n data.value = initialData;\n\n let response = await runOnRequest(initialData);\n\n if (!response && emptyAdForTracking) {\n // `onRequest` identified the ad as empty via `processOnEmpty(ad)`. Keep the original ad around so\n // it still reaches `render()`, where the position is tracked even though no creative is shown.\n response = emptyAdForTracking;\n }\n\n data.value = response;\n // eslint-disable-next-line require-atomic-updates\n status.value = response ? 'loaded' : 'empty';\n\n return;\n }\n\n status.value = 'initialized';\n\n if (options.lazyLoading) {\n return;\n }\n\n data.value = (await slotContext.value?.request()) ?? null;\n });\n\n return state;\n })!;\n}\n"],"names":["extRequestAd"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@adhese/sdk",
3
3
  "type": "module",
4
- "version": "1.12.1",
4
+ "version": "1.12.2",
5
5
  "description": "Adhese SDK",
6
6
  "license": "GPL-3.0",
7
7
  "repository": {