@adhese/sdk 1.8.0 → 1.8.1
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 +6 -0
- package/dist/adheseSdk.d.ts +4 -0
- package/dist/cjs/package.json.cjs +1 -1
- package/dist/cjs/requestAds/requestAds.cjs +2 -0
- package/dist/cjs/requestAds/requestAds.cjs.map +1 -1
- package/dist/cjs/slot/slot.cjs +6 -3
- package/dist/cjs/slot/slot.cjs.map +1 -1
- package/dist/package.json.js +1 -1
- package/dist/requestAds/requestAds.js +2 -0
- package/dist/requestAds/requestAds.js.map +1 -1
- package/dist/slot/slot.js +6 -3
- package/dist/slot/slot.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/adheseSdk.d.ts
CHANGED
|
@@ -416,6 +416,10 @@ type BaseAdheseSlot = Merge<Omit<AdheseSlotOptions, 'onDispose' | 'context' | 'o
|
|
|
416
416
|
* Removes the slot from the DOM and cleans up the slot instance.
|
|
417
417
|
*/
|
|
418
418
|
dispose(): void;
|
|
419
|
+
/**
|
|
420
|
+
* Process the onEmpty hook when a slot is not filled with an Ad.
|
|
421
|
+
*/
|
|
422
|
+
processOnEmpty(): void;
|
|
419
423
|
}>;
|
|
420
424
|
type AdheseSlotContext = BaseAdheseSlot;
|
|
421
425
|
type ReadonlyProps$1 = 'type' | 'name' | 'format' | 'location' | 'status' | 'isDisposed' | 'element' | 'id';
|
|
@@ -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.8.
|
|
4
|
+
const version = "1.8.1";
|
|
5
5
|
exports.name = name;
|
|
6
6
|
exports.version = version;
|
|
7
7
|
//# sourceMappingURL=package.json.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requestAds.cjs","sources":["../../../src/requestAds/requestAds.ts"],"sourcesContent":["import type { AdheseContext } from '../main.types';\nimport type { AdheseAd } from './requestAds.schema';\nimport { debounce } from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { requestPreviews } from './requestAds.preview';\nimport { requestWithGet, requestWithPost } from './requestAds.utils';\n\nexport type AdRequestOptions = {\n /**\n * Slot you want to fetch the ad for\n */\n slot: {\n name: string;\n parameters: Map<string, ReadonlyArray<string> | string>;\n };\n context: AdheseContext;\n};\n\nexport type AdMultiRequestOptions = Omit<AdRequestOptions, 'slot'> & {\n slots: ReadonlyArray<AdRequestOptions['slot']>;\n};\n\nconst batch = new Map<\n string,\n {\n options: AdRequestOptions;\n resolve(ad: AdheseAd | null): void;\n }\n>();\n\n/**\n * Debounced function to request ads in batches. This function is debounced to prevent multiple requests for the same ad.\n */\nconst runRequestAdsBatch = debounce(\n async (context: AdheseContext) => {\n if (batch.size === 0)\n return [];\n\n const ads = await requestAds({\n slots: Array.from(batch.values()).map(({ options }) => options.slot),\n context,\n });\n\n for (const { options, resolve } of batch.values()) {\n const ad = ads.find(({ slotName }) => slotName === options.slot.name);\n\n if (ad)\n resolve(ad);\n else resolve(null);\n }\n\n batch.clear();\n return ads;\n },\n {\n waitMs: 200,\n timing: 'trailing',\n },\n);\n\n/**\n * Request a single ad from the API. If you need to fetch multiple ads at once use the `requestAds` function.\n */\nexport async function requestAd(\n options: AdRequestOptions,\n): Promise<AdheseAd | null> {\n const promise = new Promise<AdheseAd | null>((resolve) => {\n batch.set(options.slot.name, { options, resolve });\n });\n\n await runRequestAdsBatch.call(options.context);\n\n return promise;\n}\n\n/**\n * Request multiple ads from the API. If you need to fetch a single ad use the `requestAd` function.\n */\nexport async function requestAds(\n requestOptions: AdMultiRequestOptions,\n): Promise<ReadonlyArray<AdheseAd>> {\n const options = await requestOptions.context.hooks.runOnRequest(\n requestOptions,\n );\n\n const { context } = options;\n\n try {\n context?.events?.requestAd.dispatch({\n ...options,\n context,\n });\n\n const [response, previews, parseResponse] = await Promise.all([\n context.options.requestType?.toUpperCase() === 'POST'\n ? requestWithPost(options)\n : requestWithGet(options),\n requestPreviews(options?.context?.options.previewHost),\n import('./requestAds.schema').then(module => module.parseResponse),\n ]);\n\n logger.debug('Received response', response);\n\n if (!response.ok) {\n throw new Error(\n `Failed to request ad: ${response.status} ${response.statusText}`,\n );\n }\n\n const result = parseResponse((await response.json()) as unknown);\n logger.debug('Parsed ad', result);\n\n if (previews.length > 0) {\n logger.info(\n `Found ${previews.length} ${\n previews.length === 1 ? 'preview' : 'previews'\n }. Replacing ads in response with preview items`,\n previews,\n );\n }\n\n const matchedPreviews: Array<AdheseAd> = [];\n for (const [, value] of context.slots.entries()) {\n const ad = result.find(({ slotName }) => slotName === value.name);\n const partnerAd = previews.find(\n preview => preview.adType === value.format,\n );\n if (ad || partnerAd) {\n const baseAd = partnerAd ?? ad;\n matchedPreviews.push({\n ...baseAd,\n slotName: value.name,\n } as AdheseAd);\n }\n }\n\n if (matchedPreviews.length > 0)\n context.events?.previewReceived.dispatch(matchedPreviews);\n\n const mergedResult = await context.hooks.runOnResponse(matchedPreviews);\n\n context.events?.responseReceived.dispatch(mergedResult);\n\n return mergedResult;\n }\n catch (error) {\n logger.error(String(error));\n context?.events?.requestError.dispatch(error as Error);\n\n throw error;\n }\n}\n"],"names":["debounce","requestWithPost","requestWithGet","requestPreviews","module","logger"],"mappings":";;;;;;AAsBA,MAAM,4BAAY,IAMhB;AAKF,MAAM,qBAAqBA,UAAA;AAAA,EACzB,OAAO,YAA2B;AAChC,QAAI,MAAM,SAAS;AACjB,aAAO,CAAC;AAEJ,UAAA,MAAM,MAAM,WAAW;AAAA,MAC3B,OAAO,MAAM,KAAK,MAAM,OAAQ,CAAA,EAAE,IAAI,CAAC,EAAE,cAAc,QAAQ,IAAI;AAAA,MACnE;AAAA,IAAA,CACD;AAED,eAAW,EAAE,SAAS,QAAa,KAAA,MAAM,UAAU;AAC3C,YAAA,KAAK,IAAI,KAAK,CAAC,EAAE,SAAe,MAAA,aAAa,QAAQ,KAAK,IAAI;AAEhE,UAAA;AACF,gBAAQ,EAAE;AAAA,mBACC,IAAI;AAAA,IAAA;AAGnB,UAAM,MAAM;AACL,WAAA;AAAA,EACT;AAAA,EACA;AAAA,IACE,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA;AAEZ;AAKA,eAAsB,UACpB,SAC0B;AAC1B,QAAM,UAAU,IAAI,QAAyB,CAAC,YAAY;AACxD,UAAM,IAAI,QAAQ,KAAK,MAAM,EAAE,SAAS,SAAS;AAAA,EAAA,CAClD;AAEK,QAAA,mBAAmB,KAAK,QAAQ,OAAO;AAEtC,SAAA;AACT;AAKA,eAAsB,WACpB,gBACkC;;AAClC,QAAM,UAAU,MAAM,eAAe,QAAQ,MAAM;AAAA,IACjD;AAAA,EACF;AAEM,QAAA,EAAE,YAAY;AAEhB,MAAA;AACO,6CAAA,WAAA,mBAAQ,UAAU,SAAS;AAAA,MAClC,GAAG;AAAA,MACH;AAAA,IAAA;AAGF,UAAM,CAAC,UAAU,UAAU,aAAa,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC5D,aAAQ,QAAQ,gBAAhB,mBAA6B,mBAAkB,SAC3CC,iBAAAA,gBAAgB,OAAO,IACvBC,iBAAA,eAAe,OAAO;AAAA,MAC1BC,mBAAAA,iBAAgB,wCAAS,YAAT,mBAAkB,QAAQ,WAAW;AAAA,MACrD,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,yBAAqB,CAAA,EAAE,KAAK,CAAAC,YAAUA,QAAO,aAAa;AAAA,IAAA,CAClE;AAEMC,kBAAA,MAAM,qBAAqB,QAAQ;AAEtC,QAAA,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,yBAAyB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,MACjE;AAAA,IAAA;AAGF,UAAM,SAAS,cAAe,MAAM,SAAS,MAAkB;AACxDA,kBAAA,MAAM,aAAa,MAAM;AAE5B,QAAA,SAAS,SAAS,GAAG;AAChBA,aAAAA,OAAA;AAAA,QACL,SAAS,SAAS,MAAM,IACtB,SAAS,WAAW,IAAI,YAAY,UACtC;AAAA,QACA;AAAA,MACF;AAAA,IAAA;AAGF,UAAM,kBAAmC,CAAC;AAC1C,eAAW,CAAG,EAAA,KAAK,KAAK,QAAQ,MAAM,WAAW;AACzC,YAAA,KAAK,OAAO,KAAK,CAAC,EAAE,eAAe,aAAa,MAAM,IAAI;AAChE,YAAM,YAAY,SAAS;AAAA,QACzB,CAAA,YAAW,QAAQ,WAAW,MAAM;AAAA,MACtC;AACA,UAAI,MAAM,WAAW;AACnB,cAAM,SAAS,aAAa;AAC5B,wBAAgB,KAAK;AAAA,UACnB,GAAG;AAAA,UACH,UAAU,MAAM;AAAA,QAAA,CACL;AAAA,MAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"requestAds.cjs","sources":["../../../src/requestAds/requestAds.ts"],"sourcesContent":["import type { AdheseContext } from '../main.types';\nimport type { AdheseAd } from './requestAds.schema';\nimport { debounce } from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { requestPreviews } from './requestAds.preview';\nimport { requestWithGet, requestWithPost } from './requestAds.utils';\n\nexport type AdRequestOptions = {\n /**\n * Slot you want to fetch the ad for\n */\n slot: {\n name: string;\n parameters: Map<string, ReadonlyArray<string> | string>;\n };\n context: AdheseContext;\n};\n\nexport type AdMultiRequestOptions = Omit<AdRequestOptions, 'slot'> & {\n slots: ReadonlyArray<AdRequestOptions['slot']>;\n};\n\nconst batch = new Map<\n string,\n {\n options: AdRequestOptions;\n resolve(ad: AdheseAd | null): void;\n }\n>();\n\n/**\n * Debounced function to request ads in batches. This function is debounced to prevent multiple requests for the same ad.\n */\nconst runRequestAdsBatch = debounce(\n async (context: AdheseContext) => {\n if (batch.size === 0)\n return [];\n\n const ads = await requestAds({\n slots: Array.from(batch.values()).map(({ options }) => options.slot),\n context,\n });\n\n for (const { options, resolve } of batch.values()) {\n const ad = ads.find(({ slotName }) => slotName === options.slot.name);\n\n if (ad)\n resolve(ad);\n else resolve(null);\n }\n\n batch.clear();\n return ads;\n },\n {\n waitMs: 200,\n timing: 'trailing',\n },\n);\n\n/**\n * Request a single ad from the API. If you need to fetch multiple ads at once use the `requestAds` function.\n */\nexport async function requestAd(\n options: AdRequestOptions,\n): Promise<AdheseAd | null> {\n const promise = new Promise<AdheseAd | null>((resolve) => {\n batch.set(options.slot.name, { options, resolve });\n });\n\n await runRequestAdsBatch.call(options.context);\n\n return promise;\n}\n\n/**\n * Request multiple ads from the API. If you need to fetch a single ad use the `requestAd` function.\n */\nexport async function requestAds(\n requestOptions: AdMultiRequestOptions,\n): Promise<ReadonlyArray<AdheseAd>> {\n const options = await requestOptions.context.hooks.runOnRequest(\n requestOptions,\n );\n\n const { context } = options;\n\n try {\n context?.events?.requestAd.dispatch({\n ...options,\n context,\n });\n\n const [response, previews, parseResponse] = await Promise.all([\n context.options.requestType?.toUpperCase() === 'POST'\n ? requestWithPost(options)\n : requestWithGet(options),\n requestPreviews(options?.context?.options.previewHost),\n import('./requestAds.schema').then(module => module.parseResponse),\n ]);\n\n logger.debug('Received response', response);\n\n if (!response.ok) {\n throw new Error(\n `Failed to request ad: ${response.status} ${response.statusText}`,\n );\n }\n\n const result = parseResponse((await response.json()) as unknown);\n logger.debug('Parsed ad', result);\n\n if (previews.length > 0) {\n logger.info(\n `Found ${previews.length} ${\n previews.length === 1 ? 'preview' : 'previews'\n }. Replacing ads in response with preview items`,\n previews,\n );\n }\n\n const matchedPreviews: Array<AdheseAd> = [];\n for (const [, value] of context.slots.entries()) {\n const ad = result.find(({ slotName }) => slotName === value.name);\n const partnerAd = previews.find(\n preview => preview.adType === value.format,\n );\n if (ad || partnerAd) {\n const baseAd = partnerAd ?? ad;\n matchedPreviews.push({\n ...baseAd,\n slotName: value.name,\n } as AdheseAd);\n }\n else {\n value.processOnEmpty();\n }\n }\n\n if (matchedPreviews.length > 0)\n context.events?.previewReceived.dispatch(matchedPreviews);\n\n const mergedResult = await context.hooks.runOnResponse(matchedPreviews);\n\n context.events?.responseReceived.dispatch(mergedResult);\n\n return mergedResult;\n }\n catch (error) {\n logger.error(String(error));\n context?.events?.requestError.dispatch(error as Error);\n\n throw error;\n }\n}\n"],"names":["debounce","requestWithPost","requestWithGet","requestPreviews","module","logger"],"mappings":"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"}
|
package/dist/cjs/slot/slot.cjs
CHANGED
|
@@ -225,9 +225,6 @@ function createSlot(slotOptions) {
|
|
|
225
225
|
return null;
|
|
226
226
|
}
|
|
227
227
|
if (!renderAd) {
|
|
228
|
-
status.value = "empty";
|
|
229
|
-
logger.logger.debug(`No ad to render for slot ${name.value}`);
|
|
230
|
-
runOnEmpty();
|
|
231
228
|
return null;
|
|
232
229
|
}
|
|
233
230
|
if (typeof (renderAd == null ? void 0 : renderAd.tag) !== "string" && renderMode !== "none") {
|
|
@@ -257,6 +254,11 @@ function createSlot(slotOptions) {
|
|
|
257
254
|
return null;
|
|
258
255
|
}
|
|
259
256
|
}
|
|
257
|
+
function processOnEmpty() {
|
|
258
|
+
status.value = "empty";
|
|
259
|
+
logger.logger.debug(`No ad to render for slot ${name.value}`);
|
|
260
|
+
runOnEmpty();
|
|
261
|
+
}
|
|
260
262
|
function cleanElement() {
|
|
261
263
|
if (!element.value || renderMode === "none")
|
|
262
264
|
return;
|
|
@@ -293,6 +295,7 @@ function createSlot(slotOptions) {
|
|
|
293
295
|
render,
|
|
294
296
|
request,
|
|
295
297
|
dispose,
|
|
298
|
+
processOnEmpty,
|
|
296
299
|
cleanElement,
|
|
297
300
|
options: sdkShared.omit(options, ["context"]),
|
|
298
301
|
...hooks
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot.cjs","sources":["../../../src/slot/slot.ts"],"sourcesContent":["import type { AdheseAd } from '@adhese/sdk';\nimport type { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } 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<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\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(Object.entries(slotOptions).filter(([, value]) => value !== undefined)) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n renderMode = 'iframe',\n type = 'normal',\n } = 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 ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(new Map(Object.entries(options.parameters ?? {})));\n\n const [device, disposeQueryDetector] = useQueryDetector(context, typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(options.format.map(item => [item.format, item.query])));\n\n const format = computed(() => typeof options.format === 'string' ? options.format : device.value);\n\n const data = ref<AdheseAd | null>(null) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const name = computed(() => generateName(options.context.location, format.value, options.slot));\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 (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(`#${options.containingElement}`);\n }\n\n watch(element, async (newElement, oldElement) => {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'loading') {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (newElement === oldElement || (oldElement === null && newElement === null))\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(isInViewport, async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered')\n await slotContext.value?.render();\n }, { immediate: true });\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 }\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 watch([status, isInViewport, data], ([newStatus, newIsInViewport, newData]) => {\n if (newStatus === 'rendered' && newIsInViewport) {\n if (newData?.impressionCounter && !impressionTrackingPixelElement.value) {\n impressionTrackingPixelElement.value = addTrackingPixel(newData.impressionCounter);\n isImpressionTracked.value = true;\n }\n if (newData?.additionalTracker && !additionalTrackingPixelElement.value) {\n additionalTrackingPixelElement.value = addTrackingPixel(newData.additionalTracker);\n isAdditionalTracked.value = true;\n }\n }\n }, { immediate: true });\n watch(status, async (newStatus, oldStatus) => {\n if (newStatus === 'loaded' && oldStatus === 'rendered') {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = null;\n additionalTrackingPixelElement.value?.remove();\n additionalTrackingPixelElement.value = null;\n }\n });\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n if (additionalTrackingPixelElement.value)\n additionalTrackingPixelElement.value.remove();\n });\n\n async function request(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\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 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 status.value = 'error';\n\n logger.error(`Error requesting ad for slot ${name.value}`, error);\n\n runOnError(new Error(`Error requesting ad for slot ${name.value}`, { cause: error }));\n\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'initializing') {\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 let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(`Could not render slot for format ${format.value}. No element found.`, slotContext.value);\n\n return null;\n }\n\n if (!renderAd) {\n // eslint-disable-next-line require-atomic-updates\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n\n runOnEmpty();\n\n return null;\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 logger.error(error, options);\n\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode]({\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions, element.value);\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 // eslint-disable-next-line require-atomic-updates\n status.value = 'error';\n\n logger.error(`${error}`, options);\n\n runOnError(new Error(error as string));\n\n return null;\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 status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(state, (newState) => {\n slotContext.value = newState;\n }, {\n deep: true,\n immediate: true,\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\n data.value = initialData;\n data.value = await runOnRequest(initialData);\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","logger","waitForDomLoad","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 { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } 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<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\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(Object.entries(slotOptions).filter(([, value]) => value !== undefined)) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n renderMode = 'iframe',\n type = 'normal',\n } = 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 ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(new Map(Object.entries(options.parameters ?? {})));\n\n const [device, disposeQueryDetector] = useQueryDetector(context, typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(options.format.map(item => [item.format, item.query])));\n\n const format = computed(() => typeof options.format === 'string' ? options.format : device.value);\n\n const data = ref<AdheseAd | null>(null) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const name = computed(() => generateName(options.context.location, format.value, options.slot));\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 (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(`#${options.containingElement}`);\n }\n\n watch(element, async (newElement, oldElement) => {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'loading') {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (newElement === oldElement || (oldElement === null && newElement === null))\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(isInViewport, async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered')\n await slotContext.value?.render();\n }, { immediate: true });\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 }\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 watch([status, isInViewport, data], ([newStatus, newIsInViewport, newData]) => {\n if (newStatus === 'rendered' && newIsInViewport) {\n if (newData?.impressionCounter && !impressionTrackingPixelElement.value) {\n impressionTrackingPixelElement.value = addTrackingPixel(newData.impressionCounter);\n isImpressionTracked.value = true;\n }\n if (newData?.additionalTracker && !additionalTrackingPixelElement.value) {\n additionalTrackingPixelElement.value = addTrackingPixel(newData.additionalTracker);\n isAdditionalTracked.value = true;\n }\n }\n }, { immediate: true });\n watch(status, async (newStatus, oldStatus) => {\n if (newStatus === 'loaded' && oldStatus === 'rendered') {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = null;\n additionalTrackingPixelElement.value?.remove();\n additionalTrackingPixelElement.value = null;\n }\n });\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n if (additionalTrackingPixelElement.value)\n additionalTrackingPixelElement.value.remove();\n });\n\n async function request(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\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 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 status.value = 'error';\n\n logger.error(`Error requesting ad for slot ${name.value}`, error);\n\n runOnError(new Error(`Error requesting ad for slot ${name.value}`, { cause: error }));\n\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'initializing') {\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 let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(`Could not render slot for format ${format.value}. No element found.`, slotContext.value);\n\n return null;\n }\n\n if (!renderAd) {\n return null;\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 logger.error(error, options);\n\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode]({\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions, element.value);\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 // eslint-disable-next-line require-atomic-updates\n status.value = 'error';\n\n logger.error(`${error}`, options);\n\n runOnError(new Error(error as string));\n\n return null;\n }\n }\n\n function processOnEmpty(): void {\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n runOnEmpty();\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 status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n processOnEmpty,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(state, (newState) => {\n slotContext.value = newState;\n }, {\n deep: true,\n immediate: true,\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\n data.value = initialData;\n data.value = await runOnRequest(initialData);\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","logger","waitForDomLoad","pick","omit"],"mappings":"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"}
|
package/dist/package.json.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requestAds.js","sources":["../../src/requestAds/requestAds.ts"],"sourcesContent":["import type { AdheseContext } from '../main.types';\nimport type { AdheseAd } from './requestAds.schema';\nimport { debounce } from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { requestPreviews } from './requestAds.preview';\nimport { requestWithGet, requestWithPost } from './requestAds.utils';\n\nexport type AdRequestOptions = {\n /**\n * Slot you want to fetch the ad for\n */\n slot: {\n name: string;\n parameters: Map<string, ReadonlyArray<string> | string>;\n };\n context: AdheseContext;\n};\n\nexport type AdMultiRequestOptions = Omit<AdRequestOptions, 'slot'> & {\n slots: ReadonlyArray<AdRequestOptions['slot']>;\n};\n\nconst batch = new Map<\n string,\n {\n options: AdRequestOptions;\n resolve(ad: AdheseAd | null): void;\n }\n>();\n\n/**\n * Debounced function to request ads in batches. This function is debounced to prevent multiple requests for the same ad.\n */\nconst runRequestAdsBatch = debounce(\n async (context: AdheseContext) => {\n if (batch.size === 0)\n return [];\n\n const ads = await requestAds({\n slots: Array.from(batch.values()).map(({ options }) => options.slot),\n context,\n });\n\n for (const { options, resolve } of batch.values()) {\n const ad = ads.find(({ slotName }) => slotName === options.slot.name);\n\n if (ad)\n resolve(ad);\n else resolve(null);\n }\n\n batch.clear();\n return ads;\n },\n {\n waitMs: 200,\n timing: 'trailing',\n },\n);\n\n/**\n * Request a single ad from the API. If you need to fetch multiple ads at once use the `requestAds` function.\n */\nexport async function requestAd(\n options: AdRequestOptions,\n): Promise<AdheseAd | null> {\n const promise = new Promise<AdheseAd | null>((resolve) => {\n batch.set(options.slot.name, { options, resolve });\n });\n\n await runRequestAdsBatch.call(options.context);\n\n return promise;\n}\n\n/**\n * Request multiple ads from the API. If you need to fetch a single ad use the `requestAd` function.\n */\nexport async function requestAds(\n requestOptions: AdMultiRequestOptions,\n): Promise<ReadonlyArray<AdheseAd>> {\n const options = await requestOptions.context.hooks.runOnRequest(\n requestOptions,\n );\n\n const { context } = options;\n\n try {\n context?.events?.requestAd.dispatch({\n ...options,\n context,\n });\n\n const [response, previews, parseResponse] = await Promise.all([\n context.options.requestType?.toUpperCase() === 'POST'\n ? requestWithPost(options)\n : requestWithGet(options),\n requestPreviews(options?.context?.options.previewHost),\n import('./requestAds.schema').then(module => module.parseResponse),\n ]);\n\n logger.debug('Received response', response);\n\n if (!response.ok) {\n throw new Error(\n `Failed to request ad: ${response.status} ${response.statusText}`,\n );\n }\n\n const result = parseResponse((await response.json()) as unknown);\n logger.debug('Parsed ad', result);\n\n if (previews.length > 0) {\n logger.info(\n `Found ${previews.length} ${\n previews.length === 1 ? 'preview' : 'previews'\n }. Replacing ads in response with preview items`,\n previews,\n );\n }\n\n const matchedPreviews: Array<AdheseAd> = [];\n for (const [, value] of context.slots.entries()) {\n const ad = result.find(({ slotName }) => slotName === value.name);\n const partnerAd = previews.find(\n preview => preview.adType === value.format,\n );\n if (ad || partnerAd) {\n const baseAd = partnerAd ?? ad;\n matchedPreviews.push({\n ...baseAd,\n slotName: value.name,\n } as AdheseAd);\n }\n }\n\n if (matchedPreviews.length > 0)\n context.events?.previewReceived.dispatch(matchedPreviews);\n\n const mergedResult = await context.hooks.runOnResponse(matchedPreviews);\n\n context.events?.responseReceived.dispatch(mergedResult);\n\n return mergedResult;\n }\n catch (error) {\n logger.error(String(error));\n context?.events?.requestError.dispatch(error as Error);\n\n throw error;\n }\n}\n"],"names":[],"mappings":";;;;AAsBA,MAAM,4BAAY,IAMhB;AAKF,MAAM,qBAAqB;AAAA,EACzB,OAAO,YAA2B;AAChC,QAAI,MAAM,SAAS;AACjB,aAAO,CAAC;AAEJ,UAAA,MAAM,MAAM,WAAW;AAAA,MAC3B,OAAO,MAAM,KAAK,MAAM,OAAQ,CAAA,EAAE,IAAI,CAAC,EAAE,cAAc,QAAQ,IAAI;AAAA,MACnE;AAAA,IAAA,CACD;AAED,eAAW,EAAE,SAAS,QAAa,KAAA,MAAM,UAAU;AAC3C,YAAA,KAAK,IAAI,KAAK,CAAC,EAAE,SAAe,MAAA,aAAa,QAAQ,KAAK,IAAI;AAEhE,UAAA;AACF,gBAAQ,EAAE;AAAA,mBACC,IAAI;AAAA,IAAA;AAGnB,UAAM,MAAM;AACL,WAAA;AAAA,EACT;AAAA,EACA;AAAA,IACE,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA;AAEZ;AAKA,eAAsB,UACpB,SAC0B;AAC1B,QAAM,UAAU,IAAI,QAAyB,CAAC,YAAY;AACxD,UAAM,IAAI,QAAQ,KAAK,MAAM,EAAE,SAAS,SAAS;AAAA,EAAA,CAClD;AAEK,QAAA,mBAAmB,KAAK,QAAQ,OAAO;AAEtC,SAAA;AACT;AAKA,eAAsB,WACpB,gBACkC;;AAClC,QAAM,UAAU,MAAM,eAAe,QAAQ,MAAM;AAAA,IACjD;AAAA,EACF;AAEM,QAAA,EAAE,YAAY;AAEhB,MAAA;AACO,6CAAA,WAAA,mBAAQ,UAAU,SAAS;AAAA,MAClC,GAAG;AAAA,MACH;AAAA,IAAA;AAGF,UAAM,CAAC,UAAU,UAAU,aAAa,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC5D,aAAQ,QAAQ,gBAAhB,mBAA6B,mBAAkB,SAC3C,gBAAgB,OAAO,IACvB,eAAe,OAAO;AAAA,MAC1B,iBAAgB,wCAAS,YAAT,mBAAkB,QAAQ,WAAW;AAAA,MACrD,OAAO,wBAAqB,EAAE,KAAK,CAAA,WAAU,OAAO,aAAa;AAAA,IAAA,CAClE;AAEM,WAAA,MAAM,qBAAqB,QAAQ;AAEtC,QAAA,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,yBAAyB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,MACjE;AAAA,IAAA;AAGF,UAAM,SAAS,cAAe,MAAM,SAAS,MAAkB;AACxD,WAAA,MAAM,aAAa,MAAM;AAE5B,QAAA,SAAS,SAAS,GAAG;AAChB,aAAA;AAAA,QACL,SAAS,SAAS,MAAM,IACtB,SAAS,WAAW,IAAI,YAAY,UACtC;AAAA,QACA;AAAA,MACF;AAAA,IAAA;AAGF,UAAM,kBAAmC,CAAC;AAC1C,eAAW,CAAG,EAAA,KAAK,KAAK,QAAQ,MAAM,WAAW;AACzC,YAAA,KAAK,OAAO,KAAK,CAAC,EAAE,eAAe,aAAa,MAAM,IAAI;AAChE,YAAM,YAAY,SAAS;AAAA,QACzB,CAAA,YAAW,QAAQ,WAAW,MAAM;AAAA,MACtC;AACA,UAAI,MAAM,WAAW;AACnB,cAAM,SAAS,aAAa;AAC5B,wBAAgB,KAAK;AAAA,UACnB,GAAG;AAAA,UACH,UAAU,MAAM;AAAA,QAAA,CACL;AAAA,MAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"requestAds.js","sources":["../../src/requestAds/requestAds.ts"],"sourcesContent":["import type { AdheseContext } from '../main.types';\nimport type { AdheseAd } from './requestAds.schema';\nimport { debounce } from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { requestPreviews } from './requestAds.preview';\nimport { requestWithGet, requestWithPost } from './requestAds.utils';\n\nexport type AdRequestOptions = {\n /**\n * Slot you want to fetch the ad for\n */\n slot: {\n name: string;\n parameters: Map<string, ReadonlyArray<string> | string>;\n };\n context: AdheseContext;\n};\n\nexport type AdMultiRequestOptions = Omit<AdRequestOptions, 'slot'> & {\n slots: ReadonlyArray<AdRequestOptions['slot']>;\n};\n\nconst batch = new Map<\n string,\n {\n options: AdRequestOptions;\n resolve(ad: AdheseAd | null): void;\n }\n>();\n\n/**\n * Debounced function to request ads in batches. This function is debounced to prevent multiple requests for the same ad.\n */\nconst runRequestAdsBatch = debounce(\n async (context: AdheseContext) => {\n if (batch.size === 0)\n return [];\n\n const ads = await requestAds({\n slots: Array.from(batch.values()).map(({ options }) => options.slot),\n context,\n });\n\n for (const { options, resolve } of batch.values()) {\n const ad = ads.find(({ slotName }) => slotName === options.slot.name);\n\n if (ad)\n resolve(ad);\n else resolve(null);\n }\n\n batch.clear();\n return ads;\n },\n {\n waitMs: 200,\n timing: 'trailing',\n },\n);\n\n/**\n * Request a single ad from the API. If you need to fetch multiple ads at once use the `requestAds` function.\n */\nexport async function requestAd(\n options: AdRequestOptions,\n): Promise<AdheseAd | null> {\n const promise = new Promise<AdheseAd | null>((resolve) => {\n batch.set(options.slot.name, { options, resolve });\n });\n\n await runRequestAdsBatch.call(options.context);\n\n return promise;\n}\n\n/**\n * Request multiple ads from the API. If you need to fetch a single ad use the `requestAd` function.\n */\nexport async function requestAds(\n requestOptions: AdMultiRequestOptions,\n): Promise<ReadonlyArray<AdheseAd>> {\n const options = await requestOptions.context.hooks.runOnRequest(\n requestOptions,\n );\n\n const { context } = options;\n\n try {\n context?.events?.requestAd.dispatch({\n ...options,\n context,\n });\n\n const [response, previews, parseResponse] = await Promise.all([\n context.options.requestType?.toUpperCase() === 'POST'\n ? requestWithPost(options)\n : requestWithGet(options),\n requestPreviews(options?.context?.options.previewHost),\n import('./requestAds.schema').then(module => module.parseResponse),\n ]);\n\n logger.debug('Received response', response);\n\n if (!response.ok) {\n throw new Error(\n `Failed to request ad: ${response.status} ${response.statusText}`,\n );\n }\n\n const result = parseResponse((await response.json()) as unknown);\n logger.debug('Parsed ad', result);\n\n if (previews.length > 0) {\n logger.info(\n `Found ${previews.length} ${\n previews.length === 1 ? 'preview' : 'previews'\n }. Replacing ads in response with preview items`,\n previews,\n );\n }\n\n const matchedPreviews: Array<AdheseAd> = [];\n for (const [, value] of context.slots.entries()) {\n const ad = result.find(({ slotName }) => slotName === value.name);\n const partnerAd = previews.find(\n preview => preview.adType === value.format,\n );\n if (ad || partnerAd) {\n const baseAd = partnerAd ?? ad;\n matchedPreviews.push({\n ...baseAd,\n slotName: value.name,\n } as AdheseAd);\n }\n else {\n value.processOnEmpty();\n }\n }\n\n if (matchedPreviews.length > 0)\n context.events?.previewReceived.dispatch(matchedPreviews);\n\n const mergedResult = await context.hooks.runOnResponse(matchedPreviews);\n\n context.events?.responseReceived.dispatch(mergedResult);\n\n return mergedResult;\n }\n catch (error) {\n logger.error(String(error));\n context?.events?.requestError.dispatch(error as Error);\n\n throw error;\n }\n}\n"],"names":[],"mappings":";;;;AAsBA,MAAM,4BAAY,IAMhB;AAKF,MAAM,qBAAqB;AAAA,EACzB,OAAO,YAA2B;AAChC,QAAI,MAAM,SAAS;AACjB,aAAO,CAAC;AAEJ,UAAA,MAAM,MAAM,WAAW;AAAA,MAC3B,OAAO,MAAM,KAAK,MAAM,OAAQ,CAAA,EAAE,IAAI,CAAC,EAAE,cAAc,QAAQ,IAAI;AAAA,MACnE;AAAA,IAAA,CACD;AAED,eAAW,EAAE,SAAS,QAAa,KAAA,MAAM,UAAU;AAC3C,YAAA,KAAK,IAAI,KAAK,CAAC,EAAE,SAAe,MAAA,aAAa,QAAQ,KAAK,IAAI;AAEhE,UAAA;AACF,gBAAQ,EAAE;AAAA,mBACC,IAAI;AAAA,IAAA;AAGnB,UAAM,MAAM;AACL,WAAA;AAAA,EACT;AAAA,EACA;AAAA,IACE,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA;AAEZ;AAKA,eAAsB,UACpB,SAC0B;AAC1B,QAAM,UAAU,IAAI,QAAyB,CAAC,YAAY;AACxD,UAAM,IAAI,QAAQ,KAAK,MAAM,EAAE,SAAS,SAAS;AAAA,EAAA,CAClD;AAEK,QAAA,mBAAmB,KAAK,QAAQ,OAAO;AAEtC,SAAA;AACT;AAKA,eAAsB,WACpB,gBACkC;;AAClC,QAAM,UAAU,MAAM,eAAe,QAAQ,MAAM;AAAA,IACjD;AAAA,EACF;AAEM,QAAA,EAAE,YAAY;AAEhB,MAAA;AACO,6CAAA,WAAA,mBAAQ,UAAU,SAAS;AAAA,MAClC,GAAG;AAAA,MACH;AAAA,IAAA;AAGF,UAAM,CAAC,UAAU,UAAU,aAAa,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC5D,aAAQ,QAAQ,gBAAhB,mBAA6B,mBAAkB,SAC3C,gBAAgB,OAAO,IACvB,eAAe,OAAO;AAAA,MAC1B,iBAAgB,wCAAS,YAAT,mBAAkB,QAAQ,WAAW;AAAA,MACrD,OAAO,wBAAqB,EAAE,KAAK,CAAA,WAAU,OAAO,aAAa;AAAA,IAAA,CAClE;AAEM,WAAA,MAAM,qBAAqB,QAAQ;AAEtC,QAAA,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,yBAAyB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,MACjE;AAAA,IAAA;AAGF,UAAM,SAAS,cAAe,MAAM,SAAS,MAAkB;AACxD,WAAA,MAAM,aAAa,MAAM;AAE5B,QAAA,SAAS,SAAS,GAAG;AAChB,aAAA;AAAA,QACL,SAAS,SAAS,MAAM,IACtB,SAAS,WAAW,IAAI,YAAY,UACtC;AAAA,QACA;AAAA,MACF;AAAA,IAAA;AAGF,UAAM,kBAAmC,CAAC;AAC1C,eAAW,CAAG,EAAA,KAAK,KAAK,QAAQ,MAAM,WAAW;AACzC,YAAA,KAAK,OAAO,KAAK,CAAC,EAAE,eAAe,aAAa,MAAM,IAAI;AAChE,YAAM,YAAY,SAAS;AAAA,QACzB,CAAA,YAAW,QAAQ,WAAW,MAAM;AAAA,MACtC;AACA,UAAI,MAAM,WAAW;AACnB,cAAM,SAAS,aAAa;AAC5B,wBAAgB,KAAK;AAAA,UACnB,GAAG;AAAA,UACH,UAAU,MAAM;AAAA,QAAA,CACL;AAAA,MAAA,OAEV;AACH,cAAM,eAAe;AAAA,MAAA;AAAA,IACvB;AAGF,QAAI,gBAAgB,SAAS;AACnB,oBAAA,WAAA,mBAAQ,gBAAgB,SAAS;AAE3C,UAAM,eAAe,MAAM,QAAQ,MAAM,cAAc,eAAe;AAE9D,kBAAA,WAAA,mBAAQ,iBAAiB,SAAS;AAEnC,WAAA;AAAA,WAEF,OAAO;AACL,WAAA,MAAM,OAAO,KAAK,CAAC;AACjB,6CAAA,WAAA,mBAAQ,aAAa,SAAS;AAEjC,UAAA;AAAA,EAAA;AAEV;"}
|
package/dist/slot/slot.js
CHANGED
|
@@ -223,9 +223,6 @@ function createSlot(slotOptions) {
|
|
|
223
223
|
return null;
|
|
224
224
|
}
|
|
225
225
|
if (!renderAd) {
|
|
226
|
-
status.value = "empty";
|
|
227
|
-
logger.debug(`No ad to render for slot ${name.value}`);
|
|
228
|
-
runOnEmpty();
|
|
229
226
|
return null;
|
|
230
227
|
}
|
|
231
228
|
if (typeof (renderAd == null ? void 0 : renderAd.tag) !== "string" && renderMode !== "none") {
|
|
@@ -255,6 +252,11 @@ function createSlot(slotOptions) {
|
|
|
255
252
|
return null;
|
|
256
253
|
}
|
|
257
254
|
}
|
|
255
|
+
function processOnEmpty() {
|
|
256
|
+
status.value = "empty";
|
|
257
|
+
logger.debug(`No ad to render for slot ${name.value}`);
|
|
258
|
+
runOnEmpty();
|
|
259
|
+
}
|
|
258
260
|
function cleanElement() {
|
|
259
261
|
if (!element.value || renderMode === "none")
|
|
260
262
|
return;
|
|
@@ -291,6 +293,7 @@ function createSlot(slotOptions) {
|
|
|
291
293
|
render,
|
|
292
294
|
request,
|
|
293
295
|
dispose,
|
|
296
|
+
processOnEmpty,
|
|
294
297
|
cleanElement,
|
|
295
298
|
options: omit(options, ["context"]),
|
|
296
299
|
...hooks
|
package/dist/slot/slot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot.js","sources":["../../src/slot/slot.ts"],"sourcesContent":["import type { AdheseAd } from '@adhese/sdk';\nimport type { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } 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<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\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(Object.entries(slotOptions).filter(([, value]) => value !== undefined)) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n renderMode = 'iframe',\n type = 'normal',\n } = 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 ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(new Map(Object.entries(options.parameters ?? {})));\n\n const [device, disposeQueryDetector] = useQueryDetector(context, typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(options.format.map(item => [item.format, item.query])));\n\n const format = computed(() => typeof options.format === 'string' ? options.format : device.value);\n\n const data = ref<AdheseAd | null>(null) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const name = computed(() => generateName(options.context.location, format.value, options.slot));\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 (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(`#${options.containingElement}`);\n }\n\n watch(element, async (newElement, oldElement) => {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'loading') {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (newElement === oldElement || (oldElement === null && newElement === null))\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(isInViewport, async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered')\n await slotContext.value?.render();\n }, { immediate: true });\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 }\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 watch([status, isInViewport, data], ([newStatus, newIsInViewport, newData]) => {\n if (newStatus === 'rendered' && newIsInViewport) {\n if (newData?.impressionCounter && !impressionTrackingPixelElement.value) {\n impressionTrackingPixelElement.value = addTrackingPixel(newData.impressionCounter);\n isImpressionTracked.value = true;\n }\n if (newData?.additionalTracker && !additionalTrackingPixelElement.value) {\n additionalTrackingPixelElement.value = addTrackingPixel(newData.additionalTracker);\n isAdditionalTracked.value = true;\n }\n }\n }, { immediate: true });\n watch(status, async (newStatus, oldStatus) => {\n if (newStatus === 'loaded' && oldStatus === 'rendered') {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = null;\n additionalTrackingPixelElement.value?.remove();\n additionalTrackingPixelElement.value = null;\n }\n });\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n if (additionalTrackingPixelElement.value)\n additionalTrackingPixelElement.value.remove();\n });\n\n async function request(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\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 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 status.value = 'error';\n\n logger.error(`Error requesting ad for slot ${name.value}`, error);\n\n runOnError(new Error(`Error requesting ad for slot ${name.value}`, { cause: error }));\n\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'initializing') {\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 let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(`Could not render slot for format ${format.value}. No element found.`, slotContext.value);\n\n return null;\n }\n\n if (!renderAd) {\n // eslint-disable-next-line require-atomic-updates\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n\n runOnEmpty();\n\n return null;\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 logger.error(error, options);\n\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode]({\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions, element.value);\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 // eslint-disable-next-line require-atomic-updates\n status.value = 'error';\n\n logger.error(`${error}`, options);\n\n runOnError(new Error(error as string));\n\n return null;\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 status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(state, (newState) => {\n slotContext.value = newState;\n }, {\n deep: true,\n immediate: true,\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\n data.value = initialData;\n data.value = await runOnRequest(initialData);\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 { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } 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<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\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(Object.entries(slotOptions).filter(([, value]) => value !== undefined)) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n renderMode = 'iframe',\n type = 'normal',\n } = 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 ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(new Map(Object.entries(options.parameters ?? {})));\n\n const [device, disposeQueryDetector] = useQueryDetector(context, typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(options.format.map(item => [item.format, item.query])));\n\n const format = computed(() => typeof options.format === 'string' ? options.format : device.value);\n\n const data = ref<AdheseAd | null>(null) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const name = computed(() => generateName(options.context.location, format.value, options.slot));\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 (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(`#${options.containingElement}`);\n }\n\n watch(element, async (newElement, oldElement) => {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'loading') {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (newElement === oldElement || (oldElement === null && newElement === null))\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(isInViewport, async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered')\n await slotContext.value?.render();\n }, { immediate: true });\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 }\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 watch([status, isInViewport, data], ([newStatus, newIsInViewport, newData]) => {\n if (newStatus === 'rendered' && newIsInViewport) {\n if (newData?.impressionCounter && !impressionTrackingPixelElement.value) {\n impressionTrackingPixelElement.value = addTrackingPixel(newData.impressionCounter);\n isImpressionTracked.value = true;\n }\n if (newData?.additionalTracker && !additionalTrackingPixelElement.value) {\n additionalTrackingPixelElement.value = addTrackingPixel(newData.additionalTracker);\n isAdditionalTracked.value = true;\n }\n }\n }, { immediate: true });\n watch(status, async (newStatus, oldStatus) => {\n if (newStatus === 'loaded' && oldStatus === 'rendered') {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = null;\n additionalTrackingPixelElement.value?.remove();\n additionalTrackingPixelElement.value = null;\n }\n });\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n if (additionalTrackingPixelElement.value)\n additionalTrackingPixelElement.value.remove();\n });\n\n async function request(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\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 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 status.value = 'error';\n\n logger.error(`Error requesting ad for slot ${name.value}`, error);\n\n runOnError(new Error(`Error requesting ad for slot ${name.value}`, { cause: error }));\n\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'initializing') {\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 let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(`Could not render slot for format ${format.value}. No element found.`, slotContext.value);\n\n return null;\n }\n\n if (!renderAd) {\n return null;\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 logger.error(error, options);\n\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode]({\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions, element.value);\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 // eslint-disable-next-line require-atomic-updates\n status.value = 'error';\n\n logger.error(`${error}`, options);\n\n runOnError(new Error(error as string));\n\n return null;\n }\n }\n\n function processOnEmpty(): void {\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n runOnEmpty();\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 status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n processOnEmpty,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(state, (newState) => {\n slotContext.value = newState;\n }, {\n deep: true,\n immediate: true,\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\n data.value = initialData;\n data.value = await runOnRequest(initialData);\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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"}
|