@adhese/sdk-lite 1.1.1 → 1.2.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 +13 -0
- package/dist/cjs/sdkLite.cjs +5 -2
- package/dist/cjs/sdkLite.cjs.map +1 -1
- package/dist/sdkLite.d.ts +3 -1
- package/dist/sdkLite.js +6 -3
- package/dist/sdkLite.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @adhese/sdk-lite
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 112e224: Add `width` and `height` option to overwrite slot sizing
|
|
8
|
+
|
|
9
|
+
**NOTE**: Only applies when `renderMode` is `iframe` or `undefined`
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [112e224]
|
|
14
|
+
- @adhese/sdk-shared@1.1.0
|
|
15
|
+
|
|
3
16
|
## 1.1.1
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/cjs/sdkLite.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const sdkShared = require("@adhese/sdk-shared");
|
|
4
|
-
const version = "1.
|
|
4
|
+
const version = "1.2.0";
|
|
5
5
|
const renderFunctions = {
|
|
6
6
|
iframe: sdkShared.renderIframe,
|
|
7
7
|
inline: sdkShared.renderInline
|
|
@@ -74,7 +74,10 @@ function createSlot(options) {
|
|
|
74
74
|
}
|
|
75
75
|
if (typeof data.tag !== "string")
|
|
76
76
|
throw new Error("Received invalid ad data, tag is not a string");
|
|
77
|
-
renderFunctions[options.renderMode ?? "iframe"](
|
|
77
|
+
renderFunctions[options.renderMode ?? "iframe"]({
|
|
78
|
+
...data,
|
|
79
|
+
...sdkShared.pick(options, ["width", "height"])
|
|
80
|
+
}, element);
|
|
78
81
|
(_b = options.onRender) == null ? void 0 : _b.call(options, this);
|
|
79
82
|
if (data.impressionCounter && !isImpressionTracked) {
|
|
80
83
|
trackingPixels.add(sdkShared.addTrackingPixel(data.impressionCounter));
|
package/dist/cjs/sdkLite.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdkLite.cjs","sources":["../../src/sdkLite.ts"],"sourcesContent":["import {\n type RenderOptions,\n addTrackingPixel,\n generateName,\n renderIframe,\n renderInline,\n round,\n uniqueId,\n} from '@adhese/sdk-shared';\n\ntype RenderMode = 'iframe' | 'inline';\n\nexport type AdheseLiteSlotOptions = {\n containingElement?: HTMLElement;\n format: string;\n account: string;\n location: string;\n host?: string;\n renderMode?: RenderMode;\n parameters?: Record<string, string | ReadonlyArray<string>>;\n slot?: string;\n consent?: boolean | string;\n clickTrackerUrl?: string | URL;\n onDispose?(slot: AdheseLiteSlot): void;\n onRender?(slot: AdheseLiteSlot): void;\n onRequest?(slot: AdheseLiteSlot): void;\n onEmpty?(slot: AdheseLiteSlot): void;\n};\n\nexport type AdheseLiteSlot = {\n options: AdheseLiteSlotOptions;\n name: string;\n data?: AdheseLiteAd;\n parameters: Record<string, string | ReadonlyArray<string>>;\n element: HTMLElement;\n render(): Promise<HTMLElement>;\n request(): Promise<AdheseLiteAd | null>;\n dispose(): void;\n};\n\nexport type AdheseLiteAd = {\n tag: string;\n width?: string;\n height?: string;\n impressionCounter?: string;\n viewableImpressionCounter?: string;\n};\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n};\n\nexport function createSlot(options: AdheseLiteSlotOptions): AdheseLiteSlot {\n const name = generateName(options.location, options.format, options.slot);\n\n const trackingPixels = new Set<HTMLImageElement>();\n\n const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {\n rootMargin: '200px',\n threshold: 0,\n });\n\n const viewabilityTrackingIntersectionObserver = new IntersectionObserver(onViewabilityIntersection, {\n rootMargin: '0px',\n threshold: Array.from({ length: 11 }, (_, i) => i * 0.1),\n });\n\n const consentParameters: {\n tl: 'all' | 'none';\n } | {\n xt: string;\n } = typeof options.consent === 'string'\n ? {\n xt: options.consent,\n }\n : {\n tl: options.consent ? 'all' : 'none',\n };\n\n const parameters = {\n ...options.parameters,\n ...consentParameters,\n };\n\n let isImpressionTracked = false;\n\n const element = options.containingElement ?? document.createElement('div');\n\n if (!options.containingElement) {\n element.id = `${name}:${uniqueId(3)}`;\n element.classList.add('adunit');\n element.dataset.format = options.format;\n element.dataset.slot = options.format;\n element.dataset.location = options.location;\n\n document.currentScript?.insertAdjacentElement('beforebegin', element);\n }\n\n const context: AdheseLiteSlot = {\n options,\n name,\n parameters,\n element,\n async request(): Promise<AdheseLiteAd | null> {\n const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {\n method: 'POST',\n body: JSON.stringify({\n slots: [{\n slotname: name,\n }],\n parameters,\n }),\n headers: {\n // eslint-disable-next-line ts/naming-convention\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok)\n throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);\n\n const [data] = await response.json() as ReadonlyArray<AdheseLiteAd>;\n\n this.data = data;\n\n options.onRequest?.(this);\n\n return data;\n },\n async render(): Promise<HTMLElement> {\n const data = this.data ?? (await this.request());\n element.removeEventListener('click', onClick);\n\n if (!data) {\n options.onEmpty?.(this);\n\n return element;\n }\n\n if (typeof data.tag !== 'string')\n throw new Error('Received invalid ad data, tag is not a string');\n\n renderFunctions[options.renderMode ?? 'iframe'](data, element);\n\n options.onRender?.(this);\n\n if (data.impressionCounter && !isImpressionTracked) {\n trackingPixels.add(addTrackingPixel(data.impressionCounter));\n isImpressionTracked = true;\n }\n\n if (data.viewableImpressionCounter) {\n viewabilityTrackingIntersectionObserver.observe(element);\n }\n\n element.addEventListener('click', onClick);\n\n return element;\n },\n dispose(): void {\n options.onDispose?.(this);\n\n element.innerHTML = '';\n\n for (const pixel of trackingPixels) {\n pixel.remove();\n }\n trackingPixels.clear();\n\n renderIntersectionObserver?.disconnect();\n viewabilityTrackingIntersectionObserver.disconnect();\n\n element.removeEventListener('click', onClick);\n },\n };\n\n let isClickTracked = false;\n function onClick(): void {\n if (options.clickTrackerUrl && !isClickTracked) {\n trackingPixels.add(addTrackingPixel(options.clickTrackerUrl));\n isClickTracked = true;\n }\n }\n\n let timeoutId: number | null = null;\n function onViewabilityIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n const ratio = round(entry.intersectionRatio, 1);\n const threshold = 0.2;\n\n if (ratio >= threshold && !timeoutId) {\n // @ts-expect-error The is misfiring to the Node type\n timeoutId = setTimeout(() => {\n timeoutId = null;\n viewabilityTrackingIntersectionObserver.disconnect();\n\n if (context.data?.viewableImpressionCounter) {\n trackingPixels.add(addTrackingPixel(context.data?.viewableImpressionCounter));\n }\n }, 1000);\n }\n else if (ratio < threshold && timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function onRenderIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n if (entry.isIntersecting) {\n context.render().catch(console.error);\n renderIntersectionObserver?.disconnect();\n }\n }\n renderIntersectionObserver.observe(element);\n return context;\n}\n\nexport { version } from '../package.json';\n"],"names":["renderIframe","renderInline","generateName","uniqueId","_a","addTrackingPixel","round"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"sdkLite.cjs","sources":["../../src/sdkLite.ts"],"sourcesContent":["import {\n type RenderOptions,\n addTrackingPixel,\n generateName,\n pick,\n renderIframe,\n renderInline,\n round,\n uniqueId,\n} from '@adhese/sdk-shared';\n\ntype RenderMode = 'iframe' | 'inline';\n\nexport type AdheseLiteSlotOptions = {\n containingElement?: HTMLElement;\n format: string;\n account: string;\n location: string;\n host?: string;\n renderMode?: RenderMode;\n width?: string | number;\n height?: string | number;\n parameters?: Record<string, string | ReadonlyArray<string>>;\n slot?: string;\n consent?: boolean | string;\n clickTrackerUrl?: string | URL;\n onDispose?(slot: AdheseLiteSlot): void;\n onRender?(slot: AdheseLiteSlot): void;\n onRequest?(slot: AdheseLiteSlot): void;\n onEmpty?(slot: AdheseLiteSlot): void;\n};\n\nexport type AdheseLiteSlot = {\n options: AdheseLiteSlotOptions;\n name: string;\n data?: AdheseLiteAd;\n parameters: Record<string, string | ReadonlyArray<string>>;\n element: HTMLElement;\n render(): Promise<HTMLElement>;\n request(): Promise<AdheseLiteAd | null>;\n dispose(): void;\n};\n\nexport type AdheseLiteAd = {\n tag: string;\n width?: string;\n height?: string;\n impressionCounter?: string;\n viewableImpressionCounter?: string;\n};\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n};\n\nexport function createSlot(options: AdheseLiteSlotOptions): AdheseLiteSlot {\n const name = generateName(options.location, options.format, options.slot);\n\n const trackingPixels = new Set<HTMLImageElement>();\n\n const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {\n rootMargin: '200px',\n threshold: 0,\n });\n\n const viewabilityTrackingIntersectionObserver = new IntersectionObserver(onViewabilityIntersection, {\n rootMargin: '0px',\n threshold: Array.from({ length: 11 }, (_, i) => i * 0.1),\n });\n\n const consentParameters: {\n tl: 'all' | 'none';\n } | {\n xt: string;\n } = typeof options.consent === 'string'\n ? {\n xt: options.consent,\n }\n : {\n tl: options.consent ? 'all' : 'none',\n };\n\n const parameters = {\n ...options.parameters,\n ...consentParameters,\n };\n\n let isImpressionTracked = false;\n\n const element = options.containingElement ?? document.createElement('div');\n\n if (!options.containingElement) {\n element.id = `${name}:${uniqueId(3)}`;\n element.classList.add('adunit');\n element.dataset.format = options.format;\n element.dataset.slot = options.format;\n element.dataset.location = options.location;\n\n document.currentScript?.insertAdjacentElement('beforebegin', element);\n }\n\n const context: AdheseLiteSlot = {\n options,\n name,\n parameters,\n element,\n async request(): Promise<AdheseLiteAd | null> {\n const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {\n method: 'POST',\n body: JSON.stringify({\n slots: [{\n slotname: name,\n }],\n parameters,\n }),\n headers: {\n // eslint-disable-next-line ts/naming-convention\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok)\n throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);\n\n const [data] = await response.json() as ReadonlyArray<AdheseLiteAd>;\n\n this.data = data;\n\n options.onRequest?.(this);\n\n return data;\n },\n async render(): Promise<HTMLElement> {\n const data = this.data ?? (await this.request());\n element.removeEventListener('click', onClick);\n\n if (!data) {\n options.onEmpty?.(this);\n\n return element;\n }\n\n if (typeof data.tag !== 'string')\n throw new Error('Received invalid ad data, tag is not a string');\n\n renderFunctions[options.renderMode ?? 'iframe']({\n ...data,\n ...pick(options, ['width', 'height']),\n }, element);\n\n options.onRender?.(this);\n\n if (data.impressionCounter && !isImpressionTracked) {\n trackingPixels.add(addTrackingPixel(data.impressionCounter));\n isImpressionTracked = true;\n }\n\n if (data.viewableImpressionCounter) {\n viewabilityTrackingIntersectionObserver.observe(element);\n }\n\n element.addEventListener('click', onClick);\n\n return element;\n },\n dispose(): void {\n options.onDispose?.(this);\n\n element.innerHTML = '';\n\n for (const pixel of trackingPixels) {\n pixel.remove();\n }\n trackingPixels.clear();\n\n renderIntersectionObserver?.disconnect();\n viewabilityTrackingIntersectionObserver.disconnect();\n\n element.removeEventListener('click', onClick);\n },\n };\n\n let isClickTracked = false;\n function onClick(): void {\n if (options.clickTrackerUrl && !isClickTracked) {\n trackingPixels.add(addTrackingPixel(options.clickTrackerUrl));\n isClickTracked = true;\n }\n }\n\n let timeoutId: number | null = null;\n function onViewabilityIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n const ratio = round(entry.intersectionRatio, 1);\n const threshold = 0.2;\n\n if (ratio >= threshold && !timeoutId) {\n // @ts-expect-error The is misfiring to the Node type\n timeoutId = setTimeout(() => {\n timeoutId = null;\n viewabilityTrackingIntersectionObserver.disconnect();\n\n if (context.data?.viewableImpressionCounter) {\n trackingPixels.add(addTrackingPixel(context.data?.viewableImpressionCounter));\n }\n }, 1000);\n }\n else if (ratio < threshold && timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function onRenderIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n if (entry.isIntersecting) {\n context.render().catch(console.error);\n renderIntersectionObserver?.disconnect();\n }\n }\n renderIntersectionObserver.observe(element);\n return context;\n}\n\nexport { version } from '../package.json';\n"],"names":["renderIframe","renderInline","generateName","uniqueId","_a","pick","addTrackingPixel","round"],"mappings":"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"}
|
package/dist/sdkLite.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var version = "1.
|
|
1
|
+
var version = "1.2.0";
|
|
2
2
|
|
|
3
3
|
type RenderMode = 'iframe' | 'inline';
|
|
4
4
|
type AdheseLiteSlotOptions = {
|
|
@@ -8,6 +8,8 @@ type AdheseLiteSlotOptions = {
|
|
|
8
8
|
location: string;
|
|
9
9
|
host?: string;
|
|
10
10
|
renderMode?: RenderMode;
|
|
11
|
+
width?: string | number;
|
|
12
|
+
height?: string | number;
|
|
11
13
|
parameters?: Record<string, string | ReadonlyArray<string>>;
|
|
12
14
|
slot?: string;
|
|
13
15
|
consent?: boolean | string;
|
package/dist/sdkLite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { generateName, uniqueId, round, addTrackingPixel, renderIframe, renderInline } from "@adhese/sdk-shared";
|
|
2
|
-
const version = "1.
|
|
1
|
+
import { generateName, uniqueId, round, addTrackingPixel, pick, renderIframe, renderInline } from "@adhese/sdk-shared";
|
|
2
|
+
const version = "1.2.0";
|
|
3
3
|
const renderFunctions = {
|
|
4
4
|
iframe: renderIframe,
|
|
5
5
|
inline: renderInline
|
|
@@ -72,7 +72,10 @@ function createSlot(options) {
|
|
|
72
72
|
}
|
|
73
73
|
if (typeof data.tag !== "string")
|
|
74
74
|
throw new Error("Received invalid ad data, tag is not a string");
|
|
75
|
-
renderFunctions[options.renderMode ?? "iframe"](
|
|
75
|
+
renderFunctions[options.renderMode ?? "iframe"]({
|
|
76
|
+
...data,
|
|
77
|
+
...pick(options, ["width", "height"])
|
|
78
|
+
}, element);
|
|
76
79
|
(_b = options.onRender) == null ? void 0 : _b.call(options, this);
|
|
77
80
|
if (data.impressionCounter && !isImpressionTracked) {
|
|
78
81
|
trackingPixels.add(addTrackingPixel(data.impressionCounter));
|
package/dist/sdkLite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdkLite.js","sources":["../src/sdkLite.ts"],"sourcesContent":["import {\n type RenderOptions,\n addTrackingPixel,\n generateName,\n renderIframe,\n renderInline,\n round,\n uniqueId,\n} from '@adhese/sdk-shared';\n\ntype RenderMode = 'iframe' | 'inline';\n\nexport type AdheseLiteSlotOptions = {\n containingElement?: HTMLElement;\n format: string;\n account: string;\n location: string;\n host?: string;\n renderMode?: RenderMode;\n parameters?: Record<string, string | ReadonlyArray<string>>;\n slot?: string;\n consent?: boolean | string;\n clickTrackerUrl?: string | URL;\n onDispose?(slot: AdheseLiteSlot): void;\n onRender?(slot: AdheseLiteSlot): void;\n onRequest?(slot: AdheseLiteSlot): void;\n onEmpty?(slot: AdheseLiteSlot): void;\n};\n\nexport type AdheseLiteSlot = {\n options: AdheseLiteSlotOptions;\n name: string;\n data?: AdheseLiteAd;\n parameters: Record<string, string | ReadonlyArray<string>>;\n element: HTMLElement;\n render(): Promise<HTMLElement>;\n request(): Promise<AdheseLiteAd | null>;\n dispose(): void;\n};\n\nexport type AdheseLiteAd = {\n tag: string;\n width?: string;\n height?: string;\n impressionCounter?: string;\n viewableImpressionCounter?: string;\n};\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n};\n\nexport function createSlot(options: AdheseLiteSlotOptions): AdheseLiteSlot {\n const name = generateName(options.location, options.format, options.slot);\n\n const trackingPixels = new Set<HTMLImageElement>();\n\n const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {\n rootMargin: '200px',\n threshold: 0,\n });\n\n const viewabilityTrackingIntersectionObserver = new IntersectionObserver(onViewabilityIntersection, {\n rootMargin: '0px',\n threshold: Array.from({ length: 11 }, (_, i) => i * 0.1),\n });\n\n const consentParameters: {\n tl: 'all' | 'none';\n } | {\n xt: string;\n } = typeof options.consent === 'string'\n ? {\n xt: options.consent,\n }\n : {\n tl: options.consent ? 'all' : 'none',\n };\n\n const parameters = {\n ...options.parameters,\n ...consentParameters,\n };\n\n let isImpressionTracked = false;\n\n const element = options.containingElement ?? document.createElement('div');\n\n if (!options.containingElement) {\n element.id = `${name}:${uniqueId(3)}`;\n element.classList.add('adunit');\n element.dataset.format = options.format;\n element.dataset.slot = options.format;\n element.dataset.location = options.location;\n\n document.currentScript?.insertAdjacentElement('beforebegin', element);\n }\n\n const context: AdheseLiteSlot = {\n options,\n name,\n parameters,\n element,\n async request(): Promise<AdheseLiteAd | null> {\n const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {\n method: 'POST',\n body: JSON.stringify({\n slots: [{\n slotname: name,\n }],\n parameters,\n }),\n headers: {\n // eslint-disable-next-line ts/naming-convention\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok)\n throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);\n\n const [data] = await response.json() as ReadonlyArray<AdheseLiteAd>;\n\n this.data = data;\n\n options.onRequest?.(this);\n\n return data;\n },\n async render(): Promise<HTMLElement> {\n const data = this.data ?? (await this.request());\n element.removeEventListener('click', onClick);\n\n if (!data) {\n options.onEmpty?.(this);\n\n return element;\n }\n\n if (typeof data.tag !== 'string')\n throw new Error('Received invalid ad data, tag is not a string');\n\n renderFunctions[options.renderMode ?? 'iframe'](data, element);\n\n options.onRender?.(this);\n\n if (data.impressionCounter && !isImpressionTracked) {\n trackingPixels.add(addTrackingPixel(data.impressionCounter));\n isImpressionTracked = true;\n }\n\n if (data.viewableImpressionCounter) {\n viewabilityTrackingIntersectionObserver.observe(element);\n }\n\n element.addEventListener('click', onClick);\n\n return element;\n },\n dispose(): void {\n options.onDispose?.(this);\n\n element.innerHTML = '';\n\n for (const pixel of trackingPixels) {\n pixel.remove();\n }\n trackingPixels.clear();\n\n renderIntersectionObserver?.disconnect();\n viewabilityTrackingIntersectionObserver.disconnect();\n\n element.removeEventListener('click', onClick);\n },\n };\n\n let isClickTracked = false;\n function onClick(): void {\n if (options.clickTrackerUrl && !isClickTracked) {\n trackingPixels.add(addTrackingPixel(options.clickTrackerUrl));\n isClickTracked = true;\n }\n }\n\n let timeoutId: number | null = null;\n function onViewabilityIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n const ratio = round(entry.intersectionRatio, 1);\n const threshold = 0.2;\n\n if (ratio >= threshold && !timeoutId) {\n // @ts-expect-error The is misfiring to the Node type\n timeoutId = setTimeout(() => {\n timeoutId = null;\n viewabilityTrackingIntersectionObserver.disconnect();\n\n if (context.data?.viewableImpressionCounter) {\n trackingPixels.add(addTrackingPixel(context.data?.viewableImpressionCounter));\n }\n }, 1000);\n }\n else if (ratio < threshold && timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function onRenderIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n if (entry.isIntersecting) {\n context.render().catch(console.error);\n renderIntersectionObserver?.disconnect();\n }\n }\n renderIntersectionObserver.observe(element);\n return context;\n}\n\nexport { version } from '../package.json';\n"],"names":["_a"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"sdkLite.js","sources":["../src/sdkLite.ts"],"sourcesContent":["import {\n type RenderOptions,\n addTrackingPixel,\n generateName,\n pick,\n renderIframe,\n renderInline,\n round,\n uniqueId,\n} from '@adhese/sdk-shared';\n\ntype RenderMode = 'iframe' | 'inline';\n\nexport type AdheseLiteSlotOptions = {\n containingElement?: HTMLElement;\n format: string;\n account: string;\n location: string;\n host?: string;\n renderMode?: RenderMode;\n width?: string | number;\n height?: string | number;\n parameters?: Record<string, string | ReadonlyArray<string>>;\n slot?: string;\n consent?: boolean | string;\n clickTrackerUrl?: string | URL;\n onDispose?(slot: AdheseLiteSlot): void;\n onRender?(slot: AdheseLiteSlot): void;\n onRequest?(slot: AdheseLiteSlot): void;\n onEmpty?(slot: AdheseLiteSlot): void;\n};\n\nexport type AdheseLiteSlot = {\n options: AdheseLiteSlotOptions;\n name: string;\n data?: AdheseLiteAd;\n parameters: Record<string, string | ReadonlyArray<string>>;\n element: HTMLElement;\n render(): Promise<HTMLElement>;\n request(): Promise<AdheseLiteAd | null>;\n dispose(): void;\n};\n\nexport type AdheseLiteAd = {\n tag: string;\n width?: string;\n height?: string;\n impressionCounter?: string;\n viewableImpressionCounter?: string;\n};\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n};\n\nexport function createSlot(options: AdheseLiteSlotOptions): AdheseLiteSlot {\n const name = generateName(options.location, options.format, options.slot);\n\n const trackingPixels = new Set<HTMLImageElement>();\n\n const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {\n rootMargin: '200px',\n threshold: 0,\n });\n\n const viewabilityTrackingIntersectionObserver = new IntersectionObserver(onViewabilityIntersection, {\n rootMargin: '0px',\n threshold: Array.from({ length: 11 }, (_, i) => i * 0.1),\n });\n\n const consentParameters: {\n tl: 'all' | 'none';\n } | {\n xt: string;\n } = typeof options.consent === 'string'\n ? {\n xt: options.consent,\n }\n : {\n tl: options.consent ? 'all' : 'none',\n };\n\n const parameters = {\n ...options.parameters,\n ...consentParameters,\n };\n\n let isImpressionTracked = false;\n\n const element = options.containingElement ?? document.createElement('div');\n\n if (!options.containingElement) {\n element.id = `${name}:${uniqueId(3)}`;\n element.classList.add('adunit');\n element.dataset.format = options.format;\n element.dataset.slot = options.format;\n element.dataset.location = options.location;\n\n document.currentScript?.insertAdjacentElement('beforebegin', element);\n }\n\n const context: AdheseLiteSlot = {\n options,\n name,\n parameters,\n element,\n async request(): Promise<AdheseLiteAd | null> {\n const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {\n method: 'POST',\n body: JSON.stringify({\n slots: [{\n slotname: name,\n }],\n parameters,\n }),\n headers: {\n // eslint-disable-next-line ts/naming-convention\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok)\n throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);\n\n const [data] = await response.json() as ReadonlyArray<AdheseLiteAd>;\n\n this.data = data;\n\n options.onRequest?.(this);\n\n return data;\n },\n async render(): Promise<HTMLElement> {\n const data = this.data ?? (await this.request());\n element.removeEventListener('click', onClick);\n\n if (!data) {\n options.onEmpty?.(this);\n\n return element;\n }\n\n if (typeof data.tag !== 'string')\n throw new Error('Received invalid ad data, tag is not a string');\n\n renderFunctions[options.renderMode ?? 'iframe']({\n ...data,\n ...pick(options, ['width', 'height']),\n }, element);\n\n options.onRender?.(this);\n\n if (data.impressionCounter && !isImpressionTracked) {\n trackingPixels.add(addTrackingPixel(data.impressionCounter));\n isImpressionTracked = true;\n }\n\n if (data.viewableImpressionCounter) {\n viewabilityTrackingIntersectionObserver.observe(element);\n }\n\n element.addEventListener('click', onClick);\n\n return element;\n },\n dispose(): void {\n options.onDispose?.(this);\n\n element.innerHTML = '';\n\n for (const pixel of trackingPixels) {\n pixel.remove();\n }\n trackingPixels.clear();\n\n renderIntersectionObserver?.disconnect();\n viewabilityTrackingIntersectionObserver.disconnect();\n\n element.removeEventListener('click', onClick);\n },\n };\n\n let isClickTracked = false;\n function onClick(): void {\n if (options.clickTrackerUrl && !isClickTracked) {\n trackingPixels.add(addTrackingPixel(options.clickTrackerUrl));\n isClickTracked = true;\n }\n }\n\n let timeoutId: number | null = null;\n function onViewabilityIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n const ratio = round(entry.intersectionRatio, 1);\n const threshold = 0.2;\n\n if (ratio >= threshold && !timeoutId) {\n // @ts-expect-error The is misfiring to the Node type\n timeoutId = setTimeout(() => {\n timeoutId = null;\n viewabilityTrackingIntersectionObserver.disconnect();\n\n if (context.data?.viewableImpressionCounter) {\n trackingPixels.add(addTrackingPixel(context.data?.viewableImpressionCounter));\n }\n }, 1000);\n }\n else if (ratio < threshold && timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function onRenderIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n if (entry.isIntersecting) {\n context.render().catch(console.error);\n renderIntersectionObserver?.disconnect();\n }\n }\n renderIntersectionObserver.observe(element);\n return context;\n}\n\nexport { version } from '../package.json';\n"],"names":["_a"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhese/sdk-lite",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"description": "Adhese SDK",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -31,6 +31,6 @@
|
|
|
31
31
|
"prepareRelease": "npm run build"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@adhese/sdk-shared": "^1.
|
|
34
|
+
"@adhese/sdk-shared": "^1.1.0"
|
|
35
35
|
}
|
|
36
36
|
}
|