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