@adhese/sdk 0.4.0 → 0.5.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/dist/cjs/index.js +604 -508
- package/dist/cjs/index.js.map +1 -1
- package/dist/es/index.js +606 -510
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +58 -77
- package/package.json +3 -2
package/dist/es/index.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField = (obj, key, value) => {
|
|
4
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
-
return value;
|
|
6
|
-
};
|
|
7
1
|
import { createDevtools } from "@adhese/sdk-devtools";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
2
|
+
import { effectScope, shallowReactive, watchEffect, watch, reactive, ref, computed, toValue } from "@vue/runtime-core";
|
|
3
|
+
import { debounce, uniqueId, random, round, isEqual } from "lodash-es";
|
|
4
|
+
import { union, coerce, literal, number, string, ZodIssueCode, NEVER, object, unknown, lazy } from "zod";
|
|
10
5
|
async function waitForDomLoad() {
|
|
11
6
|
return new Promise((resolve) => {
|
|
12
7
|
function onDomLoad() {
|
|
@@ -66,91 +61,132 @@ function createEvent() {
|
|
|
66
61
|
removeListener
|
|
67
62
|
};
|
|
68
63
|
}
|
|
64
|
+
function renderIframe(ad, element) {
|
|
65
|
+
const iframe = document.createElement("iframe");
|
|
66
|
+
iframe.srcdoc = `
|
|
67
|
+
<!DOCTYPE html>
|
|
68
|
+
<html>
|
|
69
|
+
<head>
|
|
70
|
+
<style>
|
|
71
|
+
body {
|
|
72
|
+
margin: 0;
|
|
73
|
+
padding: 0;
|
|
74
|
+
overflow: hidden;
|
|
75
|
+
}
|
|
76
|
+
</style>
|
|
77
|
+
</head>
|
|
78
|
+
<body>
|
|
79
|
+
${String(ad.tag)}
|
|
80
|
+
</body>
|
|
81
|
+
`.replaceAll(/\s+/g, " ").trim();
|
|
82
|
+
iframe.style.border = "none";
|
|
83
|
+
iframe.style.width = ad.width ?? "auto";
|
|
84
|
+
iframe.style.height = ad.height ?? "auto";
|
|
85
|
+
element.replaceChildren(iframe);
|
|
86
|
+
}
|
|
87
|
+
function renderInline(ad, element) {
|
|
88
|
+
element.style.width = ad.width ?? "auto";
|
|
89
|
+
element.style.height = ad.height ?? "auto";
|
|
90
|
+
element.innerHTML = String(ad.tag);
|
|
91
|
+
}
|
|
92
|
+
function generateName(location, format, slot) {
|
|
93
|
+
return `${location}${slot ? `${slot}` : ""}-${format}`;
|
|
94
|
+
}
|
|
69
95
|
async function findDomSlots(context) {
|
|
70
96
|
await waitForDomLoad();
|
|
71
|
-
return
|
|
97
|
+
return Array.from(document.querySelectorAll(".adunit")).filter((element) => {
|
|
98
|
+
var _a;
|
|
99
|
+
if (!element.dataset.format)
|
|
100
|
+
return false;
|
|
101
|
+
const name = generateName(
|
|
102
|
+
context.location,
|
|
103
|
+
element.dataset.format,
|
|
104
|
+
element.dataset.slot
|
|
105
|
+
);
|
|
106
|
+
return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === name));
|
|
107
|
+
}).map((element) => createSlot({
|
|
72
108
|
format: element.dataset.format,
|
|
73
109
|
containingElement: element,
|
|
74
110
|
slot: element.dataset.slot,
|
|
75
111
|
context
|
|
76
|
-
}))
|
|
112
|
+
})).filter((slot) => {
|
|
77
113
|
var _a;
|
|
78
|
-
return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.
|
|
114
|
+
return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === slot.name.value));
|
|
79
115
|
});
|
|
80
116
|
}
|
|
81
|
-
|
|
117
|
+
function createSlotManager({
|
|
82
118
|
initialSlots = [],
|
|
83
119
|
context
|
|
84
120
|
}) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return Array.from(slots).map(([, slot]) => slot);
|
|
92
|
-
}
|
|
93
|
-
async function add(options) {
|
|
94
|
-
var _a, _b;
|
|
95
|
-
const slot = await createSlot({
|
|
96
|
-
...options,
|
|
97
|
-
onDispose,
|
|
98
|
-
onNameChange,
|
|
99
|
-
context
|
|
121
|
+
const scope = effectScope();
|
|
122
|
+
return scope.run(() => {
|
|
123
|
+
const slots = shallowReactive(/* @__PURE__ */ new Map());
|
|
124
|
+
watchEffect(() => {
|
|
125
|
+
var _a;
|
|
126
|
+
(_a = context.events) == null ? void 0 : _a.changeSlots.dispatch(Array.from(slots.values()));
|
|
100
127
|
});
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
128
|
+
function getAll() {
|
|
129
|
+
return Array.from(slots).map(([, slot]) => slot);
|
|
130
|
+
}
|
|
131
|
+
function add(options) {
|
|
132
|
+
var _a;
|
|
133
|
+
const slot = createSlot({
|
|
134
|
+
...options,
|
|
135
|
+
onDispose,
|
|
136
|
+
context
|
|
137
|
+
});
|
|
138
|
+
function onDispose() {
|
|
139
|
+
var _a2;
|
|
140
|
+
slots.delete(slot.name.value);
|
|
141
|
+
logger.debug("Slot removed", {
|
|
142
|
+
slot,
|
|
143
|
+
slots: Array.from(slots)
|
|
144
|
+
});
|
|
145
|
+
(_a2 = context.events) == null ? void 0 : _a2.removeSlot.dispatch(slot);
|
|
146
|
+
}
|
|
147
|
+
slots.set(slot.name.value, slot);
|
|
148
|
+
watch(slot.name, (newName, previousName) => {
|
|
149
|
+
slots.set(newName, slot);
|
|
150
|
+
slots.delete(previousName);
|
|
151
|
+
});
|
|
152
|
+
logger.debug("Slot added", {
|
|
105
153
|
slot,
|
|
106
|
-
slots: Array.from(slots)
|
|
154
|
+
slots: Array.from(slots.values())
|
|
107
155
|
});
|
|
108
|
-
(
|
|
109
|
-
|
|
156
|
+
(_a = context.events) == null ? void 0 : _a.addSlot.dispatch(slot);
|
|
157
|
+
return slot;
|
|
110
158
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
159
|
+
async function findDomSlots$1() {
|
|
160
|
+
const domSlots = await findDomSlots(
|
|
161
|
+
context
|
|
162
|
+
);
|
|
163
|
+
for (const slot of domSlots)
|
|
164
|
+
slots.set(slot.name.value, slot);
|
|
165
|
+
return domSlots;
|
|
117
166
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
slots: Array.from(slots.values())
|
|
121
|
-
});
|
|
122
|
-
(_a = context.events) == null ? void 0 : _a.addSlot.dispatch(slot);
|
|
123
|
-
(_b = context.events) == null ? void 0 : _b.changeSlots.dispatch(Array.from(slots.values()));
|
|
124
|
-
return slot;
|
|
125
|
-
}
|
|
126
|
-
async function findDomSlots$1() {
|
|
127
|
-
var _a;
|
|
128
|
-
const domSlots = await findDomSlots(
|
|
129
|
-
context
|
|
130
|
-
);
|
|
131
|
-
for (const slot of domSlots) {
|
|
132
|
-
slots.set(slot.getName(), slot);
|
|
133
|
-
(_a = context.events) == null ? void 0 : _a.changeSlots.dispatch(Array.from(slots.values()));
|
|
167
|
+
function get(name) {
|
|
168
|
+
return slots.get(name);
|
|
134
169
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
170
|
+
function dispose() {
|
|
171
|
+
for (const slot of slots.values())
|
|
172
|
+
slot.dispose();
|
|
173
|
+
slots.clear();
|
|
174
|
+
scope.stop();
|
|
175
|
+
}
|
|
176
|
+
for (const options of initialSlots) {
|
|
177
|
+
add({
|
|
178
|
+
...options,
|
|
179
|
+
lazyLoading: false
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
getAll,
|
|
184
|
+
add,
|
|
185
|
+
findDomSlots: findDomSlots$1,
|
|
186
|
+
get,
|
|
187
|
+
dispose
|
|
188
|
+
};
|
|
189
|
+
});
|
|
154
190
|
}
|
|
155
191
|
function onTcfConsentChange(callback) {
|
|
156
192
|
var _a;
|
|
@@ -270,7 +306,7 @@ const logger = createLogger({
|
|
|
270
306
|
scope: "Adhese SDK"
|
|
271
307
|
});
|
|
272
308
|
function createParameters(options, queryDetector) {
|
|
273
|
-
const parameters = new
|
|
309
|
+
const parameters = /* @__PURE__ */ new Map();
|
|
274
310
|
if (options.logReferrer)
|
|
275
311
|
parameters.set("re", btoa(document.referrer));
|
|
276
312
|
if (options.logUrl)
|
|
@@ -297,230 +333,234 @@ function setupLogging(mergedOptions) {
|
|
|
297
333
|
function isPreviewMode() {
|
|
298
334
|
return window.location.search.includes("adhesePreviewCreativeId");
|
|
299
335
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
336
|
+
function createHook({
|
|
337
|
+
onRun,
|
|
338
|
+
onAdd
|
|
339
|
+
}) {
|
|
340
|
+
const callbacks = /* @__PURE__ */ new Set();
|
|
341
|
+
function run() {
|
|
342
|
+
for (const callback of callbacks)
|
|
343
|
+
callback();
|
|
344
|
+
onRun == null ? void 0 : onRun(callbacks);
|
|
304
345
|
}
|
|
305
|
-
|
|
306
|
-
|
|
346
|
+
function add(callback) {
|
|
347
|
+
callbacks.add(callback);
|
|
348
|
+
onAdd == null ? void 0 : onAdd(callbacks);
|
|
307
349
|
}
|
|
308
|
-
|
|
309
|
-
|
|
350
|
+
return [run, add];
|
|
351
|
+
}
|
|
352
|
+
let resolveOnInitPromise = () => {
|
|
353
|
+
};
|
|
354
|
+
let isInit = false;
|
|
355
|
+
new Promise((resolve) => {
|
|
356
|
+
resolveOnInitPromise = resolve;
|
|
357
|
+
});
|
|
358
|
+
const [runOnInit, onInit] = createHook({
|
|
359
|
+
onRun(callbacks) {
|
|
360
|
+
isInit = true;
|
|
361
|
+
resolveOnInitPromise();
|
|
362
|
+
logger.debug("Initialization completed");
|
|
363
|
+
callbacks.clear();
|
|
364
|
+
},
|
|
365
|
+
onAdd() {
|
|
366
|
+
if (isInit)
|
|
367
|
+
runOnInit();
|
|
310
368
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
369
|
+
});
|
|
370
|
+
function createAdhese(options) {
|
|
371
|
+
const scope = effectScope();
|
|
372
|
+
return scope.run(() => {
|
|
373
|
+
const mergedOptions = {
|
|
374
|
+
host: `https://ads-${options.account}.adhese.com`,
|
|
375
|
+
poolHost: `https://pool-${options.account}.adhese.com`,
|
|
376
|
+
location: "homepage",
|
|
377
|
+
requestType: "POST",
|
|
378
|
+
debug: false,
|
|
379
|
+
initialSlots: [],
|
|
380
|
+
findDomSlotsOnLoad: false,
|
|
381
|
+
consent: false,
|
|
382
|
+
logReferrer: true,
|
|
383
|
+
logUrl: true,
|
|
384
|
+
eagerRendering: false,
|
|
385
|
+
viewabilityTracking: true,
|
|
386
|
+
...options
|
|
387
|
+
};
|
|
388
|
+
setupLogging(mergedOptions);
|
|
389
|
+
const context = reactive({
|
|
390
|
+
location: mergedOptions.location,
|
|
391
|
+
consent: mergedOptions.consent,
|
|
392
|
+
debug: mergedOptions.debug,
|
|
393
|
+
getAll,
|
|
394
|
+
get,
|
|
395
|
+
options: mergedOptions,
|
|
396
|
+
logger
|
|
315
397
|
});
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
398
|
+
context.events = createEventManager();
|
|
399
|
+
function getLocation() {
|
|
400
|
+
return context.location;
|
|
401
|
+
}
|
|
402
|
+
function setLocation(newLocation) {
|
|
403
|
+
var _a;
|
|
404
|
+
context.location = newLocation;
|
|
405
|
+
(_a = context.events) == null ? void 0 : _a.locationChange.dispatch(newLocation);
|
|
406
|
+
}
|
|
407
|
+
const queryDetector = createQueryDetector({
|
|
408
|
+
onChange: onQueryChange,
|
|
409
|
+
queries: mergedOptions.queries
|
|
322
410
|
});
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
411
|
+
context.parameters = createParameters(mergedOptions, queryDetector);
|
|
412
|
+
watch(
|
|
413
|
+
context.parameters,
|
|
414
|
+
onParametersChange,
|
|
415
|
+
{
|
|
416
|
+
deep: true,
|
|
417
|
+
immediate: true
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
function onParametersChange() {
|
|
421
|
+
var _a;
|
|
422
|
+
if (context.parameters)
|
|
423
|
+
(_a = context.events) == null ? void 0 : _a.parametersChange.dispatch(context.parameters);
|
|
424
|
+
}
|
|
425
|
+
async function onQueryChange() {
|
|
426
|
+
var _a, _b;
|
|
427
|
+
const query = queryDetector.getQuery();
|
|
428
|
+
(_a = context.parameters) == null ? void 0 : _a.set("dt", query);
|
|
429
|
+
(_b = context.parameters) == null ? void 0 : _b.set("br", query);
|
|
430
|
+
await fetchAndRenderAllSlots();
|
|
431
|
+
}
|
|
432
|
+
function getConsent() {
|
|
433
|
+
return context.consent;
|
|
434
|
+
}
|
|
435
|
+
function setConsent(newConsent) {
|
|
436
|
+
var _a, _b;
|
|
437
|
+
(_a = context.parameters) == null ? void 0 : _a.set("tl", newConsent ? "all" : "none");
|
|
438
|
+
context.consent = newConsent;
|
|
439
|
+
(_b = context.events) == null ? void 0 : _b.consentChange.dispatch(newConsent);
|
|
440
|
+
}
|
|
441
|
+
const slotManager = createSlotManager({
|
|
442
|
+
initialSlots: mergedOptions.initialSlots,
|
|
443
|
+
context
|
|
328
444
|
});
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
viewabilityTracking: true,
|
|
354
|
-
...options
|
|
355
|
-
};
|
|
356
|
-
setupLogging(mergedOptions);
|
|
357
|
-
const context = new Proxy({
|
|
358
|
-
location: mergedOptions.location,
|
|
359
|
-
consent: mergedOptions.consent,
|
|
360
|
-
debug: mergedOptions.debug,
|
|
361
|
-
getAll,
|
|
362
|
-
get,
|
|
363
|
-
options: mergedOptions,
|
|
364
|
-
logger
|
|
365
|
-
}, {});
|
|
366
|
-
context.events = createEventManager();
|
|
367
|
-
function getLocation() {
|
|
368
|
-
return context.location;
|
|
369
|
-
}
|
|
370
|
-
function setLocation(newLocation) {
|
|
371
|
-
var _a2;
|
|
372
|
-
context.location = newLocation;
|
|
373
|
-
(_a2 = context.events) == null ? void 0 : _a2.locationChange.dispatch(newLocation);
|
|
374
|
-
}
|
|
375
|
-
const queryDetector = createQueryDetector({
|
|
376
|
-
onChange: onQueryChange,
|
|
377
|
-
queries: mergedOptions.queries
|
|
378
|
-
});
|
|
379
|
-
context.parameters = createParameters(mergedOptions, queryDetector);
|
|
380
|
-
context.parameters.addEventListener(onParametersChange);
|
|
381
|
-
let unmountDevtools;
|
|
382
|
-
if (mergedOptions.debug || window.location.search.includes("adhese_debug=true") || isPreviewMode()) {
|
|
383
|
-
unmountDevtools = await createDevtools(context);
|
|
384
|
-
(_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
|
|
385
|
-
}
|
|
386
|
-
function onParametersChange() {
|
|
387
|
-
var _a2;
|
|
388
|
-
if (context.parameters)
|
|
389
|
-
(_a2 = context.events) == null ? void 0 : _a2.parametersChange.dispatch(context.parameters);
|
|
390
|
-
}
|
|
391
|
-
async function onQueryChange() {
|
|
392
|
-
var _a2, _b;
|
|
393
|
-
const query = queryDetector.getQuery();
|
|
394
|
-
(_a2 = context.parameters) == null ? void 0 : _a2.set("dt", query);
|
|
395
|
-
(_b = context.parameters) == null ? void 0 : _b.set("br", query);
|
|
396
|
-
await fetchAndRenderAllSlots();
|
|
397
|
-
}
|
|
398
|
-
function getConsent() {
|
|
399
|
-
return context.consent;
|
|
400
|
-
}
|
|
401
|
-
function setConsent(newConsent) {
|
|
402
|
-
var _a2, _b;
|
|
403
|
-
(_a2 = context.parameters) == null ? void 0 : _a2.set("tl", newConsent ? "all" : "none");
|
|
404
|
-
context.consent = newConsent;
|
|
405
|
-
(_b = context.events) == null ? void 0 : _b.consentChange.dispatch(newConsent);
|
|
406
|
-
}
|
|
407
|
-
const slotManager = await createSlotManager({
|
|
408
|
-
initialSlots: mergedOptions.initialSlots,
|
|
409
|
-
context
|
|
410
|
-
});
|
|
411
|
-
function getAll() {
|
|
412
|
-
return slotManager.getAll();
|
|
413
|
-
}
|
|
414
|
-
function get(name) {
|
|
415
|
-
return slotManager.get(name);
|
|
416
|
-
}
|
|
417
|
-
async function addSlot(slotOptions) {
|
|
418
|
-
const slot = await slotManager.add(slotOptions);
|
|
419
|
-
if (!slot.lazyLoading) {
|
|
420
|
-
const ad = await requestAd({
|
|
421
|
-
slot,
|
|
422
|
-
host: mergedOptions.host,
|
|
423
|
-
parameters: context.parameters,
|
|
424
|
-
account: mergedOptions.account,
|
|
445
|
+
function getAll() {
|
|
446
|
+
return slotManager.getAll() ?? [];
|
|
447
|
+
}
|
|
448
|
+
function get(name) {
|
|
449
|
+
return slotManager.get(name);
|
|
450
|
+
}
|
|
451
|
+
async function addSlot(slotOptions) {
|
|
452
|
+
if (!slotManager)
|
|
453
|
+
throw new Error("Slot manager not initialized");
|
|
454
|
+
const slot = slotManager.add(slotOptions);
|
|
455
|
+
if (!slot.lazyLoading) {
|
|
456
|
+
slot.ad.value = await requestAd({
|
|
457
|
+
slot,
|
|
458
|
+
context
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
return slot;
|
|
462
|
+
}
|
|
463
|
+
async function findDomSlots2() {
|
|
464
|
+
const domSlots = (await slotManager.findDomSlots() ?? []).filter((slot) => !slot.lazyLoading);
|
|
465
|
+
if (domSlots.length <= 0)
|
|
466
|
+
return [];
|
|
467
|
+
const ads = await requestAds({
|
|
468
|
+
slots: domSlots,
|
|
425
469
|
context
|
|
426
470
|
});
|
|
427
|
-
|
|
471
|
+
for (const ad of ads) {
|
|
472
|
+
const slot = slotManager.get(ad.slotName);
|
|
473
|
+
if (slot)
|
|
474
|
+
slot.ad.value = ad;
|
|
475
|
+
}
|
|
476
|
+
return domSlots;
|
|
428
477
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
478
|
+
let unmountDevtools;
|
|
479
|
+
async function toggleDebug() {
|
|
480
|
+
var _a, _b;
|
|
481
|
+
context.debug = !context.debug;
|
|
482
|
+
if (context.debug && !unmountDevtools) {
|
|
483
|
+
unmountDevtools = await createDevtools(context);
|
|
484
|
+
logger.setMinLogLevelThreshold("debug");
|
|
485
|
+
logger.debug("Debug mode enabled");
|
|
486
|
+
(_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
|
|
487
|
+
} else {
|
|
488
|
+
logger.debug("Debug mode disabled");
|
|
489
|
+
unmountDevtools == null ? void 0 : unmountDevtools();
|
|
490
|
+
unmountDevtools = void 0;
|
|
491
|
+
logger.setMinLogLevelThreshold("info");
|
|
492
|
+
(_b = context.events) == null ? void 0 : _b.debugChange.dispatch(false);
|
|
493
|
+
}
|
|
494
|
+
return context.debug;
|
|
495
|
+
}
|
|
496
|
+
async function fetchAndRenderAllSlots() {
|
|
497
|
+
const slots = (slotManager.getAll() ?? []).filter((slot) => !slot.lazyLoading);
|
|
498
|
+
if (slots.length === 0)
|
|
499
|
+
return;
|
|
500
|
+
const ads = await requestAds({
|
|
501
|
+
slots,
|
|
502
|
+
context
|
|
503
|
+
});
|
|
504
|
+
for (const ad of ads) {
|
|
505
|
+
const slot = slotManager.get(ad.slotName);
|
|
506
|
+
if (slot)
|
|
507
|
+
slot.ad.value = ad;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
const disposeOnTcfConsentChange = onTcfConsentChange(async (data) => {
|
|
511
|
+
var _a, _b;
|
|
512
|
+
if (!data.tcString)
|
|
513
|
+
return;
|
|
514
|
+
logger.debug("TCF v2 consent data received", {
|
|
515
|
+
data
|
|
516
|
+
});
|
|
517
|
+
(_a = context.parameters) == null ? void 0 : _a.set("xt", data.tcString);
|
|
518
|
+
(_b = context.parameters) == null ? void 0 : _b.delete("tl");
|
|
519
|
+
await fetchAndRenderAllSlots();
|
|
440
520
|
});
|
|
441
|
-
|
|
442
|
-
var
|
|
443
|
-
return (_a2 = slotManager.get(ad.slotName)) == null ? void 0 : _a2.setAd(ad);
|
|
444
|
-
}));
|
|
445
|
-
return domSlots;
|
|
446
|
-
}
|
|
447
|
-
async function toggleDebug() {
|
|
448
|
-
var _a2, _b;
|
|
449
|
-
context.debug = !context.debug;
|
|
450
|
-
if (context.debug && !unmountDevtools) {
|
|
451
|
-
unmountDevtools = await createDevtools(context);
|
|
452
|
-
logger.setMinLogLevelThreshold("debug");
|
|
453
|
-
logger.debug("Debug mode enabled");
|
|
454
|
-
(_a2 = context.events) == null ? void 0 : _a2.debugChange.dispatch(true);
|
|
455
|
-
} else {
|
|
456
|
-
logger.debug("Debug mode disabled");
|
|
521
|
+
function dispose() {
|
|
522
|
+
var _a, _b;
|
|
457
523
|
unmountDevtools == null ? void 0 : unmountDevtools();
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
524
|
+
queryDetector.dispose();
|
|
525
|
+
slotManager.dispose();
|
|
526
|
+
queryDetector.dispose();
|
|
527
|
+
disposeOnTcfConsentChange();
|
|
528
|
+
(_a = context.parameters) == null ? void 0 : _a.clear();
|
|
529
|
+
logger.resetLogs();
|
|
530
|
+
(_b = context.events) == null ? void 0 : _b.dispose();
|
|
531
|
+
logger.info("Adhese instance disposed");
|
|
532
|
+
scope.stop();
|
|
461
533
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
534
|
+
onInit(async () => {
|
|
535
|
+
var _a;
|
|
536
|
+
if ((slotManager.getAll().length ?? 0) > 0)
|
|
537
|
+
await fetchAndRenderAllSlots().catch(logger.error);
|
|
538
|
+
if (mergedOptions.findDomSlotsOnLoad)
|
|
539
|
+
await findDomSlots2();
|
|
540
|
+
if (mergedOptions.debug || window.location.search.includes("adhese_debug=true") || isPreviewMode()) {
|
|
541
|
+
unmountDevtools = await createDevtools(context);
|
|
542
|
+
(_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
|
|
543
|
+
}
|
|
544
|
+
if (!scope.active)
|
|
545
|
+
dispose();
|
|
546
|
+
});
|
|
547
|
+
runOnInit();
|
|
548
|
+
return {
|
|
549
|
+
...mergedOptions,
|
|
550
|
+
...slotManager,
|
|
473
551
|
parameters: context.parameters,
|
|
552
|
+
events: context.events,
|
|
553
|
+
getLocation,
|
|
554
|
+
setLocation,
|
|
555
|
+
getConsent,
|
|
556
|
+
setConsent,
|
|
557
|
+
addSlot,
|
|
558
|
+
findDomSlots: findDomSlots2,
|
|
559
|
+
dispose,
|
|
560
|
+
toggleDebug,
|
|
474
561
|
context
|
|
475
|
-
}
|
|
476
|
-
await Promise.allSettled(ads.map((ad) => {
|
|
477
|
-
var _a2;
|
|
478
|
-
return (_a2 = slotManager.get(ad.slotName)) == null ? void 0 : _a2.setAd(ad);
|
|
479
|
-
}));
|
|
480
|
-
}
|
|
481
|
-
const disposeOnTcfConsentChange = onTcfConsentChange(async (data) => {
|
|
482
|
-
var _a2, _b;
|
|
483
|
-
if (!data.tcString)
|
|
484
|
-
return;
|
|
485
|
-
logger.debug("TCF v2 consent data received", {
|
|
486
|
-
data
|
|
487
|
-
});
|
|
488
|
-
(_a2 = context.parameters) == null ? void 0 : _a2.set("xt", data.tcString);
|
|
489
|
-
(_b = context.parameters) == null ? void 0 : _b.delete("tl");
|
|
490
|
-
await fetchAndRenderAllSlots();
|
|
562
|
+
};
|
|
491
563
|
});
|
|
492
|
-
if (slotManager.getAll().length > 0)
|
|
493
|
-
await fetchAndRenderAllSlots().catch(logger.error);
|
|
494
|
-
function dispose() {
|
|
495
|
-
var _a2, _b, _c;
|
|
496
|
-
queryDetector.dispose();
|
|
497
|
-
slotManager.dispose();
|
|
498
|
-
queryDetector.dispose();
|
|
499
|
-
disposeOnTcfConsentChange();
|
|
500
|
-
(_a2 = context.parameters) == null ? void 0 : _a2.dispose();
|
|
501
|
-
(_b = context.parameters) == null ? void 0 : _b.clear();
|
|
502
|
-
logger.resetLogs();
|
|
503
|
-
(_c = context.events) == null ? void 0 : _c.dispose();
|
|
504
|
-
unmountDevtools == null ? void 0 : unmountDevtools();
|
|
505
|
-
logger.info("Adhese instance disposed");
|
|
506
|
-
}
|
|
507
|
-
if (mergedOptions.findDomSlotsOnLoad)
|
|
508
|
-
await slotManager.findDomSlots();
|
|
509
|
-
return {
|
|
510
|
-
...mergedOptions,
|
|
511
|
-
...slotManager,
|
|
512
|
-
parameters: context.parameters,
|
|
513
|
-
events: context.events,
|
|
514
|
-
getLocation,
|
|
515
|
-
setLocation,
|
|
516
|
-
getConsent,
|
|
517
|
-
setConsent,
|
|
518
|
-
addSlot,
|
|
519
|
-
findDomSlots: findDomSlots2,
|
|
520
|
-
dispose,
|
|
521
|
-
toggleDebug,
|
|
522
|
-
context
|
|
523
|
-
};
|
|
524
564
|
}
|
|
525
565
|
function addTrackingPixel(url) {
|
|
526
566
|
const img = document.createElement("img");
|
|
@@ -533,119 +573,7 @@ function addTrackingPixel(url) {
|
|
|
533
573
|
img.style.top = "0";
|
|
534
574
|
return document.body.appendChild(img);
|
|
535
575
|
}
|
|
536
|
-
function
|
|
537
|
-
const iframe = document.createElement("iframe");
|
|
538
|
-
iframe.srcdoc = `
|
|
539
|
-
<!DOCTYPE html>
|
|
540
|
-
<html>
|
|
541
|
-
<head>
|
|
542
|
-
<style>
|
|
543
|
-
body {
|
|
544
|
-
margin: 0;
|
|
545
|
-
padding: 0;
|
|
546
|
-
overflow: hidden;
|
|
547
|
-
}
|
|
548
|
-
</style>
|
|
549
|
-
</head>
|
|
550
|
-
<body>
|
|
551
|
-
${ad.tag}
|
|
552
|
-
</body>
|
|
553
|
-
`.replaceAll(/\s+/g, " ").trim();
|
|
554
|
-
iframe.style.border = "none";
|
|
555
|
-
iframe.style.width = ad.width ? `${ad.width}px` : "100%";
|
|
556
|
-
iframe.style.height = ad.height ? `${ad.height}px` : "100%";
|
|
557
|
-
element.replaceChildren(iframe);
|
|
558
|
-
}
|
|
559
|
-
function renderInline(ad, element) {
|
|
560
|
-
element.style.width = ad.width ? `${ad.width}px` : "100%";
|
|
561
|
-
element.style.height = ad.height ? `${ad.height}px` : "100%";
|
|
562
|
-
element.innerHTML = ad.tag;
|
|
563
|
-
}
|
|
564
|
-
const renderFunctions = {
|
|
565
|
-
iframe: renderIframe,
|
|
566
|
-
inline: renderInline
|
|
567
|
-
};
|
|
568
|
-
async function createSlot(options) {
|
|
569
|
-
var _a;
|
|
570
|
-
const {
|
|
571
|
-
containingElement,
|
|
572
|
-
slot,
|
|
573
|
-
context,
|
|
574
|
-
renderMode = "iframe"
|
|
575
|
-
} = options;
|
|
576
|
-
await waitForDomLoad();
|
|
577
|
-
const parameters = new Map(Object.entries(options.parameters ?? {}));
|
|
578
|
-
let format;
|
|
579
|
-
let queryDetector = null;
|
|
580
|
-
if (typeof options.format === "string") {
|
|
581
|
-
format = options.format;
|
|
582
|
-
} else {
|
|
583
|
-
queryDetector = createQueryDetector({
|
|
584
|
-
onChange: setFormat,
|
|
585
|
-
queries: Object.fromEntries(options.format.map((item) => [item.format, item.query]))
|
|
586
|
-
});
|
|
587
|
-
format = queryDetector.getQuery();
|
|
588
|
-
}
|
|
589
|
-
async function setFormat(newFormat) {
|
|
590
|
-
var _a2;
|
|
591
|
-
const oldName = getName();
|
|
592
|
-
format = newFormat;
|
|
593
|
-
(_a2 = options.onNameChange) == null ? void 0 : _a2.call(options, getName(), oldName);
|
|
594
|
-
const newAd = await requestAd({
|
|
595
|
-
slot: {
|
|
596
|
-
getName,
|
|
597
|
-
parameters
|
|
598
|
-
},
|
|
599
|
-
account: context.options.account,
|
|
600
|
-
host: context.options.host,
|
|
601
|
-
parameters: context.parameters,
|
|
602
|
-
method: context.options.requestType,
|
|
603
|
-
context
|
|
604
|
-
});
|
|
605
|
-
cleanElement();
|
|
606
|
-
await setAd(newAd);
|
|
607
|
-
}
|
|
608
|
-
function getFormat() {
|
|
609
|
-
return format;
|
|
610
|
-
}
|
|
611
|
-
let element = typeof containingElement === "string" || !containingElement ? document.querySelector(`.adunit[data-format="${format}"]#${containingElement}${slot ? `[data-slot="${slot}"]` : ""}`) : containingElement;
|
|
612
|
-
function getElement() {
|
|
613
|
-
if (renderMode === "iframe")
|
|
614
|
-
return (element == null ? void 0 : element.querySelector("iframe")) ?? null;
|
|
615
|
-
return (element == null ? void 0 : element.innerHTML) ? element.firstElementChild : null;
|
|
616
|
-
}
|
|
617
|
-
let impressionTrackingPixelElement = null;
|
|
618
|
-
let viewabilityTrackingPixelElement = null;
|
|
619
|
-
let isInViewport = false;
|
|
620
|
-
let ad = null;
|
|
621
|
-
function getAd() {
|
|
622
|
-
return ad;
|
|
623
|
-
}
|
|
624
|
-
async function setAd(newAd) {
|
|
625
|
-
var _a2, _b;
|
|
626
|
-
ad = newAd;
|
|
627
|
-
if (isInViewport || context.options.eagerRendering)
|
|
628
|
-
await render(ad);
|
|
629
|
-
if (element) {
|
|
630
|
-
element.style.width = `${ad.width}px`;
|
|
631
|
-
element.style.height = `${ad.height}px`;
|
|
632
|
-
}
|
|
633
|
-
await ((_b = context.events) == null ? void 0 : _b.changeSlots.dispatchAsync(Array.from(((_a2 = context.getAll) == null ? void 0 : _a2.call(context)) ?? [])));
|
|
634
|
-
}
|
|
635
|
-
const renderIntersectionObserver = new IntersectionObserver((entries) => {
|
|
636
|
-
isInViewport = entries.some((entry) => entry.isIntersecting);
|
|
637
|
-
if (isInViewport) {
|
|
638
|
-
(async () => {
|
|
639
|
-
if (!ad && options.lazyLoading)
|
|
640
|
-
await render();
|
|
641
|
-
else if (ad)
|
|
642
|
-
await render(ad);
|
|
643
|
-
})().catch(logger.error);
|
|
644
|
-
}
|
|
645
|
-
}, {
|
|
646
|
-
rootMargin: ((_a = options.lazyLoadingOptions) == null ? void 0 : _a.rootMargin) ?? "200px",
|
|
647
|
-
threshold: 0
|
|
648
|
-
});
|
|
576
|
+
function useViewabilityObserver({ context, ad, name, element }) {
|
|
649
577
|
let timeoutId = null;
|
|
650
578
|
const {
|
|
651
579
|
threshold,
|
|
@@ -657,17 +585,19 @@ async function createSlot(options) {
|
|
|
657
585
|
rootMargin: "0px",
|
|
658
586
|
...context.options.viewabilityTrackingOptions
|
|
659
587
|
};
|
|
588
|
+
const trackingPixel = ref(null);
|
|
589
|
+
const isTracked = computed(() => Boolean(trackingPixel.value));
|
|
660
590
|
const viewabilityObserver = new IntersectionObserver(([entry]) => {
|
|
661
|
-
if (context.options.viewabilityTracking && !
|
|
591
|
+
if (context.options.viewabilityTracking && !trackingPixel.value && ad) {
|
|
662
592
|
const ratio = round(entry.intersectionRatio, 1);
|
|
663
593
|
if (ratio >= threshold && !timeoutId) {
|
|
664
594
|
timeoutId = setTimeout(() => {
|
|
665
|
-
var
|
|
595
|
+
var _a, _b, _c;
|
|
666
596
|
timeoutId = null;
|
|
667
|
-
if (ad == null ? void 0 :
|
|
668
|
-
|
|
669
|
-
logger.debug(`Viewability tracking pixel fired for ${
|
|
670
|
-
(
|
|
597
|
+
if ((_a = ad.value) == null ? void 0 : _a.viewableImpressionCounter) {
|
|
598
|
+
trackingPixel.value = addTrackingPixel(ad.value.viewableImpressionCounter);
|
|
599
|
+
logger.debug(`Viewability tracking pixel fired for ${name.value}`);
|
|
600
|
+
(_c = context.events) == null ? void 0 : _c.changeSlots.dispatch(Array.from(((_b = context.getAll) == null ? void 0 : _b.call(context)) ?? []));
|
|
671
601
|
}
|
|
672
602
|
}, duration);
|
|
673
603
|
} else if (ratio < threshold && timeoutId) {
|
|
@@ -679,91 +609,221 @@ async function createSlot(options) {
|
|
|
679
609
|
rootMargin,
|
|
680
610
|
threshold: Array.from({ length: 11 }, (_, i) => i * 0.1)
|
|
681
611
|
});
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
getName,
|
|
692
|
-
parameters
|
|
693
|
-
},
|
|
694
|
-
account: context.options.account,
|
|
695
|
-
host: context.options.host,
|
|
696
|
-
parameters: context.parameters,
|
|
697
|
-
method: context.options.requestType,
|
|
698
|
-
context
|
|
699
|
-
});
|
|
700
|
-
if (!element) {
|
|
701
|
-
const error = `Could not create slot for format ${format}. No element found.`;
|
|
702
|
-
logger.error(error, options);
|
|
703
|
-
throw new Error(error);
|
|
704
|
-
}
|
|
705
|
-
if (context.debug)
|
|
706
|
-
element.style.position = "relative";
|
|
707
|
-
renderFunctions[renderMode](ad, element);
|
|
708
|
-
if ((ad == null ? void 0 : ad.impressionCounter) && !impressionTrackingPixelElement) {
|
|
709
|
-
impressionTrackingPixelElement = addTrackingPixel(ad.impressionCounter);
|
|
710
|
-
logger.debug(`Impression tracking pixel fired for ${getName()}`);
|
|
711
|
-
}
|
|
712
|
-
logger.debug("Slot rendered", {
|
|
713
|
-
renderedElement: element,
|
|
714
|
-
location: context.location,
|
|
715
|
-
format,
|
|
716
|
-
containingElement
|
|
717
|
-
});
|
|
718
|
-
renderIntersectionObserver.disconnect();
|
|
719
|
-
await ((_b = context.events) == null ? void 0 : _b.changeSlots.dispatchAsync(Array.from(((_a2 = context.getAll) == null ? void 0 : _a2.call(context)) ?? [])));
|
|
720
|
-
return element;
|
|
721
|
-
}
|
|
722
|
-
function cleanElement() {
|
|
723
|
-
if (!element)
|
|
724
|
-
return;
|
|
725
|
-
element.innerHTML = "";
|
|
726
|
-
element.style.position = "";
|
|
727
|
-
element.style.width = "";
|
|
728
|
-
element.style.height = "";
|
|
729
|
-
}
|
|
730
|
-
function getName() {
|
|
731
|
-
return `${context.location}${slot ? `${slot}` : ""}-${format}`;
|
|
612
|
+
function observe(newElement, oldElement) {
|
|
613
|
+
if (oldElement)
|
|
614
|
+
viewabilityObserver.unobserve(oldElement);
|
|
615
|
+
if (newElement && context.options.viewabilityTracking)
|
|
616
|
+
viewabilityObserver.observe(newElement);
|
|
617
|
+
return () => {
|
|
618
|
+
if (newElement)
|
|
619
|
+
viewabilityObserver.unobserve(newElement);
|
|
620
|
+
};
|
|
732
621
|
}
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
element = null;
|
|
739
|
-
ad = null;
|
|
740
|
-
renderIntersectionObserver.disconnect();
|
|
622
|
+
watch(element, observe);
|
|
623
|
+
observe(element.value);
|
|
624
|
+
return [isTracked, () => {
|
|
625
|
+
var _a;
|
|
626
|
+
(_a = trackingPixel.value) == null ? void 0 : _a.remove();
|
|
741
627
|
viewabilityObserver.disconnect();
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
628
|
+
}];
|
|
629
|
+
}
|
|
630
|
+
function useRenderIntersectionObserver({ ad, options, element, render }) {
|
|
631
|
+
var _a;
|
|
632
|
+
const isInViewport = ref(false);
|
|
633
|
+
const renderIntersectionObserver = new IntersectionObserver((entries) => {
|
|
634
|
+
isInViewport.value = entries.some((entry) => entry.isIntersecting);
|
|
635
|
+
if (isInViewport.value) {
|
|
636
|
+
(async () => {
|
|
637
|
+
if (!ad.value && options.lazyLoading)
|
|
638
|
+
await render();
|
|
639
|
+
await render(ad.value ?? void 0);
|
|
640
|
+
})().catch(logger.error);
|
|
641
|
+
}
|
|
642
|
+
}, {
|
|
643
|
+
rootMargin: ((_a = options.lazyLoadingOptions) == null ? void 0 : _a.rootMargin) ?? "200px",
|
|
644
|
+
threshold: 0
|
|
645
|
+
});
|
|
646
|
+
function observe(newElement, oldElement) {
|
|
647
|
+
if (oldElement)
|
|
648
|
+
renderIntersectionObserver.unobserve(oldElement);
|
|
649
|
+
if (newElement)
|
|
650
|
+
renderIntersectionObserver.observe(newElement);
|
|
651
|
+
return () => {
|
|
652
|
+
if (newElement)
|
|
653
|
+
renderIntersectionObserver.unobserve(newElement);
|
|
654
|
+
};
|
|
750
655
|
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
656
|
+
watch(element, observe);
|
|
657
|
+
observe(element.value);
|
|
658
|
+
return [isInViewport, () => {
|
|
659
|
+
renderIntersectionObserver.disconnect();
|
|
660
|
+
}];
|
|
661
|
+
}
|
|
662
|
+
const renderFunctions = {
|
|
663
|
+
iframe: renderIframe,
|
|
664
|
+
inline: renderInline
|
|
665
|
+
};
|
|
666
|
+
function createSlot(options) {
|
|
667
|
+
const scope = effectScope();
|
|
668
|
+
return scope.run(() => {
|
|
669
|
+
const {
|
|
670
|
+
containingElement,
|
|
671
|
+
slot,
|
|
672
|
+
context,
|
|
673
|
+
renderMode = "iframe"
|
|
674
|
+
} = options;
|
|
675
|
+
const parameters = reactive(new Map(Object.entries(options.parameters ?? {})));
|
|
676
|
+
let queryDetector = null;
|
|
677
|
+
if (typeof options.format !== "string") {
|
|
678
|
+
queryDetector = createQueryDetector({
|
|
679
|
+
onChange: onQueryChange,
|
|
680
|
+
queries: Object.fromEntries(options.format.map((item) => [item.format, item.query]))
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
const format = ref(queryDetector ? queryDetector.getQuery() : options.format);
|
|
684
|
+
function onQueryChange(newFormat) {
|
|
685
|
+
format.value = newFormat;
|
|
686
|
+
}
|
|
687
|
+
const ad = ref(null);
|
|
688
|
+
const originalAd = ref(ad.value);
|
|
689
|
+
const name = computed(() => generateName(context.location, format.value, slot));
|
|
690
|
+
watch(name, async (newName, oldName) => {
|
|
691
|
+
var _a;
|
|
692
|
+
if (newName === oldName)
|
|
693
|
+
return;
|
|
694
|
+
(_a = options.onNameChange) == null ? void 0 : _a.call(options, newName, oldName);
|
|
695
|
+
const newAd = await requestAd$1();
|
|
696
|
+
cleanElement();
|
|
697
|
+
ad.value = newAd;
|
|
698
|
+
originalAd.value = newAd;
|
|
699
|
+
});
|
|
700
|
+
const isDomLoaded = useDomLoaded();
|
|
701
|
+
const element = computed(
|
|
702
|
+
() => {
|
|
703
|
+
if (!(typeof containingElement === "string" || !containingElement))
|
|
704
|
+
return containingElement;
|
|
705
|
+
if (!isDomLoaded.value)
|
|
706
|
+
return null;
|
|
707
|
+
return document.querySelector(`.adunit[data-format="${format.value}"]#${containingElement}${slot ? `[data-slot="${slot}"]` : ""}`);
|
|
708
|
+
}
|
|
709
|
+
);
|
|
710
|
+
function getElement() {
|
|
711
|
+
var _a, _b;
|
|
712
|
+
if (renderMode === "iframe")
|
|
713
|
+
return ((_a = element.value) == null ? void 0 : _a.querySelector("iframe")) ?? null;
|
|
714
|
+
return ((_b = element.value) == null ? void 0 : _b.innerHTML) ? element.value.firstElementChild : null;
|
|
715
|
+
}
|
|
716
|
+
const [isInViewport, disposeRenderIntersectionObserver] = useRenderIntersectionObserver({
|
|
717
|
+
ad,
|
|
718
|
+
options,
|
|
719
|
+
element,
|
|
720
|
+
render
|
|
721
|
+
});
|
|
722
|
+
watch([ad, isInViewport], async ([newAd, newIsInViewport], [oldAd]) => {
|
|
723
|
+
var _a, _b;
|
|
724
|
+
if (!newAd || isEqual(newAd, oldAd))
|
|
725
|
+
return;
|
|
726
|
+
if (newIsInViewport || context.options.eagerRendering)
|
|
727
|
+
await render(newAd);
|
|
728
|
+
if (element.value) {
|
|
729
|
+
element.value.style.width = `${newAd.width}px`;
|
|
730
|
+
element.value.style.height = `${newAd.height}px`;
|
|
731
|
+
}
|
|
732
|
+
(_b = context.events) == null ? void 0 : _b.changeSlots.dispatch(Array.from(((_a = context.getAll) == null ? void 0 : _a.call(context)) ?? []));
|
|
733
|
+
});
|
|
734
|
+
const [
|
|
735
|
+
isViewabilityTracked,
|
|
736
|
+
disposeViewabilityObserver
|
|
737
|
+
] = useViewabilityObserver({
|
|
738
|
+
context,
|
|
739
|
+
ad,
|
|
740
|
+
name,
|
|
741
|
+
element
|
|
742
|
+
});
|
|
743
|
+
const impressionTrackingPixelElement = ref(null);
|
|
744
|
+
const isImpressionTracked = computed(() => Boolean(impressionTrackingPixelElement.value));
|
|
745
|
+
async function requestAd$1() {
|
|
746
|
+
const response = await requestAd({
|
|
747
|
+
slot: {
|
|
748
|
+
name: name.value,
|
|
749
|
+
parameters
|
|
750
|
+
},
|
|
751
|
+
context
|
|
752
|
+
});
|
|
753
|
+
originalAd.value = response;
|
|
754
|
+
return response;
|
|
755
|
+
}
|
|
756
|
+
async function render(adToRender) {
|
|
757
|
+
var _a, _b;
|
|
758
|
+
await waitForDomLoad();
|
|
759
|
+
const renderAd = adToRender ?? ad.value ?? await requestAd$1();
|
|
760
|
+
if (originalAd.value) {
|
|
761
|
+
ad.value = ((_a = options.onBeforeRender) == null ? void 0 : _a.call(options, adToRender ?? originalAd.value)) ?? renderAd;
|
|
762
|
+
}
|
|
763
|
+
if (!element.value) {
|
|
764
|
+
const error = `Could not create slot for format ${format.value}. No element found.`;
|
|
765
|
+
logger.error(error, options);
|
|
766
|
+
throw new Error(error);
|
|
767
|
+
}
|
|
768
|
+
if (context.debug)
|
|
769
|
+
element.value.style.position = "relative";
|
|
770
|
+
renderFunctions[renderMode](renderAd, element.value);
|
|
771
|
+
if (renderAd.impressionCounter && !impressionTrackingPixelElement.value) {
|
|
772
|
+
impressionTrackingPixelElement.value = addTrackingPixel(renderAd.impressionCounter);
|
|
773
|
+
logger.debug(`Impression tracking pixel fired for ${name.value}`);
|
|
774
|
+
}
|
|
775
|
+
logger.debug("Slot rendered", {
|
|
776
|
+
renderedElement: element,
|
|
777
|
+
location: context.location,
|
|
778
|
+
format,
|
|
779
|
+
containingElement
|
|
780
|
+
});
|
|
781
|
+
(_b = options.onRender) == null ? void 0 : _b.call(options, element.value);
|
|
782
|
+
disposeRenderIntersectionObserver();
|
|
783
|
+
return element.value;
|
|
784
|
+
}
|
|
785
|
+
function cleanElement() {
|
|
786
|
+
if (!element.value)
|
|
787
|
+
return;
|
|
788
|
+
element.value.innerHTML = "";
|
|
789
|
+
element.value.style.position = "";
|
|
790
|
+
element.value.style.width = "";
|
|
791
|
+
element.value.style.height = "";
|
|
792
|
+
}
|
|
793
|
+
function dispose() {
|
|
794
|
+
var _a, _b;
|
|
795
|
+
cleanElement();
|
|
796
|
+
(_a = impressionTrackingPixelElement.value) == null ? void 0 : _a.remove();
|
|
797
|
+
ad.value = null;
|
|
798
|
+
disposeRenderIntersectionObserver();
|
|
799
|
+
disposeViewabilityObserver();
|
|
800
|
+
(_b = options.onDispose) == null ? void 0 : _b.call(options);
|
|
801
|
+
queryDetector == null ? void 0 : queryDetector.dispose();
|
|
802
|
+
scope.stop();
|
|
803
|
+
}
|
|
804
|
+
return {
|
|
805
|
+
location: context.location,
|
|
806
|
+
lazyLoading: options.lazyLoading ?? false,
|
|
807
|
+
slot,
|
|
808
|
+
parameters,
|
|
809
|
+
format,
|
|
810
|
+
name,
|
|
811
|
+
ad,
|
|
812
|
+
isViewabilityTracked,
|
|
813
|
+
isImpressionTracked,
|
|
814
|
+
render,
|
|
815
|
+
getElement,
|
|
816
|
+
dispose
|
|
817
|
+
};
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
function useDomLoaded() {
|
|
821
|
+
const isDomLoaded = ref(false);
|
|
822
|
+
onInit(async () => {
|
|
823
|
+
await waitForDomLoad();
|
|
824
|
+
isDomLoaded.value = true;
|
|
825
|
+
});
|
|
826
|
+
return isDomLoaded;
|
|
767
827
|
}
|
|
768
828
|
const numberLike = union([coerce.string().regex(/^\d+$/), literal("")]).transform((value) => value === "" ? void 0 : Number(value));
|
|
769
829
|
const booleanLike = union([coerce.boolean(), literal("")]);
|
|
@@ -782,6 +842,46 @@ const dateLike = union([coerce.string(), literal("")]).transform((value) => {
|
|
|
782
842
|
return void 0;
|
|
783
843
|
return date;
|
|
784
844
|
});
|
|
845
|
+
const cssValueLike = union([coerce.string(), literal(""), number()]).transform((value) => {
|
|
846
|
+
if (value === "" || value === 0 || value === "0")
|
|
847
|
+
return void 0;
|
|
848
|
+
if (numberLike.parse(value))
|
|
849
|
+
return `${numberLike.parse(value)}px`;
|
|
850
|
+
return String(value);
|
|
851
|
+
});
|
|
852
|
+
const isJson = string().transform((value, { addIssue }) => {
|
|
853
|
+
try {
|
|
854
|
+
return JSON.parse(value.replaceAll("'", '"'));
|
|
855
|
+
} catch (error) {
|
|
856
|
+
addIssue({
|
|
857
|
+
code: ZodIssueCode.custom,
|
|
858
|
+
message: `Invalid JSON: ${error.message}`
|
|
859
|
+
});
|
|
860
|
+
return NEVER;
|
|
861
|
+
}
|
|
862
|
+
});
|
|
863
|
+
const isHtmlString = string().transform((value, { addIssue }) => {
|
|
864
|
+
var _a;
|
|
865
|
+
const htmlParser = new DOMParser();
|
|
866
|
+
try {
|
|
867
|
+
const html = htmlParser.parseFromString(value, "text/html");
|
|
868
|
+
if (((_a = html.body) == null ? void 0 : _a.children.length) === 0)
|
|
869
|
+
throw new Error("Invalid HTML");
|
|
870
|
+
return value;
|
|
871
|
+
} catch (error) {
|
|
872
|
+
addIssue({
|
|
873
|
+
code: ZodIssueCode.custom,
|
|
874
|
+
message: error.message
|
|
875
|
+
});
|
|
876
|
+
return NEVER;
|
|
877
|
+
}
|
|
878
|
+
});
|
|
879
|
+
const isJsonOrHtmlString = union([isJson, isHtmlString]);
|
|
880
|
+
const isJsonOrHtmlOptionalString = union([coerce.string(), isJsonOrHtmlString]).transform((value) => {
|
|
881
|
+
if (value === "")
|
|
882
|
+
return void 0;
|
|
883
|
+
return value;
|
|
884
|
+
}).optional();
|
|
785
885
|
const baseSchema = object({
|
|
786
886
|
adDuration: numberLike.optional(),
|
|
787
887
|
adFormat: string().optional(),
|
|
@@ -795,7 +895,7 @@ const baseSchema = object({
|
|
|
795
895
|
advertiserId: string().optional(),
|
|
796
896
|
altText: string().optional(),
|
|
797
897
|
auctionable: booleanLike.optional(),
|
|
798
|
-
body:
|
|
898
|
+
body: isJsonOrHtmlOptionalString,
|
|
799
899
|
clickTag: urlLike.optional(),
|
|
800
900
|
comment: string().optional(),
|
|
801
901
|
creativeName: string().optional(),
|
|
@@ -806,7 +906,7 @@ const baseSchema = object({
|
|
|
806
906
|
mediaType: string(),
|
|
807
907
|
prebid: unknown().optional()
|
|
808
908
|
}).optional(),
|
|
809
|
-
height:
|
|
909
|
+
height: cssValueLike.optional(),
|
|
810
910
|
id: string().optional(),
|
|
811
911
|
impressionCounter: urlLike.optional(),
|
|
812
912
|
libId: string().optional(),
|
|
@@ -824,7 +924,7 @@ const baseSchema = object({
|
|
|
824
924
|
slotID: string(),
|
|
825
925
|
slotName: string(),
|
|
826
926
|
swfSrc: urlLike.optional(),
|
|
827
|
-
tag:
|
|
927
|
+
tag: isJsonOrHtmlOptionalString,
|
|
828
928
|
tagUrl: urlLike.optional(),
|
|
829
929
|
timeStamp: dateLike.optional(),
|
|
830
930
|
trackedImpressionCounter: urlLike.optional(),
|
|
@@ -832,16 +932,16 @@ const baseSchema = object({
|
|
|
832
932
|
trackingUrl: urlLike.optional(),
|
|
833
933
|
url: urlLike.optional(),
|
|
834
934
|
viewableImpressionCounter: urlLike.optional(),
|
|
835
|
-
width:
|
|
836
|
-
widthLarge:
|
|
935
|
+
width: cssValueLike.optional(),
|
|
936
|
+
widthLarge: cssValueLike.optional()
|
|
837
937
|
});
|
|
838
938
|
const jerliciaSchema = object({
|
|
839
939
|
origin: literal("JERLICIA"),
|
|
840
|
-
tag:
|
|
940
|
+
tag: isJsonOrHtmlString
|
|
841
941
|
}).passthrough();
|
|
842
942
|
const daleSchema = object({
|
|
843
943
|
origin: literal("DALE"),
|
|
844
|
-
body:
|
|
944
|
+
body: isJsonOrHtmlString
|
|
845
945
|
}).passthrough().transform(({ body, ...data }) => ({
|
|
846
946
|
...data,
|
|
847
947
|
tag: body
|
|
@@ -921,16 +1021,16 @@ function getPreviewObjects() {
|
|
|
921
1021
|
return previewObjects;
|
|
922
1022
|
}
|
|
923
1023
|
function requestWithPost({
|
|
924
|
-
host,
|
|
1024
|
+
context: { options: { host }, parameters },
|
|
925
1025
|
...options
|
|
926
1026
|
}) {
|
|
927
1027
|
const payload = {
|
|
928
1028
|
...options,
|
|
929
1029
|
slots: options.slots.map((slot) => ({
|
|
930
|
-
slotname: slot.
|
|
1030
|
+
slotname: toValue(slot.name),
|
|
931
1031
|
parameters: parseParameters(slot.parameters)
|
|
932
1032
|
})),
|
|
933
|
-
parameters:
|
|
1033
|
+
parameters: parameters && parseParameters(parameters)
|
|
934
1034
|
};
|
|
935
1035
|
return fetch(`${new URL(host).href}json`, {
|
|
936
1036
|
method: "POST",
|
|
@@ -941,8 +1041,8 @@ function requestWithPost({
|
|
|
941
1041
|
}
|
|
942
1042
|
});
|
|
943
1043
|
}
|
|
944
|
-
async function requestWithGet(
|
|
945
|
-
return fetch(new URL(`${options.host}/json/sl${
|
|
1044
|
+
async function requestWithGet({ context, slots }) {
|
|
1045
|
+
return fetch(new URL(`${context.options.host}/json/sl${slots.map((slot) => toValue(slot.name)).join("/sl")}`), {
|
|
946
1046
|
method: "GET",
|
|
947
1047
|
headers: {
|
|
948
1048
|
// eslint-disable-next-line ts/naming-convention
|
|
@@ -958,19 +1058,15 @@ function parseParameters(parameters) {
|
|
|
958
1058
|
return false;
|
|
959
1059
|
}));
|
|
960
1060
|
}
|
|
961
|
-
async function requestAds({
|
|
962
|
-
|
|
963
|
-
context
|
|
964
|
-
...options
|
|
965
|
-
}) {
|
|
966
|
-
var _a, _b, _c, _d;
|
|
1061
|
+
async function requestAds(options) {
|
|
1062
|
+
var _a, _b, _c, _d, _e;
|
|
1063
|
+
const { context } = options;
|
|
967
1064
|
try {
|
|
968
1065
|
(_a = context.events) == null ? void 0 : _a.requestAd.dispatch({
|
|
969
1066
|
...options,
|
|
970
|
-
context
|
|
971
|
-
method
|
|
1067
|
+
context
|
|
972
1068
|
});
|
|
973
|
-
const [response, previews] = await Promise.all([(
|
|
1069
|
+
const [response, previews] = await Promise.all([((_b = context.options.requestType) == null ? void 0 : _b.toUpperCase()) === "POST" ? requestWithPost(options) : requestWithGet(options), requestPreviews(context.options.account)]);
|
|
974
1070
|
logger.debug("Received response", response);
|
|
975
1071
|
if (!response.ok)
|
|
976
1072
|
throw new Error(`Failed to request ad: ${response.status} ${response.statusText}`);
|
|
@@ -986,18 +1082,18 @@ async function requestAds({
|
|
|
986
1082
|
};
|
|
987
1083
|
});
|
|
988
1084
|
if (matchedPreviews.length > 0)
|
|
989
|
-
(
|
|
1085
|
+
(_c = context.events) == null ? void 0 : _c.previewReceived.dispatch(matchedPreviews);
|
|
990
1086
|
const mergedResult = [
|
|
991
1087
|
...result.filter((ad) => !previews.some((preview) => preview.libId === ad.libId)),
|
|
992
1088
|
...matchedPreviews
|
|
993
1089
|
];
|
|
994
1090
|
if (mergedResult.length === 0)
|
|
995
1091
|
throw new Error("No ads found");
|
|
996
|
-
(
|
|
1092
|
+
(_d = context.events) == null ? void 0 : _d.responseReceived.dispatch(mergedResult);
|
|
997
1093
|
return mergedResult;
|
|
998
1094
|
} catch (error) {
|
|
999
1095
|
logger.error(String(error));
|
|
1000
|
-
(
|
|
1096
|
+
(_e = context.events) == null ? void 0 : _e.requestError.dispatch(error);
|
|
1001
1097
|
throw error;
|
|
1002
1098
|
}
|
|
1003
1099
|
}
|