@adhese/sdk 0.21.0 → 0.22.0
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 +12 -0
- package/dist/cjs/package.json.cjs +1 -1
- package/dist/cjs/slot/slot.cjs +1 -0
- package/dist/cjs/slot/slot.cjs.map +1 -1
- package/dist/index.d.ts +666 -0
- package/dist/package.json.js +1 -1
- package/dist/slot/slot.js +1 -0
- package/dist/slot/slot.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -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 = "0.
|
|
4
|
+
const version = "0.22.0";
|
|
5
5
|
exports.name = name;
|
|
6
6
|
exports.version = version;
|
|
7
7
|
//# sourceMappingURL=package.json.cjs.map
|
package/dist/cjs/slot/slot.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot.cjs","sources":["../../../src/slot/slot.ts"],"sourcesContent":["import {\n type Ref,\n type UnwrapRef,\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n isDeepEqual,\n omit,\n reactive,\n ref,\n uniqueId,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport type { AdheseAd } from '@adhese/sdk';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport type { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } from './slot.types';\nimport { renderIframe, renderInline } from './slot.utils';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<RenderMode, (ad: AdheseAd, 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 ...slotOptions,\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\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 ...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 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 = computed(() => {\n if (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value || slotContext.value?.isDisposed)\n return null;\n\n return document.querySelector<HTMLElement>(`.adunit[data-format=\"${format.value}\"]#${options.containingElement}${options.slot ? `[data-slot=\"${options.slot}\"]` : ''}`);\n },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch([data, isInViewport], async ([newData, newIsInViewport], [oldData]) => {\n if ((!newData || (oldData && isDeepEqual(newData, oldData))) && status.value === 'rendered')\n return;\n\n if (newIsInViewport)\n await slotContext.value?.render(newData ?? undefined);\n });\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n if (slotContext.value?.data?.viewableImpressionCounter) {\n trackingPixel.value = addTrackingPixel(slotContext.value?.data?.viewableImpressionCounter);\n\n context.logger.debug(`Viewability tracking pixel fired for ${slotContext.value?.name}`);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n });\n\n async function request(): Promise<AdheseAd | null> {\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 return response;\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n status.value = 'rendering';\n\n await waitForDomLoad();\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!renderAd) {\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n\n return null;\n }\n\n if (!element.value) {\n const error = `Could not create slot for format ${format.value}. No element found.`;\n logger.error(error, options);\n throw new Error(error);\n }\n\n if (context.debug)\n element.value.style.position = 'relative';\n\n if (typeof renderAd?.tag !== 'string') {\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 status.value = 'error';\n throw new Error(error);\n }\n\n renderFunctions[renderMode](renderAd, element.value);\n\n if (renderAd.impressionCounter && !impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value = addTrackingPixel(renderAd.impressionCounter);\n\n isImpressionTracked.value = true;\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 data.value = renderAd;\n\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n\n function cleanElement(): void {\n if (!element.value)\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n element.value.style.width = '';\n element.value.style.height = '';\n\n data.value = null;\n originalData.value = null;\n }\n\n function dispose(): void {\n cleanElement();\n\n data.value = null;\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 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 status.value = 'initialized';\n\n runOnInit();\n\n if (options.lazyLoading)\n return;\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","useRenderIntersectionObserver","isDeepEqual","useViewabilityObserver","addTrackingPixel","extRequestAd","waitForDomLoad","logger","omit"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"slot.cjs","sources":["../../../src/slot/slot.ts"],"sourcesContent":["import {\n type Ref,\n type UnwrapRef,\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n isDeepEqual,\n omit,\n reactive,\n ref,\n uniqueId,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport type { AdheseAd } from '@adhese/sdk';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport type { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } from './slot.types';\nimport { renderIframe, renderInline } from './slot.utils';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<RenderMode, (ad: AdheseAd, 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 ...slotOptions,\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\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 ...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 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 = computed(() => {\n if (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value || slotContext.value?.isDisposed)\n return null;\n\n return document.querySelector<HTMLElement>(`.adunit[data-format=\"${format.value}\"]#${options.containingElement}${options.slot ? `[data-slot=\"${options.slot}\"]` : ''}`);\n },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch([data, isInViewport], async ([newData, newIsInViewport], [oldData]) => {\n if ((!newData || (oldData && isDeepEqual(newData, oldData))) && status.value === 'rendered')\n return;\n\n if (newIsInViewport)\n await slotContext.value?.render(newData ?? undefined);\n });\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n if (slotContext.value?.data?.viewableImpressionCounter) {\n trackingPixel.value = addTrackingPixel(slotContext.value?.data?.viewableImpressionCounter);\n\n context.logger.debug(`Viewability tracking pixel fired for ${slotContext.value?.name}`);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n });\n\n async function request(): Promise<AdheseAd | null> {\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 return response;\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n status.value = 'rendering';\n\n await waitForDomLoad();\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!renderAd) {\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n\n return null;\n }\n\n if (!element.value) {\n const error = `Could not create slot for format ${format.value}. No element found.`;\n logger.error(error, options);\n throw new Error(error);\n }\n\n if (context.debug)\n element.value.style.position = 'relative';\n\n if (typeof renderAd?.tag !== 'string') {\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 status.value = 'error';\n throw new Error(error);\n }\n\n renderFunctions[renderMode](renderAd, element.value);\n\n if (renderAd.impressionCounter && !impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value = addTrackingPixel(renderAd.impressionCounter);\n\n isImpressionTracked.value = true;\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 data.value = renderAd;\n\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n\n function cleanElement(): void {\n if (!element.value)\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n element.value.style.width = '';\n element.value.style.height = '';\n\n data.value = null;\n originalData.value = null;\n }\n\n function dispose(): void {\n cleanElement();\n\n data.value = null;\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 status.value = 'initialized';\n\n runOnInit();\n\n if (options.lazyLoading)\n return;\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","useRenderIntersectionObserver","isDeepEqual","useViewabilityObserver","addTrackingPixel","extRequestAd","waitForDomLoad","logger","omit"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
import * as _adhese_sdk_shared from '@adhese/sdk-shared';
|
|
2
|
+
import { createAsyncHook, createPassiveHook, Ref, Merge, MaybeRef, UrlString, EventManager } from '@adhese/sdk-shared';
|
|
3
|
+
import * as _adhese_sdk_shared_validators from '@adhese/sdk-shared/validators';
|
|
4
|
+
import { TypeOf, ZodType } from '@adhese/sdk-shared/validators';
|
|
5
|
+
|
|
6
|
+
type RenderMode = 'iframe' | 'inline' | 'none';
|
|
7
|
+
type AdheseSlotHooks = {
|
|
8
|
+
/**
|
|
9
|
+
* Hook that is called when the format of the slot changes.
|
|
10
|
+
*/
|
|
11
|
+
onBeforeRender: ReturnType<typeof createAsyncHook<AdheseAd>>[1];
|
|
12
|
+
/**
|
|
13
|
+
* Hook that is called when the slot is rendered.
|
|
14
|
+
*/
|
|
15
|
+
onRender: ReturnType<typeof createPassiveHook<AdheseAd>>[1];
|
|
16
|
+
/**
|
|
17
|
+
* Hook that is called before the slot is requested from the server.
|
|
18
|
+
*/
|
|
19
|
+
onBeforeRequest: ReturnType<typeof createAsyncHook<AdheseAd | null>>[1];
|
|
20
|
+
/**
|
|
21
|
+
* Hook that is called when the slot is requested from the server.
|
|
22
|
+
*/
|
|
23
|
+
onRequest: ReturnType<typeof createAsyncHook<AdheseAd>>[1];
|
|
24
|
+
/**
|
|
25
|
+
* Hook that is called when the slot is initialized.
|
|
26
|
+
*/
|
|
27
|
+
onInit: ReturnType<typeof createPassiveHook>[1];
|
|
28
|
+
/**
|
|
29
|
+
* Hook that is called when the slot is disposed.
|
|
30
|
+
*/
|
|
31
|
+
onDispose: ReturnType<typeof createPassiveHook>[1];
|
|
32
|
+
};
|
|
33
|
+
type AdheseSlotOptions = {
|
|
34
|
+
/**
|
|
35
|
+
* The format code of the slot. Used to find the correct element on the page to render the ad in. If the format is a
|
|
36
|
+
* string, it is used as the format code. If the format is an array, the format code is determined by the query
|
|
37
|
+
* detector.
|
|
38
|
+
*/
|
|
39
|
+
format: string | ReadonlyArray<{
|
|
40
|
+
format: string;
|
|
41
|
+
query: string;
|
|
42
|
+
}>;
|
|
43
|
+
/**
|
|
44
|
+
* Type of the slot. On its own has no effect, but can be used by plugins to create different behavior for different
|
|
45
|
+
* types of slots.
|
|
46
|
+
*/
|
|
47
|
+
type?: string;
|
|
48
|
+
/**
|
|
49
|
+
* If we have multiple slots with the same format, we can use this to differentiate between them.
|
|
50
|
+
*/
|
|
51
|
+
slot?: string;
|
|
52
|
+
/**
|
|
53
|
+
* The element that contains the slot. Used to find the correct element on the page to render the ad in.
|
|
54
|
+
*/
|
|
55
|
+
containingElement?: string | HTMLElement;
|
|
56
|
+
/**
|
|
57
|
+
* The parameters that are used to render the ad.
|
|
58
|
+
*/
|
|
59
|
+
parameters?: Record<string, ReadonlyArray<string> | string>;
|
|
60
|
+
/**
|
|
61
|
+
* The Adhese context
|
|
62
|
+
*/
|
|
63
|
+
context: AdheseContext;
|
|
64
|
+
/**
|
|
65
|
+
* The render mode of the slot.
|
|
66
|
+
*
|
|
67
|
+
* - `iframe`: The ad will be rendered in an iframe.
|
|
68
|
+
* - `inline`: The ad will be rendered in the containing element.
|
|
69
|
+
*
|
|
70
|
+
* @default 'iframe'
|
|
71
|
+
*/
|
|
72
|
+
renderMode?: RenderMode;
|
|
73
|
+
/**
|
|
74
|
+
* Specific options for the slot that may be used my plugins
|
|
75
|
+
*/
|
|
76
|
+
pluginOptions?: Record<string, unknown>;
|
|
77
|
+
/**
|
|
78
|
+
* Special callback that is run when the slot is initialized. It passes the slot context ref object and a special
|
|
79
|
+
* plugin object that contains a set of hooks you can use to hook into different moments of the slots lifecycle.
|
|
80
|
+
*/
|
|
81
|
+
setup?(context: Ref<AdheseSlotContext | null>, hooks: AdheseSlotHooks): void;
|
|
82
|
+
} & ({
|
|
83
|
+
/**
|
|
84
|
+
* If the slot should be lazy loaded. This means that the ad will only be requested when the slot is in the viewport.
|
|
85
|
+
* If `true`, the slot will handle the request itself and render the ad.
|
|
86
|
+
*/
|
|
87
|
+
lazyLoading: true;
|
|
88
|
+
lazyLoadingOptions?: {
|
|
89
|
+
/**
|
|
90
|
+
* The root margin of the intersection observer. This is used to determine when the slot is in the viewport.
|
|
91
|
+
*/
|
|
92
|
+
rootMargin?: string;
|
|
93
|
+
};
|
|
94
|
+
} | {
|
|
95
|
+
lazyLoading?: false;
|
|
96
|
+
lazyLoadingOptions?: never;
|
|
97
|
+
});
|
|
98
|
+
type BaseAdheseSlot = Merge<Omit<AdheseSlotOptions, 'onDispose' | 'context' | 'onFormatChange' | 'format'>, AdheseSlotHooks & {
|
|
99
|
+
/**
|
|
100
|
+
* Type of the slot. On its own has no effect, but can be used by plugins to create different behavior for different
|
|
101
|
+
* types of slots.
|
|
102
|
+
*/
|
|
103
|
+
type?: string;
|
|
104
|
+
/**
|
|
105
|
+
* The name of the slot. This is used to identify the slot in the Adhese instance.
|
|
106
|
+
*
|
|
107
|
+
* The name is generated based on the location, format, and slot of the slot.
|
|
108
|
+
*/
|
|
109
|
+
name: string;
|
|
110
|
+
/**
|
|
111
|
+
* The format code of the slot. Used to find the correct element on the page to render the ad in.
|
|
112
|
+
*
|
|
113
|
+
* If the format is a string, it is used as the format code. If the format is an array, the format code is determined
|
|
114
|
+
* by the query detector.
|
|
115
|
+
*
|
|
116
|
+
* When you change the format, the slot will request a new ad from the API automatically.
|
|
117
|
+
*/
|
|
118
|
+
format: string;
|
|
119
|
+
/**
|
|
120
|
+
* The location of the slot. This is the location that is used to determine the current page URL.
|
|
121
|
+
*/
|
|
122
|
+
location: string;
|
|
123
|
+
/**
|
|
124
|
+
* The parameters that are used to render the ad.
|
|
125
|
+
*/
|
|
126
|
+
parameters: Map<string, ReadonlyArray<string> | string>;
|
|
127
|
+
/**
|
|
128
|
+
* Whether the viewability tracking pixel has been fired.
|
|
129
|
+
*/
|
|
130
|
+
readonly isViewabilityTracked: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Whether the impression tracking pixel has been fired.
|
|
133
|
+
*/
|
|
134
|
+
readonly isImpressionTracked: boolean;
|
|
135
|
+
/**
|
|
136
|
+
* The state of the slot is currently in.
|
|
137
|
+
*
|
|
138
|
+
* - `initializing`: The slot is initializing.
|
|
139
|
+
* - `initialized`: The slot is initialized.
|
|
140
|
+
* - `loading`: The slot is loading data from the API
|
|
141
|
+
* - `loaded`: The slot has loaded data from the API and is ready to render
|
|
142
|
+
* - `empty`: The slot has loaded data from the API but the response was empty
|
|
143
|
+
* - `rendering`: The slot is rendering the ad
|
|
144
|
+
* - `rendered`: The slot has rendered the ad
|
|
145
|
+
* - `error`: The slot has encountered an error
|
|
146
|
+
*/
|
|
147
|
+
status: 'initializing' | 'initialized' | 'loading' | 'loaded' | 'empty' | 'rendering' | 'rendered' | 'error';
|
|
148
|
+
/**
|
|
149
|
+
* Is the slot disposed.
|
|
150
|
+
*/
|
|
151
|
+
isDisposed: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* The element that contains the slot.
|
|
154
|
+
*/
|
|
155
|
+
element: HTMLElement | null;
|
|
156
|
+
/**
|
|
157
|
+
* Unique identifier of the slot. ID is generated on initialization and will never change.
|
|
158
|
+
*/
|
|
159
|
+
id: string;
|
|
160
|
+
/**
|
|
161
|
+
* Slot related data fetched from the API.
|
|
162
|
+
*/
|
|
163
|
+
data: AdheseAd | null;
|
|
164
|
+
/**
|
|
165
|
+
* Options slot was created with
|
|
166
|
+
*/
|
|
167
|
+
options: Omit<AdheseSlotOptions, 'context'>;
|
|
168
|
+
/**
|
|
169
|
+
* Is the slot visible in the viewport.
|
|
170
|
+
*/
|
|
171
|
+
isVisible: boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Renders the slot in the containing element. If no data is provided, new data will be requested from the API.
|
|
174
|
+
*/
|
|
175
|
+
render(data?: AdheseAd): Promise<HTMLElement | null>;
|
|
176
|
+
/**
|
|
177
|
+
* Requests a new ad from the API and returns the ad object.
|
|
178
|
+
*/
|
|
179
|
+
request(): Promise<AdheseAd | null>;
|
|
180
|
+
/**
|
|
181
|
+
* Remove the HTML element contents from the dom.
|
|
182
|
+
*/
|
|
183
|
+
cleanElement(): void;
|
|
184
|
+
/**
|
|
185
|
+
* Removes the slot from the DOM and cleans up the slot instance.
|
|
186
|
+
*/
|
|
187
|
+
dispose(): void;
|
|
188
|
+
}>;
|
|
189
|
+
type AdheseSlotContext = BaseAdheseSlot;
|
|
190
|
+
type ReadonlyProps$1 = 'type' | 'name' | 'format' | 'location' | 'status' | 'isDisposed' | 'element' | 'id';
|
|
191
|
+
type AdheseSlot = Omit<BaseAdheseSlot, ReadonlyProps$1> & Readonly<Pick<BaseAdheseSlot, ReadonlyProps$1>>;
|
|
192
|
+
|
|
193
|
+
type AdheseSlotManager = {
|
|
194
|
+
/**
|
|
195
|
+
* Returns all slots that are currently registered and rendered.
|
|
196
|
+
*/
|
|
197
|
+
getAll(): ReadonlyArray<AdheseSlot>;
|
|
198
|
+
/**
|
|
199
|
+
* Adds a new slot to the Adhese instance and renders it.
|
|
200
|
+
*/
|
|
201
|
+
add(slot: Omit<AdheseSlotOptions, 'context'>): Readonly<AdheseSlot>;
|
|
202
|
+
/**
|
|
203
|
+
* Finds all slots in the DOM and adds them to the Adhese instance.
|
|
204
|
+
*/
|
|
205
|
+
findDomSlots(): Promise<ReadonlyArray<AdheseSlot>>;
|
|
206
|
+
/**
|
|
207
|
+
* Returns the slot with the given name.
|
|
208
|
+
*/
|
|
209
|
+
get(name: string): AdheseSlot | undefined;
|
|
210
|
+
/**
|
|
211
|
+
* Removes all slots from the Adhese instance and cleans up the slot manager.
|
|
212
|
+
*/
|
|
213
|
+
dispose(): void;
|
|
214
|
+
};
|
|
215
|
+
type SlotManagerOptions = {
|
|
216
|
+
/**
|
|
217
|
+
* List of initial slots to add to the slot manager.
|
|
218
|
+
*/
|
|
219
|
+
initialSlots?: ReadonlyArray<Merge<Omit<AdheseSlotOptions, 'containingElement' | 'context' | 'lazy'>, {
|
|
220
|
+
containingElement: string;
|
|
221
|
+
}>>;
|
|
222
|
+
context: AdheseContext;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
declare const baseSchema: _adhese_sdk_shared_validators.ZodObject<{
|
|
226
|
+
adDuration: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, number | undefined, string>>;
|
|
227
|
+
adFormat: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
228
|
+
adType: _adhese_sdk_shared_validators.ZodString;
|
|
229
|
+
additionalCreativeTracker: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
230
|
+
additionalViewableTracker: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
231
|
+
adspaceEnd: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, Date | undefined, string>>;
|
|
232
|
+
adspaceId: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
233
|
+
adspaceKey: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
234
|
+
adspaceStart: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, Date | undefined, string>>;
|
|
235
|
+
advertiserId: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
236
|
+
altText: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
237
|
+
auctionable: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodBoolean, _adhese_sdk_shared_validators.ZodLiteral<"">]>>;
|
|
238
|
+
body: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodString, Record<string, unknown> | readonly unknown[], string>, _adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodString, string, string>]>]>, string | Record<string, unknown> | readonly unknown[] | undefined, string>>;
|
|
239
|
+
clickTag: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
240
|
+
comment: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
241
|
+
creativeName: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
242
|
+
deliveryGroupId: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
243
|
+
deliveryMultiples: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
244
|
+
ext: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
245
|
+
extension: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodObject<{
|
|
246
|
+
mediaType: _adhese_sdk_shared_validators.ZodString;
|
|
247
|
+
prebid: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodUnknown>;
|
|
248
|
+
}, "strip", _adhese_sdk_shared_validators.ZodTypeAny, {
|
|
249
|
+
mediaType: string;
|
|
250
|
+
prebid?: unknown;
|
|
251
|
+
}, {
|
|
252
|
+
mediaType: string;
|
|
253
|
+
prebid?: unknown;
|
|
254
|
+
}>>;
|
|
255
|
+
height: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, number | undefined, string>>;
|
|
256
|
+
id: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
257
|
+
impressionCounter: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
258
|
+
libId: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
259
|
+
orderId: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
260
|
+
orderName: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
261
|
+
orderProperty: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
262
|
+
origin: _adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodLiteral<"JERLICIA">, _adhese_sdk_shared_validators.ZodLiteral<"DALE">]>;
|
|
263
|
+
originData: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodUnknown>;
|
|
264
|
+
originInstance: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
265
|
+
poolPath: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
266
|
+
preview: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodBoolean, _adhese_sdk_shared_validators.ZodLiteral<"">]>>;
|
|
267
|
+
priority: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, number | undefined, string>>;
|
|
268
|
+
sfSrc: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
269
|
+
share: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodString>;
|
|
270
|
+
slotID: _adhese_sdk_shared_validators.ZodString;
|
|
271
|
+
slotName: _adhese_sdk_shared_validators.ZodString;
|
|
272
|
+
swfSrc: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
273
|
+
tag: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodString, Record<string, unknown> | readonly unknown[], string>, _adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodString, string, string>]>]>, string | Record<string, unknown> | readonly unknown[] | undefined, string>>;
|
|
274
|
+
tagUrl: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
275
|
+
timeStamp: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, Date | undefined, string>>;
|
|
276
|
+
trackedImpressionCounter: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
277
|
+
tracker: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
278
|
+
trackingUrl: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
279
|
+
url: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
280
|
+
viewableImpressionCounter: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, URL | undefined, string>>;
|
|
281
|
+
width: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">]>, number | undefined, string>>;
|
|
282
|
+
widthLarge: _adhese_sdk_shared_validators.ZodOptional<_adhese_sdk_shared_validators.ZodEffects<_adhese_sdk_shared_validators.ZodUnion<[_adhese_sdk_shared_validators.ZodString, _adhese_sdk_shared_validators.ZodLiteral<"">, _adhese_sdk_shared_validators.ZodNumber]>, string | undefined, string | number>>;
|
|
283
|
+
}, "strip", _adhese_sdk_shared_validators.ZodTypeAny, {
|
|
284
|
+
adType: string;
|
|
285
|
+
origin: "JERLICIA" | "DALE";
|
|
286
|
+
slotID: string;
|
|
287
|
+
slotName: string;
|
|
288
|
+
adDuration?: number | undefined;
|
|
289
|
+
adFormat?: string | undefined;
|
|
290
|
+
additionalCreativeTracker?: URL | undefined;
|
|
291
|
+
additionalViewableTracker?: string | undefined;
|
|
292
|
+
adspaceEnd?: Date | undefined;
|
|
293
|
+
adspaceId?: string | undefined;
|
|
294
|
+
adspaceKey?: string | undefined;
|
|
295
|
+
adspaceStart?: Date | undefined;
|
|
296
|
+
advertiserId?: string | undefined;
|
|
297
|
+
altText?: string | undefined;
|
|
298
|
+
auctionable?: boolean | "" | undefined;
|
|
299
|
+
body?: string | Record<string, unknown> | readonly unknown[] | undefined;
|
|
300
|
+
clickTag?: URL | undefined;
|
|
301
|
+
comment?: string | undefined;
|
|
302
|
+
creativeName?: string | undefined;
|
|
303
|
+
deliveryGroupId?: string | undefined;
|
|
304
|
+
deliveryMultiples?: string | undefined;
|
|
305
|
+
ext?: string | undefined;
|
|
306
|
+
extension?: {
|
|
307
|
+
mediaType: string;
|
|
308
|
+
prebid?: unknown;
|
|
309
|
+
} | undefined;
|
|
310
|
+
height?: number | undefined;
|
|
311
|
+
id?: string | undefined;
|
|
312
|
+
impressionCounter?: URL | undefined;
|
|
313
|
+
libId?: string | undefined;
|
|
314
|
+
orderId?: string | undefined;
|
|
315
|
+
orderName?: string | undefined;
|
|
316
|
+
orderProperty?: string | undefined;
|
|
317
|
+
originData?: unknown;
|
|
318
|
+
originInstance?: string | undefined;
|
|
319
|
+
poolPath?: URL | undefined;
|
|
320
|
+
preview?: boolean | "" | undefined;
|
|
321
|
+
priority?: number | undefined;
|
|
322
|
+
sfSrc?: URL | undefined;
|
|
323
|
+
share?: string | undefined;
|
|
324
|
+
swfSrc?: URL | undefined;
|
|
325
|
+
tag?: string | Record<string, unknown> | readonly unknown[] | undefined;
|
|
326
|
+
tagUrl?: URL | undefined;
|
|
327
|
+
timeStamp?: Date | undefined;
|
|
328
|
+
trackedImpressionCounter?: URL | undefined;
|
|
329
|
+
tracker?: URL | undefined;
|
|
330
|
+
trackingUrl?: URL | undefined;
|
|
331
|
+
url?: URL | undefined;
|
|
332
|
+
viewableImpressionCounter?: URL | undefined;
|
|
333
|
+
width?: number | undefined;
|
|
334
|
+
widthLarge?: string | undefined;
|
|
335
|
+
}, {
|
|
336
|
+
adType: string;
|
|
337
|
+
origin: "JERLICIA" | "DALE";
|
|
338
|
+
slotID: string;
|
|
339
|
+
slotName: string;
|
|
340
|
+
adDuration?: string | undefined;
|
|
341
|
+
adFormat?: string | undefined;
|
|
342
|
+
additionalCreativeTracker?: string | undefined;
|
|
343
|
+
additionalViewableTracker?: string | undefined;
|
|
344
|
+
adspaceEnd?: string | undefined;
|
|
345
|
+
adspaceId?: string | undefined;
|
|
346
|
+
adspaceKey?: string | undefined;
|
|
347
|
+
adspaceStart?: string | undefined;
|
|
348
|
+
advertiserId?: string | undefined;
|
|
349
|
+
altText?: string | undefined;
|
|
350
|
+
auctionable?: boolean | "" | undefined;
|
|
351
|
+
body?: string | undefined;
|
|
352
|
+
clickTag?: string | undefined;
|
|
353
|
+
comment?: string | undefined;
|
|
354
|
+
creativeName?: string | undefined;
|
|
355
|
+
deliveryGroupId?: string | undefined;
|
|
356
|
+
deliveryMultiples?: string | undefined;
|
|
357
|
+
ext?: string | undefined;
|
|
358
|
+
extension?: {
|
|
359
|
+
mediaType: string;
|
|
360
|
+
prebid?: unknown;
|
|
361
|
+
} | undefined;
|
|
362
|
+
height?: string | undefined;
|
|
363
|
+
id?: string | undefined;
|
|
364
|
+
impressionCounter?: string | undefined;
|
|
365
|
+
libId?: string | undefined;
|
|
366
|
+
orderId?: string | undefined;
|
|
367
|
+
orderName?: string | undefined;
|
|
368
|
+
orderProperty?: string | undefined;
|
|
369
|
+
originData?: unknown;
|
|
370
|
+
originInstance?: string | undefined;
|
|
371
|
+
poolPath?: string | undefined;
|
|
372
|
+
preview?: boolean | "" | undefined;
|
|
373
|
+
priority?: string | undefined;
|
|
374
|
+
sfSrc?: string | undefined;
|
|
375
|
+
share?: string | undefined;
|
|
376
|
+
swfSrc?: string | undefined;
|
|
377
|
+
tag?: string | undefined;
|
|
378
|
+
tagUrl?: string | undefined;
|
|
379
|
+
timeStamp?: string | undefined;
|
|
380
|
+
trackedImpressionCounter?: string | undefined;
|
|
381
|
+
tracker?: string | undefined;
|
|
382
|
+
trackingUrl?: string | undefined;
|
|
383
|
+
url?: string | undefined;
|
|
384
|
+
viewableImpressionCounter?: string | undefined;
|
|
385
|
+
width?: string | undefined;
|
|
386
|
+
widthLarge?: string | number | undefined;
|
|
387
|
+
}>;
|
|
388
|
+
type AdResponse = (TypeOf<typeof baseSchema> & {
|
|
389
|
+
additionalCreatives?: ReadonlyArray<AdResponse> | string;
|
|
390
|
+
});
|
|
391
|
+
declare const adResponseSchema: ZodType<AdResponse>;
|
|
392
|
+
type PreParsedAd = TypeOf<typeof adResponseSchema> & {
|
|
393
|
+
additionalCreatives?: ReadonlyArray<PreParsedAd> | string;
|
|
394
|
+
};
|
|
395
|
+
type AdheseAd<T = string | Record<string, unknown> | ReadonlyArray<unknown>> = Omit<PreParsedAd, 'tag'> & {
|
|
396
|
+
tag: T | string;
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
type AdRequestOptions = {
|
|
400
|
+
/**
|
|
401
|
+
* Slot you want to fetch the ad for
|
|
402
|
+
*/
|
|
403
|
+
slot: {
|
|
404
|
+
name: MaybeRef<string>;
|
|
405
|
+
parameters: Map<string, ReadonlyArray<string> | string>;
|
|
406
|
+
};
|
|
407
|
+
context: AdheseContext;
|
|
408
|
+
};
|
|
409
|
+
type AdMultiRequestOptions = Omit<AdRequestOptions, 'slot'> & {
|
|
410
|
+
slots: ReadonlyArray<AdRequestOptions['slot']>;
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
declare const logger: _adhese_sdk_shared.Logger<"error" | "trace" | "debug" | "info" | "warn">;
|
|
414
|
+
|
|
415
|
+
declare function createGlobalHooks(): {
|
|
416
|
+
runOnInit: (arg: void) => void;
|
|
417
|
+
onInit: (callback: (arg: void) => void | Promise<void>) => () => void;
|
|
418
|
+
runOnDispose: (arg: void) => void;
|
|
419
|
+
onDispose: (callback: (arg: void) => void | Promise<void>) => () => void;
|
|
420
|
+
runOnRequest: (arg: AdMultiRequestOptions) => Promise<AdMultiRequestOptions>;
|
|
421
|
+
onRequest: (callback: (arg: AdMultiRequestOptions) => void | AdMultiRequestOptions | Promise<void | AdMultiRequestOptions>) => () => void;
|
|
422
|
+
runOnResponse: (arg: readonly AdheseAd[]) => Promise<readonly AdheseAd[]>;
|
|
423
|
+
onResponse: (callback: (arg: readonly AdheseAd[]) => void | readonly AdheseAd[] | Promise<void | readonly AdheseAd[]>) => () => void;
|
|
424
|
+
runOnSlotCreate: (arg: AdheseSlotOptions) => AdheseSlotOptions;
|
|
425
|
+
onSlotCreate: (callback: (arg: AdheseSlotOptions) => void | Promise<void> | AdheseSlotOptions) => () => void;
|
|
426
|
+
clearAll: () => void;
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
type AdhesePluginInformation = {
|
|
430
|
+
index: number;
|
|
431
|
+
version: string;
|
|
432
|
+
hooks: ReturnType<typeof createGlobalHooks>;
|
|
433
|
+
};
|
|
434
|
+
type AdhesePlugin<T extends {
|
|
435
|
+
name: string;
|
|
436
|
+
} & Record<string, unknown> = {
|
|
437
|
+
name: string;
|
|
438
|
+
} & Record<string, unknown>> = (context: AdheseContext, plugin: AdhesePluginInformation) => T;
|
|
439
|
+
type BaseOptions = {
|
|
440
|
+
/**
|
|
441
|
+
* The Adhese account name.
|
|
442
|
+
*/
|
|
443
|
+
account: string;
|
|
444
|
+
/**
|
|
445
|
+
* The url that is used to connect to the Adhese ad server. Pass a custom URL if you want to use your own domain for
|
|
446
|
+
* the connection.
|
|
447
|
+
*
|
|
448
|
+
* @default 'https://ads-{{account}}.adhese.com'
|
|
449
|
+
*/
|
|
450
|
+
host?: UrlString;
|
|
451
|
+
/**
|
|
452
|
+
* The url that is used to connect to the Adhese pool server. Pass a custom URL if you want to use your own domain for
|
|
453
|
+
* the connection.
|
|
454
|
+
*
|
|
455
|
+
* @default 'https://pool-{{account}}.adhese.com'
|
|
456
|
+
*/
|
|
457
|
+
poolHost?: UrlString;
|
|
458
|
+
/**
|
|
459
|
+
* The page location. This is used to determine the current page location identifier.
|
|
460
|
+
*/
|
|
461
|
+
location?: string;
|
|
462
|
+
/**
|
|
463
|
+
* The requestAds type to use for the Adhese API requests. This can be either `GET` or `POST`. `POST` is the default
|
|
464
|
+
* and offers the most options. `GET` is more limited as it needs pass its data as search parameters but can be used
|
|
465
|
+
* in environments where `POST` requests are not allowed.
|
|
466
|
+
*
|
|
467
|
+
* @default 'POST'
|
|
468
|
+
*/
|
|
469
|
+
requestType?: 'GET' | 'POST';
|
|
470
|
+
/**
|
|
471
|
+
* Enable debug logging.
|
|
472
|
+
*
|
|
473
|
+
* @default false
|
|
474
|
+
*/
|
|
475
|
+
debug?: boolean;
|
|
476
|
+
/**
|
|
477
|
+
* Find all slots in the DOM and add them to the Adhese instance during initialization.
|
|
478
|
+
*
|
|
479
|
+
* @default false
|
|
480
|
+
*/
|
|
481
|
+
findDomSlotsOnLoad?: boolean;
|
|
482
|
+
/**
|
|
483
|
+
* Additional parameters to send with each request. Make sure that the keys of a parameter only contain `2` characters.
|
|
484
|
+
*/
|
|
485
|
+
parameters?: Record<string, ReadonlyArray<string> | string>;
|
|
486
|
+
/**
|
|
487
|
+
* The consent type to use for the Adhese API requests. This can be either `true` or `false`. `false` is the default and
|
|
488
|
+
* will send all consent data to the Adhese API. `false` will send no consent data to the Adhese API.
|
|
489
|
+
*
|
|
490
|
+
* @default false
|
|
491
|
+
*/
|
|
492
|
+
consent?: boolean;
|
|
493
|
+
/**
|
|
494
|
+
* Will log the `document.referrer` to the Adhese API in a BASE64 string with the `re` parameter.
|
|
495
|
+
*
|
|
496
|
+
* @default true
|
|
497
|
+
*/
|
|
498
|
+
logReferrer?: boolean;
|
|
499
|
+
/**
|
|
500
|
+
* Will log the `window.location.href` to the Adhese API in a BASE64 string with the `ur` parameter.
|
|
501
|
+
*
|
|
502
|
+
* @default true
|
|
503
|
+
*/
|
|
504
|
+
logUrl?: boolean;
|
|
505
|
+
/**
|
|
506
|
+
* If `true`, ads will be rendered immediately after they are fetched from the API. If `false`, ads will only be
|
|
507
|
+
* rendered when the slot is in the viewport.
|
|
508
|
+
*
|
|
509
|
+
* @default false
|
|
510
|
+
*/
|
|
511
|
+
eagerRendering?: boolean;
|
|
512
|
+
/**
|
|
513
|
+
* The query detector options for the Adhese instance.
|
|
514
|
+
*/
|
|
515
|
+
queries?: Record<string, string>;
|
|
516
|
+
} & ({
|
|
517
|
+
viewabilityTracking?: true;
|
|
518
|
+
/**
|
|
519
|
+
* Options for the viewability tracking of the ads. If `true` or `undefined`, the default viewability tracking options will be used.
|
|
520
|
+
*
|
|
521
|
+
* @default true
|
|
522
|
+
*/
|
|
523
|
+
viewabilityTrackingOptions?: {
|
|
524
|
+
/**
|
|
525
|
+
* Fraction of the ad that needs to be in the viewport for the ad to be considered viewable.
|
|
526
|
+
*
|
|
527
|
+
* @default 0.2
|
|
528
|
+
*/
|
|
529
|
+
threshold?: number;
|
|
530
|
+
/**
|
|
531
|
+
* The duration the ad needs to be in the viewport for the ad to be considered viewable in milliseconds.
|
|
532
|
+
*
|
|
533
|
+
* @default 1000
|
|
534
|
+
*/
|
|
535
|
+
duration?: number;
|
|
536
|
+
/**
|
|
537
|
+
* The margin around the viewport where the ad is considered viewable.
|
|
538
|
+
*
|
|
539
|
+
* @default '0px'
|
|
540
|
+
*/
|
|
541
|
+
rootMargin?: string;
|
|
542
|
+
};
|
|
543
|
+
} | {
|
|
544
|
+
viewabilityTracking?: false;
|
|
545
|
+
viewabilityTrackingOptions?: never;
|
|
546
|
+
}) & Pick<SlotManagerOptions, 'initialSlots'>;
|
|
547
|
+
type AdheseOptions<T extends ReadonlyArray<AdhesePlugin> = []> = BaseOptions & {
|
|
548
|
+
/**
|
|
549
|
+
* The plugins that are used for the Adhese instance.
|
|
550
|
+
*/
|
|
551
|
+
plugins?: T['length'] extends 0 ? ReadonlyArray<AdhesePlugin> : T;
|
|
552
|
+
};
|
|
553
|
+
type MergedOptions = Merge<BaseOptions, Required<Pick<BaseOptions, 'host' | 'poolHost' | 'location' | 'requestType' | 'debug' | 'initialSlots' | 'findDomSlotsOnLoad' | 'consent' | 'logUrl' | 'logReferrer' | 'eagerRendering' | 'viewabilityTracking'>>>;
|
|
554
|
+
type AdheseEvents = {
|
|
555
|
+
locationChange: string;
|
|
556
|
+
consentChange: boolean;
|
|
557
|
+
addSlot: AdheseSlot;
|
|
558
|
+
removeSlot: AdheseSlot;
|
|
559
|
+
responseReceived: ReadonlyArray<AdheseAd>;
|
|
560
|
+
requestAd: AdMultiRequestOptions;
|
|
561
|
+
requestError: Error;
|
|
562
|
+
previewReceived: ReadonlyArray<AdheseAd>;
|
|
563
|
+
parametersChange: Map<string, ReadonlyArray<string> | string>;
|
|
564
|
+
debugChange: boolean;
|
|
565
|
+
};
|
|
566
|
+
type BaseAdhese = {
|
|
567
|
+
/**
|
|
568
|
+
* The slots that are in the Adhese instance.
|
|
569
|
+
*/
|
|
570
|
+
slots: Map<string, AdheseSlot>;
|
|
571
|
+
/**
|
|
572
|
+
* The page location. This is used to determine the current page location identifier.
|
|
573
|
+
*/
|
|
574
|
+
location: string;
|
|
575
|
+
/**
|
|
576
|
+
* The consent type to use for the Adhese API requests. This can be either `true` or `false`. `false` is the default and
|
|
577
|
+
* will send all consent data to the Adhese API. `false` will send no consent data to the Adhese API.
|
|
578
|
+
*/
|
|
579
|
+
consent: boolean;
|
|
580
|
+
/**
|
|
581
|
+
* String that is generated by either the binary consent passed with `consent` property or the value passed by the TCF
|
|
582
|
+
* API. If consent is `true` the string will be `all` otherwise it will be `none`. If the consent is coming from TCF
|
|
583
|
+
* the string will be the TCF string.
|
|
584
|
+
*/
|
|
585
|
+
consentString?: string;
|
|
586
|
+
/**
|
|
587
|
+
* The logger instance that is used for multi level console logging
|
|
588
|
+
*/
|
|
589
|
+
logger: typeof logger;
|
|
590
|
+
/**
|
|
591
|
+
* Debug mode of the Adhese instance. When set to true will log verbose logs to the console and will load the Devtools.
|
|
592
|
+
*/
|
|
593
|
+
debug: boolean;
|
|
594
|
+
/**
|
|
595
|
+
* The parameters that are used for all ads.
|
|
596
|
+
*/
|
|
597
|
+
parameters: Map<string, ReadonlyArray<string> | string>;
|
|
598
|
+
/**
|
|
599
|
+
* The event manager for the Adhese instance.
|
|
600
|
+
*/
|
|
601
|
+
events: EventManager<AdheseEvents>;
|
|
602
|
+
/**
|
|
603
|
+
* Options passed to the Adhese instance.
|
|
604
|
+
*/
|
|
605
|
+
options: Readonly<MergedOptions>;
|
|
606
|
+
/**
|
|
607
|
+
* Is the instance disposed
|
|
608
|
+
*/
|
|
609
|
+
isDisposed: boolean;
|
|
610
|
+
/**
|
|
611
|
+
* Active media query device
|
|
612
|
+
*/
|
|
613
|
+
device: string;
|
|
614
|
+
/**
|
|
615
|
+
* Get a slot by name.
|
|
616
|
+
* @param name The name of the slot.
|
|
617
|
+
*/
|
|
618
|
+
get(name: string): AdheseSlot | undefined;
|
|
619
|
+
/**
|
|
620
|
+
* Get all slots in the Adhese instance.
|
|
621
|
+
*/
|
|
622
|
+
getAll(): ReadonlyArray<AdheseSlot>;
|
|
623
|
+
/**
|
|
624
|
+
* Adds a new slot to the Adhese instance and renders it.
|
|
625
|
+
*/
|
|
626
|
+
addSlot(slot: Omit<AdheseSlotOptions, 'location' | 'context'>): Readonly<AdheseSlot>;
|
|
627
|
+
/**
|
|
628
|
+
* Finds all slots in the DOM and adds them to the Adhese instance.
|
|
629
|
+
*/
|
|
630
|
+
findDomSlots(): Promise<ReadonlyArray<AdheseSlot>>;
|
|
631
|
+
/**
|
|
632
|
+
* Removes all slots from the Adhese instance and cleans up the Adhese instance.
|
|
633
|
+
*
|
|
634
|
+
* After calling this method, the Adhese instance is no longer usable.
|
|
635
|
+
*/
|
|
636
|
+
dispose(): void;
|
|
637
|
+
};
|
|
638
|
+
type ExtractFromTupleWithNameKey<T extends string, U extends Record<string, unknown>> = U extends {
|
|
639
|
+
name: T;
|
|
640
|
+
} ? U : never;
|
|
641
|
+
type Plugins<T extends ReadonlyArray<AdhesePlugin> = [], U extends {
|
|
642
|
+
name: string;
|
|
643
|
+
} = ReturnType<Required<AdheseOptions<T>>['plugins'][number]>> = {
|
|
644
|
+
[K in U['name']]: Omit<ExtractFromTupleWithNameKey<K, U>, 'name'>;
|
|
645
|
+
};
|
|
646
|
+
type ReadonlyProps = 'options' | 'isDisposed' | 'logger' | 'events' | 'get' | 'getAll' | 'addSlot' | 'findDomSlots' | 'dispose' | 'slots' | 'device' | 'consentString';
|
|
647
|
+
type Adhese<T extends ReadonlyArray<AdhesePlugin> = []> = Omit<BaseAdhese, ReadonlyProps> & Readonly<Pick<BaseAdhese, ReadonlyProps>> & {
|
|
648
|
+
plugins: Plugins<T>;
|
|
649
|
+
};
|
|
650
|
+
type AdheseContextState = Omit<BaseAdhese, 'options'> & {
|
|
651
|
+
readonly options: MergedOptions;
|
|
652
|
+
hooks: ReturnType<typeof createGlobalHooks>;
|
|
653
|
+
};
|
|
654
|
+
type NonPartialProps = 'options' | 'logger' | 'events' | 'isDisposed' | 'location' | 'consent' | 'debug' | 'parameters' | 'slots' | 'hooks';
|
|
655
|
+
type AdheseContext = Omit<Partial<AdheseContextState>, NonPartialProps> & Pick<AdheseContextState, NonPartialProps>;
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Creates an Adhese instance. This instance is your main entry point to the Adhese API.
|
|
659
|
+
*
|
|
660
|
+
* @param options {AdheseOptions} The options to create the Adhese instance with. See the {@link AdheseOptions} type for more information.
|
|
661
|
+
*
|
|
662
|
+
* @return Adhese The Adhese instance.
|
|
663
|
+
*/
|
|
664
|
+
declare function createAdhese<T extends ReadonlyArray<AdhesePlugin>>(options: AdheseOptions<T>): Adhese<T>;
|
|
665
|
+
|
|
666
|
+
export { type AdRequestOptions, type Adhese, type AdheseAd, type AdheseContext, type AdheseOptions, type AdhesePlugin, type AdhesePluginInformation, type AdheseSlot, type AdheseSlotContext, type AdheseSlotHooks, type AdheseSlotManager, type AdheseSlotOptions, createAdhese };
|
package/dist/package.json.js
CHANGED
package/dist/slot/slot.js
CHANGED
package/dist/slot/slot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot.js","sources":["../../src/slot/slot.ts"],"sourcesContent":["import {\n type Ref,\n type UnwrapRef,\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n isDeepEqual,\n omit,\n reactive,\n ref,\n uniqueId,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport type { AdheseAd } from '@adhese/sdk';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport type { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } from './slot.types';\nimport { renderIframe, renderInline } from './slot.utils';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<RenderMode, (ad: AdheseAd, 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 ...slotOptions,\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\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 ...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 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 = computed(() => {\n if (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value || slotContext.value?.isDisposed)\n return null;\n\n return document.querySelector<HTMLElement>(`.adunit[data-format=\"${format.value}\"]#${options.containingElement}${options.slot ? `[data-slot=\"${options.slot}\"]` : ''}`);\n },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch([data, isInViewport], async ([newData, newIsInViewport], [oldData]) => {\n if ((!newData || (oldData && isDeepEqual(newData, oldData))) && status.value === 'rendered')\n return;\n\n if (newIsInViewport)\n await slotContext.value?.render(newData ?? undefined);\n });\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n if (slotContext.value?.data?.viewableImpressionCounter) {\n trackingPixel.value = addTrackingPixel(slotContext.value?.data?.viewableImpressionCounter);\n\n context.logger.debug(`Viewability tracking pixel fired for ${slotContext.value?.name}`);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n });\n\n async function request(): Promise<AdheseAd | null> {\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 return response;\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n status.value = 'rendering';\n\n await waitForDomLoad();\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!renderAd) {\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n\n return null;\n }\n\n if (!element.value) {\n const error = `Could not create slot for format ${format.value}. No element found.`;\n logger.error(error, options);\n throw new Error(error);\n }\n\n if (context.debug)\n element.value.style.position = 'relative';\n\n if (typeof renderAd?.tag !== 'string') {\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 status.value = 'error';\n throw new Error(error);\n }\n\n renderFunctions[renderMode](renderAd, element.value);\n\n if (renderAd.impressionCounter && !impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value = addTrackingPixel(renderAd.impressionCounter);\n\n isImpressionTracked.value = true;\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 data.value = renderAd;\n\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n\n function cleanElement(): void {\n if (!element.value)\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n element.value.style.width = '';\n element.value.style.height = '';\n\n data.value = null;\n originalData.value = null;\n }\n\n function dispose(): void {\n cleanElement();\n\n data.value = null;\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 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 status.value = 'initialized';\n\n runOnInit();\n\n if (options.lazyLoading)\n return;\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 {\n type Ref,\n type UnwrapRef,\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n isDeepEqual,\n omit,\n reactive,\n ref,\n uniqueId,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport type { AdheseAd } from '@adhese/sdk';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport type { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } from './slot.types';\nimport { renderIframe, renderInline } from './slot.utils';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<RenderMode, (ad: AdheseAd, 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 ...slotOptions,\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\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 ...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 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 = computed(() => {\n if (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value || slotContext.value?.isDisposed)\n return null;\n\n return document.querySelector<HTMLElement>(`.adunit[data-format=\"${format.value}\"]#${options.containingElement}${options.slot ? `[data-slot=\"${options.slot}\"]` : ''}`);\n },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch([data, isInViewport], async ([newData, newIsInViewport], [oldData]) => {\n if ((!newData || (oldData && isDeepEqual(newData, oldData))) && status.value === 'rendered')\n return;\n\n if (newIsInViewport)\n await slotContext.value?.render(newData ?? undefined);\n });\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n if (slotContext.value?.data?.viewableImpressionCounter) {\n trackingPixel.value = addTrackingPixel(slotContext.value?.data?.viewableImpressionCounter);\n\n context.logger.debug(`Viewability tracking pixel fired for ${slotContext.value?.name}`);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n });\n\n async function request(): Promise<AdheseAd | null> {\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 return response;\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n status.value = 'rendering';\n\n await waitForDomLoad();\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!renderAd) {\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n\n return null;\n }\n\n if (!element.value) {\n const error = `Could not create slot for format ${format.value}. No element found.`;\n logger.error(error, options);\n throw new Error(error);\n }\n\n if (context.debug)\n element.value.style.position = 'relative';\n\n if (typeof renderAd?.tag !== 'string') {\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 status.value = 'error';\n throw new Error(error);\n }\n\n renderFunctions[renderMode](renderAd, element.value);\n\n if (renderAd.impressionCounter && !impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value = addTrackingPixel(renderAd.impressionCounter);\n\n isImpressionTracked.value = true;\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 data.value = renderAd;\n\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n\n function cleanElement(): void {\n if (!element.value)\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n element.value.style.width = '';\n element.value.style.height = '';\n\n data.value = null;\n originalData.value = null;\n }\n\n function dispose(): void {\n cleanElement();\n\n data.value = null;\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 status.value = 'initialized';\n\n runOnInit();\n\n if (options.lazyLoading)\n return;\n\n data.value = await slotContext.value?.request() ?? null;\n });\n\n return state;\n })!;\n}\n"],"names":["extRequestAd"],"mappings":"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"}
|