@adhese/sdk-lite 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/cjs/sdkLite.cjs +8 -19
- package/dist/cjs/sdkLite.cjs.map +1 -1
- package/dist/sdkLite.d.ts +2 -4
- package/dist/sdkLite.js +10 -21
- package/dist/sdkLite.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/cjs/sdkLite.cjs
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const sdkShared = require("@adhese/sdk-shared");
|
|
4
|
-
const
|
|
5
|
-
const version = "1.1.0";
|
|
4
|
+
const version = "1.1.1";
|
|
6
5
|
const renderFunctions = {
|
|
7
6
|
iframe: sdkShared.renderIframe,
|
|
8
7
|
inline: sdkShared.renderInline
|
|
9
8
|
};
|
|
10
9
|
function createSlot(options) {
|
|
11
10
|
var _a;
|
|
12
|
-
const
|
|
13
|
-
scope: `${name}@${version}`,
|
|
14
|
-
minLogLevelThreshold: options.debug ? "debug" : "info"
|
|
15
|
-
});
|
|
16
|
-
const name$1 = sdkShared.generateName(options.location, options.format, options.slot);
|
|
11
|
+
const name = sdkShared.generateName(options.location, options.format, options.slot);
|
|
17
12
|
const trackingPixels = /* @__PURE__ */ new Set();
|
|
18
13
|
const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {
|
|
19
14
|
rootMargin: "200px",
|
|
@@ -35,7 +30,7 @@ function createSlot(options) {
|
|
|
35
30
|
let isImpressionTracked = false;
|
|
36
31
|
const element = options.containingElement ?? document.createElement("div");
|
|
37
32
|
if (!options.containingElement) {
|
|
38
|
-
element.id = `${name
|
|
33
|
+
element.id = `${name}:${sdkShared.uniqueId(3)}`;
|
|
39
34
|
element.classList.add("adunit");
|
|
40
35
|
element.dataset.format = options.format;
|
|
41
36
|
element.dataset.slot = options.format;
|
|
@@ -44,18 +39,16 @@ function createSlot(options) {
|
|
|
44
39
|
}
|
|
45
40
|
const context = {
|
|
46
41
|
options,
|
|
47
|
-
name
|
|
48
|
-
logger,
|
|
42
|
+
name,
|
|
49
43
|
parameters,
|
|
50
44
|
element,
|
|
51
45
|
async request() {
|
|
52
46
|
var _a2;
|
|
53
|
-
logger.debug(`Requesting ad for slot ${name$1}`, this);
|
|
54
47
|
const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {
|
|
55
48
|
method: "POST",
|
|
56
49
|
body: JSON.stringify({
|
|
57
50
|
slots: [{
|
|
58
|
-
slotname: name
|
|
51
|
+
slotname: name
|
|
59
52
|
}],
|
|
60
53
|
parameters
|
|
61
54
|
}),
|
|
@@ -65,10 +58,9 @@ function createSlot(options) {
|
|
|
65
58
|
}
|
|
66
59
|
});
|
|
67
60
|
if (!response.ok)
|
|
68
|
-
throw new Error(`Failed to request ad for slot ${name
|
|
61
|
+
throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);
|
|
69
62
|
const [data] = await response.json();
|
|
70
63
|
this.data = data;
|
|
71
|
-
logger.debug(`Received ad data for slot ${name$1}`, this);
|
|
72
64
|
(_a2 = options.onRequest) == null ? void 0 : _a2.call(options, this);
|
|
73
65
|
return data;
|
|
74
66
|
},
|
|
@@ -78,14 +70,12 @@ function createSlot(options) {
|
|
|
78
70
|
element.removeEventListener("click", onClick);
|
|
79
71
|
if (!data) {
|
|
80
72
|
(_a2 = options.onEmpty) == null ? void 0 : _a2.call(options, this);
|
|
81
|
-
logger.debug(`Slot ${name$1} is empty`, this);
|
|
82
73
|
return element;
|
|
83
74
|
}
|
|
84
75
|
if (typeof data.tag !== "string")
|
|
85
76
|
throw new Error("Received invalid ad data, tag is not a string");
|
|
86
77
|
renderFunctions[options.renderMode ?? "iframe"](data, element);
|
|
87
78
|
(_b = options.onRender) == null ? void 0 : _b.call(options, this);
|
|
88
|
-
logger.debug(`Rendered slot ${name$1}`, this);
|
|
89
79
|
if (data.impressionCounter && !isImpressionTracked) {
|
|
90
80
|
trackingPixels.add(sdkShared.addTrackingPixel(data.impressionCounter));
|
|
91
81
|
isImpressionTracked = true;
|
|
@@ -107,8 +97,6 @@ function createSlot(options) {
|
|
|
107
97
|
renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
|
|
108
98
|
viewabilityTrackingIntersectionObserver.disconnect();
|
|
109
99
|
element.removeEventListener("click", onClick);
|
|
110
|
-
logger.debug(`Disposing slot ${name$1}`, this);
|
|
111
|
-
logger.resetLogs();
|
|
112
100
|
}
|
|
113
101
|
};
|
|
114
102
|
let isClickTracked = false;
|
|
@@ -138,7 +126,7 @@ function createSlot(options) {
|
|
|
138
126
|
}
|
|
139
127
|
function onRenderIntersection([entry]) {
|
|
140
128
|
if (entry.isIntersecting) {
|
|
141
|
-
context.render().catch(
|
|
129
|
+
context.render().catch(console.error);
|
|
142
130
|
renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
|
|
143
131
|
}
|
|
144
132
|
}
|
|
@@ -146,4 +134,5 @@ function createSlot(options) {
|
|
|
146
134
|
return context;
|
|
147
135
|
}
|
|
148
136
|
exports.createSlot = createSlot;
|
|
137
|
+
exports.version = version;
|
|
149
138
|
//# sourceMappingURL=sdkLite.cjs.map
|
package/dist/cjs/sdkLite.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdkLite.cjs","sources":["../../src/sdkLite.ts"],"sourcesContent":["import {\n type DefaultLogLevels,\n type Logger,\n type RenderOptions,\n addTrackingPixel,\n createLogger,\n generateName,\n renderIframe,\n renderInline,\n round,\n uniqueId,\n} from '@adhese/sdk-shared';\nimport { name as packageName, version } from '../package.json';\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 debug?: boolean;\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 logger: Logger<DefaultLogLevels>;\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 logger = createLogger({\n scope: `${packageName}@${version}`,\n minLogLevelThreshold: options.debug ? 'debug' : 'info',\n });\n\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 logger,\n parameters,\n element,\n async request(): Promise<AdheseLiteAd | null> {\n logger.debug(`Requesting ad for slot ${name}`, this);\n\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 logger.debug(`Received ad data for slot ${name}`, this);\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 logger.debug(`Slot ${name} is empty`, 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 logger.debug(`Rendered slot ${name}`, 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 logger.debug(`Disposing slot ${name}`, this);\n\n logger.resetLogs();\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(logger.error);\n renderIntersectionObserver?.disconnect();\n }\n }\n renderIntersectionObserver.observe(element);\n return context;\n}\n"],"names":["renderIframe","renderInline","createLogger","packageName","name","generateName","uniqueId","_a","addTrackingPixel","round"],"mappings":"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"}
|
|
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":"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"}
|
package/dist/sdkLite.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
var version = "1.1.1";
|
|
2
2
|
|
|
3
3
|
type RenderMode = 'iframe' | 'inline';
|
|
4
4
|
type AdheseLiteSlotOptions = {
|
|
@@ -7,7 +7,6 @@ type AdheseLiteSlotOptions = {
|
|
|
7
7
|
account: string;
|
|
8
8
|
location: string;
|
|
9
9
|
host?: string;
|
|
10
|
-
debug?: boolean;
|
|
11
10
|
renderMode?: RenderMode;
|
|
12
11
|
parameters?: Record<string, string | ReadonlyArray<string>>;
|
|
13
12
|
slot?: string;
|
|
@@ -22,7 +21,6 @@ type AdheseLiteSlot = {
|
|
|
22
21
|
options: AdheseLiteSlotOptions;
|
|
23
22
|
name: string;
|
|
24
23
|
data?: AdheseLiteAd;
|
|
25
|
-
logger: Logger<DefaultLogLevels>;
|
|
26
24
|
parameters: Record<string, string | ReadonlyArray<string>>;
|
|
27
25
|
element: HTMLElement;
|
|
28
26
|
render(): Promise<HTMLElement>;
|
|
@@ -38,4 +36,4 @@ type AdheseLiteAd = {
|
|
|
38
36
|
};
|
|
39
37
|
declare function createSlot(options: AdheseLiteSlotOptions): AdheseLiteSlot;
|
|
40
38
|
|
|
41
|
-
export { type AdheseLiteAd, type AdheseLiteSlot, type AdheseLiteSlotOptions, createSlot };
|
|
39
|
+
export { type AdheseLiteAd, type AdheseLiteSlot, type AdheseLiteSlotOptions, createSlot, version };
|
package/dist/sdkLite.js
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const
|
|
3
|
-
const version = "1.1.0";
|
|
1
|
+
import { generateName, uniqueId, round, addTrackingPixel, renderIframe, renderInline } from "@adhese/sdk-shared";
|
|
2
|
+
const version = "1.1.1";
|
|
4
3
|
const renderFunctions = {
|
|
5
4
|
iframe: renderIframe,
|
|
6
5
|
inline: renderInline
|
|
7
6
|
};
|
|
8
7
|
function createSlot(options) {
|
|
9
8
|
var _a;
|
|
10
|
-
const
|
|
11
|
-
scope: `${name}@${version}`,
|
|
12
|
-
minLogLevelThreshold: options.debug ? "debug" : "info"
|
|
13
|
-
});
|
|
14
|
-
const name$1 = generateName(options.location, options.format, options.slot);
|
|
9
|
+
const name = generateName(options.location, options.format, options.slot);
|
|
15
10
|
const trackingPixels = /* @__PURE__ */ new Set();
|
|
16
11
|
const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {
|
|
17
12
|
rootMargin: "200px",
|
|
@@ -33,7 +28,7 @@ function createSlot(options) {
|
|
|
33
28
|
let isImpressionTracked = false;
|
|
34
29
|
const element = options.containingElement ?? document.createElement("div");
|
|
35
30
|
if (!options.containingElement) {
|
|
36
|
-
element.id = `${name
|
|
31
|
+
element.id = `${name}:${uniqueId(3)}`;
|
|
37
32
|
element.classList.add("adunit");
|
|
38
33
|
element.dataset.format = options.format;
|
|
39
34
|
element.dataset.slot = options.format;
|
|
@@ -42,18 +37,16 @@ function createSlot(options) {
|
|
|
42
37
|
}
|
|
43
38
|
const context = {
|
|
44
39
|
options,
|
|
45
|
-
name
|
|
46
|
-
logger,
|
|
40
|
+
name,
|
|
47
41
|
parameters,
|
|
48
42
|
element,
|
|
49
43
|
async request() {
|
|
50
44
|
var _a2;
|
|
51
|
-
logger.debug(`Requesting ad for slot ${name$1}`, this);
|
|
52
45
|
const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {
|
|
53
46
|
method: "POST",
|
|
54
47
|
body: JSON.stringify({
|
|
55
48
|
slots: [{
|
|
56
|
-
slotname: name
|
|
49
|
+
slotname: name
|
|
57
50
|
}],
|
|
58
51
|
parameters
|
|
59
52
|
}),
|
|
@@ -63,10 +56,9 @@ function createSlot(options) {
|
|
|
63
56
|
}
|
|
64
57
|
});
|
|
65
58
|
if (!response.ok)
|
|
66
|
-
throw new Error(`Failed to request ad for slot ${name
|
|
59
|
+
throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);
|
|
67
60
|
const [data] = await response.json();
|
|
68
61
|
this.data = data;
|
|
69
|
-
logger.debug(`Received ad data for slot ${name$1}`, this);
|
|
70
62
|
(_a2 = options.onRequest) == null ? void 0 : _a2.call(options, this);
|
|
71
63
|
return data;
|
|
72
64
|
},
|
|
@@ -76,14 +68,12 @@ function createSlot(options) {
|
|
|
76
68
|
element.removeEventListener("click", onClick);
|
|
77
69
|
if (!data) {
|
|
78
70
|
(_a2 = options.onEmpty) == null ? void 0 : _a2.call(options, this);
|
|
79
|
-
logger.debug(`Slot ${name$1} is empty`, this);
|
|
80
71
|
return element;
|
|
81
72
|
}
|
|
82
73
|
if (typeof data.tag !== "string")
|
|
83
74
|
throw new Error("Received invalid ad data, tag is not a string");
|
|
84
75
|
renderFunctions[options.renderMode ?? "iframe"](data, element);
|
|
85
76
|
(_b = options.onRender) == null ? void 0 : _b.call(options, this);
|
|
86
|
-
logger.debug(`Rendered slot ${name$1}`, this);
|
|
87
77
|
if (data.impressionCounter && !isImpressionTracked) {
|
|
88
78
|
trackingPixels.add(addTrackingPixel(data.impressionCounter));
|
|
89
79
|
isImpressionTracked = true;
|
|
@@ -105,8 +95,6 @@ function createSlot(options) {
|
|
|
105
95
|
renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
|
|
106
96
|
viewabilityTrackingIntersectionObserver.disconnect();
|
|
107
97
|
element.removeEventListener("click", onClick);
|
|
108
|
-
logger.debug(`Disposing slot ${name$1}`, this);
|
|
109
|
-
logger.resetLogs();
|
|
110
98
|
}
|
|
111
99
|
};
|
|
112
100
|
let isClickTracked = false;
|
|
@@ -136,7 +124,7 @@ function createSlot(options) {
|
|
|
136
124
|
}
|
|
137
125
|
function onRenderIntersection([entry]) {
|
|
138
126
|
if (entry.isIntersecting) {
|
|
139
|
-
context.render().catch(
|
|
127
|
+
context.render().catch(console.error);
|
|
140
128
|
renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
|
|
141
129
|
}
|
|
142
130
|
}
|
|
@@ -144,6 +132,7 @@ function createSlot(options) {
|
|
|
144
132
|
return context;
|
|
145
133
|
}
|
|
146
134
|
export {
|
|
147
|
-
createSlot
|
|
135
|
+
createSlot,
|
|
136
|
+
version
|
|
148
137
|
};
|
|
149
138
|
//# sourceMappingURL=sdkLite.js.map
|
package/dist/sdkLite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdkLite.js","sources":["../src/sdkLite.ts"],"sourcesContent":["import {\n type
|
|
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":";;AAgDA,MAAM,kBAAyF;AAAA,EAC7F,QAAQ;AAAA,EACR,QAAQ;AACV;AAEO,SAAS,WAAW,SAAgD;;AACzE,QAAM,OAAO,aAAa,QAAQ,UAAU,QAAQ,QAAQ,QAAQ,IAAI;AAElE,QAAA,qCAAqB;AAErB,QAAA,6BAA6B,IAAI,qBAAqB,sBAAsB;AAAA,IAChF,YAAY;AAAA,IACZ,WAAW;AAAA,EAAA,CACZ;AAEK,QAAA,0CAA0C,IAAI,qBAAqB,2BAA2B;AAAA,IAClG,YAAY;AAAA,IACZ,WAAW,MAAM,KAAK,EAAE,QAAQ,MAAM,CAAC,GAAG,MAAM,IAAI,GAAG;AAAA,EAAA,CACxD;AAED,QAAM,oBAIF,OAAO,QAAQ,YAAY,WAC3B;AAAA,IACE,IAAI,QAAQ;AAAA,EAAA,IAEd;AAAA,IACE,IAAI,QAAQ,UAAU,QAAQ;AAAA,EAAA;AAGpC,QAAM,aAAa;AAAA,IACjB,GAAG,QAAQ;AAAA,IACX,GAAG;AAAA,EAAA;AAGL,MAAI,sBAAsB;AAE1B,QAAM,UAAU,QAAQ,qBAAqB,SAAS,cAAc,KAAK;AAErE,MAAA,CAAC,QAAQ,mBAAmB;AAC9B,YAAQ,KAAK,GAAG,IAAI,IAAI,SAAS,CAAC,CAAC;AAC3B,YAAA,UAAU,IAAI,QAAQ;AACtB,YAAA,QAAQ,SAAS,QAAQ;AACzB,YAAA,QAAQ,OAAO,QAAQ;AACvB,YAAA,QAAQ,WAAW,QAAQ;AAE1B,mBAAA,kBAAA,mBAAe,sBAAsB,eAAe;AAAA,EAC/D;AAEA,QAAM,UAA0B;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,UAAwC;;AACtC,YAAA,WAAW,MAAM,MAAM,GAAG,QAAQ,QAAQ,eAAe,QAAQ,OAAO,aAAa,SAAS;AAAA,QAClG,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU;AAAA,UACnB,OAAO,CAAC;AAAA,YACN,UAAU;AAAA,UAAA,CACX;AAAA,UACD;AAAA,QAAA,CACD;AAAA,QACD,SAAS;AAAA;AAAA,UAEP,gBAAgB;AAAA,QAClB;AAAA,MAAA,CACD;AAED,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,iCAAiC,IAAI,aAAa,SAAS,MAAM,EAAE;AAErF,YAAM,CAAC,IAAI,IAAI,MAAM,SAAS,KAAK;AAEnC,WAAK,OAAO;AAEZ,OAAAA,MAAA,QAAQ,cAAR,gBAAAA,IAAA,cAAoB;AAEb,aAAA;AAAA,IACT;AAAA,IACA,MAAM,SAA+B;;AACnC,YAAM,OAAO,KAAK,QAAS,MAAM,KAAK,QAAQ;AACtC,cAAA,oBAAoB,SAAS,OAAO;AAE5C,UAAI,CAAC,MAAM;AACT,SAAAA,MAAA,QAAQ,YAAR,gBAAAA,IAAA,cAAkB;AAEX,eAAA;AAAA,MACT;AAEI,UAAA,OAAO,KAAK,QAAQ;AAChB,cAAA,IAAI,MAAM,+CAA+C;AAEjE,sBAAgB,QAAQ,cAAc,QAAQ,EAAE,MAAM,OAAO;AAE7D,oBAAQ,aAAR,iCAAmB;AAEf,UAAA,KAAK,qBAAqB,CAAC,qBAAqB;AAClD,uBAAe,IAAI,iBAAiB,KAAK,iBAAiB,CAAC;AACrC,8BAAA;AAAA,MACxB;AAEA,UAAI,KAAK,2BAA2B;AAClC,gDAAwC,QAAQ,OAAO;AAAA,MACzD;AAEQ,cAAA,iBAAiB,SAAS,OAAO;AAElC,aAAA;AAAA,IACT;AAAA,IACA,UAAgB;;AACd,OAAAA,MAAA,QAAQ,cAAR,gBAAAA,IAAA,cAAoB;AAEpB,cAAQ,YAAY;AAEpB,iBAAW,SAAS,gBAAgB;AAClC,cAAM,OAAO;AAAA,MACf;AACA,qBAAe,MAAM;AAErB,+EAA4B;AAC5B,8CAAwC,WAAW;AAE3C,cAAA,oBAAoB,SAAS,OAAO;AAAA,IAC9C;AAAA,EAAA;AAGF,MAAI,iBAAiB;AACrB,WAAS,UAAgB;AACnB,QAAA,QAAQ,mBAAmB,CAAC,gBAAgB;AAC9C,qBAAe,IAAI,iBAAiB,QAAQ,eAAe,CAAC;AAC3C,uBAAA;AAAA,IACnB;AAAA,EACF;AAEA,MAAI,YAA2B;AACtB,WAAA,0BAA0B,CAAC,KAAK,GAAmD;AAC1F,UAAM,QAAQ,MAAM,MAAM,mBAAmB,CAAC;AAC9C,UAAM,YAAY;AAEd,QAAA,SAAS,aAAa,CAAC,WAAW;AAEpC,kBAAY,WAAW,MAAM;;AACf,oBAAA;AACZ,gDAAwC,WAAW;AAE/C,aAAAA,MAAA,QAAQ,SAAR,gBAAAA,IAAc,2BAA2B;AAC3C,yBAAe,IAAI,kBAAiB,aAAQ,SAAR,mBAAc,yBAAyB,CAAC;AAAA,QAC9E;AAAA,SACC,GAAI;AAAA,IAAA,WAEA,QAAQ,aAAa,WAAW;AACvC,mBAAa,SAAS;AACV,kBAAA;AAAA,IACd;AAAA,EACF;AAES,WAAA,qBAAqB,CAAC,KAAK,GAAmD;AACrF,QAAI,MAAM,gBAAgB;AACxB,cAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK;AACpC,+EAA4B;AAAA,IAC9B;AAAA,EACF;AACA,6BAA2B,QAAQ,OAAO;AACnC,SAAA;AACT;"}
|