@adhese/sdk 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +598 -508
- package/dist/cjs/index.js.map +1 -1
- package/dist/es/index.js +600 -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,231 @@ 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();
|
|
306
347
|
}
|
|
307
|
-
|
|
308
|
-
|
|
348
|
+
function add(callback) {
|
|
349
|
+
callbacks.add(callback);
|
|
350
|
+
onAdd == null ? void 0 : onAdd();
|
|
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() {
|
|
362
|
+
isInit = true;
|
|
363
|
+
resolveOnInitPromise();
|
|
364
|
+
logger.debug("Initialization completed");
|
|
365
|
+
},
|
|
366
|
+
onAdd() {
|
|
367
|
+
if (isInit)
|
|
368
|
+
runOnInit();
|
|
312
369
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
370
|
+
});
|
|
371
|
+
function createAdhese(options) {
|
|
372
|
+
const scope = runtimeCore.effectScope();
|
|
373
|
+
return scope.run(() => {
|
|
374
|
+
const mergedOptions = {
|
|
375
|
+
host: `https://ads-${options.account}.adhese.com`,
|
|
376
|
+
poolHost: `https://pool-${options.account}.adhese.com`,
|
|
377
|
+
location: "homepage",
|
|
378
|
+
requestType: "POST",
|
|
379
|
+
debug: false,
|
|
380
|
+
initialSlots: [],
|
|
381
|
+
findDomSlotsOnLoad: false,
|
|
382
|
+
consent: false,
|
|
383
|
+
logReferrer: true,
|
|
384
|
+
logUrl: true,
|
|
385
|
+
eagerRendering: false,
|
|
386
|
+
viewabilityTracking: true,
|
|
387
|
+
...options
|
|
388
|
+
};
|
|
389
|
+
setupLogging(mergedOptions);
|
|
390
|
+
const context = runtimeCore.reactive({
|
|
391
|
+
location: mergedOptions.location,
|
|
392
|
+
consent: mergedOptions.consent,
|
|
393
|
+
debug: mergedOptions.debug,
|
|
394
|
+
getAll,
|
|
395
|
+
get,
|
|
396
|
+
options: mergedOptions,
|
|
397
|
+
logger
|
|
317
398
|
});
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
399
|
+
context.events = createEventManager();
|
|
400
|
+
function getLocation() {
|
|
401
|
+
return context.location;
|
|
402
|
+
}
|
|
403
|
+
function setLocation(newLocation) {
|
|
404
|
+
var _a;
|
|
405
|
+
context.location = newLocation;
|
|
406
|
+
(_a = context.events) == null ? void 0 : _a.locationChange.dispatch(newLocation);
|
|
407
|
+
}
|
|
408
|
+
const queryDetector = createQueryDetector({
|
|
409
|
+
onChange: onQueryChange,
|
|
410
|
+
queries: mergedOptions.queries
|
|
324
411
|
});
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
412
|
+
context.parameters = createParameters(mergedOptions, queryDetector);
|
|
413
|
+
runtimeCore.watch(
|
|
414
|
+
context.parameters,
|
|
415
|
+
onParametersChange,
|
|
416
|
+
{
|
|
417
|
+
deep: true,
|
|
418
|
+
immediate: true
|
|
419
|
+
}
|
|
420
|
+
);
|
|
421
|
+
function onParametersChange() {
|
|
422
|
+
var _a;
|
|
423
|
+
if (context.parameters)
|
|
424
|
+
(_a = context.events) == null ? void 0 : _a.parametersChange.dispatch(context.parameters);
|
|
425
|
+
}
|
|
426
|
+
async function onQueryChange() {
|
|
427
|
+
var _a, _b;
|
|
428
|
+
const query = queryDetector.getQuery();
|
|
429
|
+
(_a = context.parameters) == null ? void 0 : _a.set("dt", query);
|
|
430
|
+
(_b = context.parameters) == null ? void 0 : _b.set("br", query);
|
|
431
|
+
await fetchAndRenderAllSlots();
|
|
432
|
+
}
|
|
433
|
+
function getConsent() {
|
|
434
|
+
return context.consent;
|
|
435
|
+
}
|
|
436
|
+
function setConsent(newConsent) {
|
|
437
|
+
var _a, _b;
|
|
438
|
+
(_a = context.parameters) == null ? void 0 : _a.set("tl", newConsent ? "all" : "none");
|
|
439
|
+
context.consent = newConsent;
|
|
440
|
+
(_b = context.events) == null ? void 0 : _b.consentChange.dispatch(newConsent);
|
|
441
|
+
}
|
|
442
|
+
const slotManager = createSlotManager({
|
|
443
|
+
initialSlots: mergedOptions.initialSlots,
|
|
444
|
+
context
|
|
330
445
|
});
|
|
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,
|
|
446
|
+
function getAll() {
|
|
447
|
+
return slotManager.getAll() ?? [];
|
|
448
|
+
}
|
|
449
|
+
function get(name) {
|
|
450
|
+
return slotManager.get(name);
|
|
451
|
+
}
|
|
452
|
+
async function addSlot(slotOptions) {
|
|
453
|
+
if (!slotManager)
|
|
454
|
+
throw new Error("Slot manager not initialized");
|
|
455
|
+
const slot = slotManager.add(slotOptions);
|
|
456
|
+
if (!slot.lazyLoading) {
|
|
457
|
+
slot.ad.value = await requestAd({
|
|
458
|
+
slot,
|
|
459
|
+
context
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
return slot;
|
|
463
|
+
}
|
|
464
|
+
async function findDomSlots2() {
|
|
465
|
+
const domSlots = (await slotManager.findDomSlots() ?? []).filter((slot) => !slot.lazyLoading);
|
|
466
|
+
if (domSlots.length <= 0)
|
|
467
|
+
return [];
|
|
468
|
+
const ads = await requestAds({
|
|
469
|
+
slots: domSlots,
|
|
427
470
|
context
|
|
428
471
|
});
|
|
429
|
-
|
|
472
|
+
for (const ad of ads) {
|
|
473
|
+
const slot = slotManager.get(ad.slotName);
|
|
474
|
+
if (slot)
|
|
475
|
+
slot.ad.value = ad;
|
|
476
|
+
}
|
|
477
|
+
return domSlots;
|
|
430
478
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
479
|
+
let unmountDevtools;
|
|
480
|
+
async function toggleDebug() {
|
|
481
|
+
var _a, _b;
|
|
482
|
+
context.debug = !context.debug;
|
|
483
|
+
if (context.debug && !unmountDevtools) {
|
|
484
|
+
unmountDevtools = await sdkDevtools.createDevtools(context);
|
|
485
|
+
logger.setMinLogLevelThreshold("debug");
|
|
486
|
+
logger.debug("Debug mode enabled");
|
|
487
|
+
(_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
|
|
488
|
+
} else {
|
|
489
|
+
logger.debug("Debug mode disabled");
|
|
490
|
+
unmountDevtools == null ? void 0 : unmountDevtools();
|
|
491
|
+
unmountDevtools = void 0;
|
|
492
|
+
logger.setMinLogLevelThreshold("info");
|
|
493
|
+
(_b = context.events) == null ? void 0 : _b.debugChange.dispatch(false);
|
|
494
|
+
}
|
|
495
|
+
return context.debug;
|
|
496
|
+
}
|
|
497
|
+
async function fetchAndRenderAllSlots() {
|
|
498
|
+
const slots = (slotManager.getAll() ?? []).filter((slot) => !slot.lazyLoading);
|
|
499
|
+
if (slots.length === 0)
|
|
500
|
+
return;
|
|
501
|
+
const ads = await requestAds({
|
|
502
|
+
slots,
|
|
503
|
+
context
|
|
504
|
+
});
|
|
505
|
+
for (const ad of ads) {
|
|
506
|
+
const slot = slotManager.get(ad.slotName);
|
|
507
|
+
if (slot)
|
|
508
|
+
slot.ad.value = ad;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
const disposeOnTcfConsentChange = onTcfConsentChange(async (data) => {
|
|
512
|
+
var _a, _b;
|
|
513
|
+
if (!data.tcString)
|
|
514
|
+
return;
|
|
515
|
+
logger.debug("TCF v2 consent data received", {
|
|
516
|
+
data
|
|
517
|
+
});
|
|
518
|
+
(_a = context.parameters) == null ? void 0 : _a.set("xt", data.tcString);
|
|
519
|
+
(_b = context.parameters) == null ? void 0 : _b.delete("tl");
|
|
520
|
+
await fetchAndRenderAllSlots();
|
|
442
521
|
});
|
|
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");
|
|
522
|
+
function dispose() {
|
|
523
|
+
var _a, _b;
|
|
459
524
|
unmountDevtools == null ? void 0 : unmountDevtools();
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
525
|
+
queryDetector.dispose();
|
|
526
|
+
slotManager.dispose();
|
|
527
|
+
queryDetector.dispose();
|
|
528
|
+
disposeOnTcfConsentChange();
|
|
529
|
+
(_a = context.parameters) == null ? void 0 : _a.clear();
|
|
530
|
+
logger.resetLogs();
|
|
531
|
+
(_b = context.events) == null ? void 0 : _b.dispose();
|
|
532
|
+
logger.info("Adhese instance disposed");
|
|
533
|
+
scope.stop();
|
|
463
534
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
535
|
+
onInit(async () => {
|
|
536
|
+
var _a;
|
|
537
|
+
if ((slotManager.getAll().length ?? 0) > 0)
|
|
538
|
+
await fetchAndRenderAllSlots().catch(logger.error);
|
|
539
|
+
if (mergedOptions.findDomSlotsOnLoad)
|
|
540
|
+
await findDomSlots2();
|
|
541
|
+
if (mergedOptions.debug || window.location.search.includes("adhese_debug=true") || isPreviewMode()) {
|
|
542
|
+
unmountDevtools = await sdkDevtools.createDevtools(context);
|
|
543
|
+
(_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
runOnInit();
|
|
547
|
+
return {
|
|
548
|
+
...mergedOptions,
|
|
549
|
+
...slotManager,
|
|
475
550
|
parameters: context.parameters,
|
|
551
|
+
events: context.events,
|
|
552
|
+
getLocation,
|
|
553
|
+
setLocation,
|
|
554
|
+
getConsent,
|
|
555
|
+
setConsent,
|
|
556
|
+
addSlot,
|
|
557
|
+
findDomSlots: findDomSlots2,
|
|
558
|
+
dispose,
|
|
559
|
+
toggleDebug,
|
|
476
560
|
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();
|
|
561
|
+
};
|
|
493
562
|
});
|
|
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
563
|
}
|
|
527
564
|
function addTrackingPixel(url) {
|
|
528
565
|
const img = document.createElement("img");
|
|
@@ -535,119 +572,7 @@ function addTrackingPixel(url) {
|
|
|
535
572
|
img.style.top = "0";
|
|
536
573
|
return document.body.appendChild(img);
|
|
537
574
|
}
|
|
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
|
-
});
|
|
575
|
+
function useViewabilityObserver({ context, ad, name, element }) {
|
|
651
576
|
let timeoutId = null;
|
|
652
577
|
const {
|
|
653
578
|
threshold,
|
|
@@ -659,17 +584,19 @@ async function createSlot(options) {
|
|
|
659
584
|
rootMargin: "0px",
|
|
660
585
|
...context.options.viewabilityTrackingOptions
|
|
661
586
|
};
|
|
587
|
+
const trackingPixel = runtimeCore.ref(null);
|
|
588
|
+
const isTracked = runtimeCore.computed(() => Boolean(trackingPixel.value));
|
|
662
589
|
const viewabilityObserver = new IntersectionObserver(([entry]) => {
|
|
663
|
-
if (context.options.viewabilityTracking && !
|
|
590
|
+
if (context.options.viewabilityTracking && !trackingPixel.value && ad) {
|
|
664
591
|
const ratio = lodashEs.round(entry.intersectionRatio, 1);
|
|
665
592
|
if (ratio >= threshold && !timeoutId) {
|
|
666
593
|
timeoutId = setTimeout(() => {
|
|
667
|
-
var
|
|
594
|
+
var _a, _b, _c;
|
|
668
595
|
timeoutId = null;
|
|
669
|
-
if (ad == null ? void 0 :
|
|
670
|
-
|
|
671
|
-
logger.debug(`Viewability tracking pixel fired for ${
|
|
672
|
-
(
|
|
596
|
+
if ((_a = ad.value) == null ? void 0 : _a.viewableImpressionCounter) {
|
|
597
|
+
trackingPixel.value = addTrackingPixel(ad.value.viewableImpressionCounter);
|
|
598
|
+
logger.debug(`Viewability tracking pixel fired for ${name.value}`);
|
|
599
|
+
(_c = context.events) == null ? void 0 : _c.changeSlots.dispatch(Array.from(((_b = context.getAll) == null ? void 0 : _b.call(context)) ?? []));
|
|
673
600
|
}
|
|
674
601
|
}, duration);
|
|
675
602
|
} else if (ratio < threshold && timeoutId) {
|
|
@@ -681,91 +608,218 @@ async function createSlot(options) {
|
|
|
681
608
|
rootMargin,
|
|
682
609
|
threshold: Array.from({ length: 11 }, (_, i) => i * 0.1)
|
|
683
610
|
});
|
|
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}`;
|
|
611
|
+
function observe(newElement, oldElement) {
|
|
612
|
+
if (oldElement)
|
|
613
|
+
viewabilityObserver.unobserve(oldElement);
|
|
614
|
+
if (newElement && context.options.viewabilityTracking)
|
|
615
|
+
viewabilityObserver.observe(newElement);
|
|
616
|
+
return () => {
|
|
617
|
+
if (newElement)
|
|
618
|
+
viewabilityObserver.unobserve(newElement);
|
|
619
|
+
};
|
|
734
620
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
element = null;
|
|
741
|
-
ad = null;
|
|
742
|
-
renderIntersectionObserver.disconnect();
|
|
621
|
+
runtimeCore.watch(element, observe);
|
|
622
|
+
observe(element.value);
|
|
623
|
+
return [isTracked, () => {
|
|
624
|
+
var _a;
|
|
625
|
+
(_a = trackingPixel.value) == null ? void 0 : _a.remove();
|
|
743
626
|
viewabilityObserver.disconnect();
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
627
|
+
}];
|
|
628
|
+
}
|
|
629
|
+
function useRenderIntersectionObserver({ ad, options, element, render }) {
|
|
630
|
+
var _a;
|
|
631
|
+
const isInViewport = runtimeCore.ref(false);
|
|
632
|
+
const renderIntersectionObserver = new IntersectionObserver((entries) => {
|
|
633
|
+
isInViewport.value = entries.some((entry) => entry.isIntersecting);
|
|
634
|
+
if (isInViewport.value) {
|
|
635
|
+
(async () => {
|
|
636
|
+
if (!ad.value && options.lazyLoading)
|
|
637
|
+
await render();
|
|
638
|
+
await render(ad.value ?? void 0);
|
|
639
|
+
})().catch(logger.error);
|
|
640
|
+
}
|
|
641
|
+
}, {
|
|
642
|
+
rootMargin: ((_a = options.lazyLoadingOptions) == null ? void 0 : _a.rootMargin) ?? "200px",
|
|
643
|
+
threshold: 0
|
|
644
|
+
});
|
|
645
|
+
function observe(newElement, oldElement) {
|
|
646
|
+
if (oldElement)
|
|
647
|
+
renderIntersectionObserver.unobserve(oldElement);
|
|
648
|
+
if (newElement)
|
|
649
|
+
renderIntersectionObserver.observe(newElement);
|
|
650
|
+
return () => {
|
|
651
|
+
if (newElement)
|
|
652
|
+
renderIntersectionObserver.unobserve(newElement);
|
|
653
|
+
};
|
|
752
654
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
655
|
+
runtimeCore.watch(element, observe);
|
|
656
|
+
observe(element.value);
|
|
657
|
+
return [isInViewport, () => {
|
|
658
|
+
renderIntersectionObserver.disconnect();
|
|
659
|
+
}];
|
|
660
|
+
}
|
|
661
|
+
const renderFunctions = {
|
|
662
|
+
iframe: renderIframe,
|
|
663
|
+
inline: renderInline
|
|
664
|
+
};
|
|
665
|
+
function createSlot(options) {
|
|
666
|
+
const scope = runtimeCore.effectScope();
|
|
667
|
+
return scope.run(() => {
|
|
668
|
+
const {
|
|
669
|
+
containingElement,
|
|
670
|
+
slot,
|
|
671
|
+
context,
|
|
672
|
+
renderMode = "iframe"
|
|
673
|
+
} = options;
|
|
674
|
+
const parameters = runtimeCore.reactive(new Map(Object.entries(options.parameters ?? {})));
|
|
675
|
+
let queryDetector = null;
|
|
676
|
+
if (typeof options.format !== "string") {
|
|
677
|
+
queryDetector = createQueryDetector({
|
|
678
|
+
onChange: onQueryChange,
|
|
679
|
+
queries: Object.fromEntries(options.format.map((item) => [item.format, item.query]))
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
const format = runtimeCore.ref(queryDetector ? queryDetector.getQuery() : options.format);
|
|
683
|
+
function onQueryChange(newFormat) {
|
|
684
|
+
format.value = newFormat;
|
|
685
|
+
}
|
|
686
|
+
const ad = runtimeCore.ref(null);
|
|
687
|
+
const name = runtimeCore.computed(() => generateName(context.location, format.value, slot));
|
|
688
|
+
runtimeCore.watch(name, async (newName, oldName) => {
|
|
689
|
+
var _a;
|
|
690
|
+
if (newName === oldName)
|
|
691
|
+
return;
|
|
692
|
+
(_a = options.onNameChange) == null ? void 0 : _a.call(options, newName, oldName);
|
|
693
|
+
const newAd = await requestAd({
|
|
694
|
+
slot: {
|
|
695
|
+
name: newName,
|
|
696
|
+
parameters
|
|
697
|
+
},
|
|
698
|
+
context
|
|
699
|
+
});
|
|
700
|
+
cleanElement();
|
|
701
|
+
ad.value = newAd;
|
|
702
|
+
});
|
|
703
|
+
const isDomLoaded = useDomLoaded();
|
|
704
|
+
const element = runtimeCore.computed(
|
|
705
|
+
() => {
|
|
706
|
+
if (!(typeof containingElement === "string" || !containingElement))
|
|
707
|
+
return containingElement;
|
|
708
|
+
if (!isDomLoaded.value)
|
|
709
|
+
return null;
|
|
710
|
+
return document.querySelector(`.adunit[data-format="${format.value}"]#${containingElement}${slot ? `[data-slot="${slot}"]` : ""}`);
|
|
711
|
+
}
|
|
712
|
+
);
|
|
713
|
+
function getElement() {
|
|
714
|
+
var _a, _b;
|
|
715
|
+
if (renderMode === "iframe")
|
|
716
|
+
return ((_a = element.value) == null ? void 0 : _a.querySelector("iframe")) ?? null;
|
|
717
|
+
return ((_b = element.value) == null ? void 0 : _b.innerHTML) ? element.value.firstElementChild : null;
|
|
718
|
+
}
|
|
719
|
+
const [isInViewport, disposeRenderIntersectionObserver] = useRenderIntersectionObserver({
|
|
720
|
+
ad,
|
|
721
|
+
options,
|
|
722
|
+
element,
|
|
723
|
+
render
|
|
724
|
+
});
|
|
725
|
+
runtimeCore.watch([ad, isInViewport], async ([newAd, newIsInViewport], [oldAd]) => {
|
|
726
|
+
var _a, _b;
|
|
727
|
+
if (!newAd || lodashEs.isEqual(newAd, oldAd))
|
|
728
|
+
return;
|
|
729
|
+
if (newIsInViewport || context.options.eagerRendering)
|
|
730
|
+
await render(newAd);
|
|
731
|
+
if (element.value) {
|
|
732
|
+
element.value.style.width = `${newAd.width}px`;
|
|
733
|
+
element.value.style.height = `${newAd.height}px`;
|
|
734
|
+
}
|
|
735
|
+
(_b = context.events) == null ? void 0 : _b.changeSlots.dispatch(Array.from(((_a = context.getAll) == null ? void 0 : _a.call(context)) ?? []));
|
|
736
|
+
});
|
|
737
|
+
const [
|
|
738
|
+
isViewabilityTracked,
|
|
739
|
+
disposeViewabilityObserver
|
|
740
|
+
] = useViewabilityObserver({
|
|
741
|
+
context,
|
|
742
|
+
ad,
|
|
743
|
+
name,
|
|
744
|
+
element
|
|
745
|
+
});
|
|
746
|
+
const impressionTrackingPixelElement = runtimeCore.ref(null);
|
|
747
|
+
const isImpressionTracked = runtimeCore.computed(() => Boolean(impressionTrackingPixelElement.value));
|
|
748
|
+
async function render(adToRender) {
|
|
749
|
+
var _a, _b, _c, _d;
|
|
750
|
+
await waitForDomLoad();
|
|
751
|
+
ad.value = adToRender ?? ad.value ?? await requestAd({
|
|
752
|
+
slot: {
|
|
753
|
+
name,
|
|
754
|
+
parameters
|
|
755
|
+
},
|
|
756
|
+
context
|
|
757
|
+
});
|
|
758
|
+
ad.value = ((_a = options.onBeforeRender) == null ? void 0 : _a.call(options, ad.value)) ?? ad.value;
|
|
759
|
+
if (!element.value) {
|
|
760
|
+
const error = `Could not create slot for format ${format.value}. No element found.`;
|
|
761
|
+
logger.error(error, options);
|
|
762
|
+
throw new Error(error);
|
|
763
|
+
}
|
|
764
|
+
if (context.debug)
|
|
765
|
+
element.value.style.position = "relative";
|
|
766
|
+
renderFunctions[renderMode](ad.value, element.value);
|
|
767
|
+
if (((_b = ad.value) == null ? void 0 : _b.impressionCounter) && !impressionTrackingPixelElement.value) {
|
|
768
|
+
impressionTrackingPixelElement.value = addTrackingPixel((_c = ad.value) == null ? void 0 : _c.impressionCounter);
|
|
769
|
+
logger.debug(`Impression tracking pixel fired for ${name.value}`);
|
|
770
|
+
}
|
|
771
|
+
logger.debug("Slot rendered", {
|
|
772
|
+
renderedElement: element,
|
|
773
|
+
location: context.location,
|
|
774
|
+
format,
|
|
775
|
+
containingElement
|
|
776
|
+
});
|
|
777
|
+
(_d = options.onRender) == null ? void 0 : _d.call(options, element.value);
|
|
778
|
+
disposeRenderIntersectionObserver();
|
|
779
|
+
return element.value;
|
|
780
|
+
}
|
|
781
|
+
function cleanElement() {
|
|
782
|
+
if (!element.value)
|
|
783
|
+
return;
|
|
784
|
+
element.value.innerHTML = "";
|
|
785
|
+
element.value.style.position = "";
|
|
786
|
+
element.value.style.width = "";
|
|
787
|
+
element.value.style.height = "";
|
|
788
|
+
}
|
|
789
|
+
function dispose() {
|
|
790
|
+
var _a, _b;
|
|
791
|
+
cleanElement();
|
|
792
|
+
(_a = impressionTrackingPixelElement.value) == null ? void 0 : _a.remove();
|
|
793
|
+
ad.value = null;
|
|
794
|
+
disposeRenderIntersectionObserver();
|
|
795
|
+
disposeViewabilityObserver();
|
|
796
|
+
(_b = options.onDispose) == null ? void 0 : _b.call(options);
|
|
797
|
+
queryDetector == null ? void 0 : queryDetector.dispose();
|
|
798
|
+
scope.stop();
|
|
799
|
+
}
|
|
800
|
+
return {
|
|
801
|
+
location: context.location,
|
|
802
|
+
lazyLoading: options.lazyLoading ?? false,
|
|
803
|
+
slot,
|
|
804
|
+
parameters,
|
|
805
|
+
format,
|
|
806
|
+
name,
|
|
807
|
+
ad,
|
|
808
|
+
isViewabilityTracked,
|
|
809
|
+
isImpressionTracked,
|
|
810
|
+
render,
|
|
811
|
+
getElement,
|
|
812
|
+
dispose
|
|
813
|
+
};
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
function useDomLoaded() {
|
|
817
|
+
const isDomLoaded = runtimeCore.ref(false);
|
|
818
|
+
onInit(async () => {
|
|
819
|
+
await waitForDomLoad();
|
|
820
|
+
isDomLoaded.value = true;
|
|
821
|
+
});
|
|
822
|
+
return isDomLoaded;
|
|
769
823
|
}
|
|
770
824
|
const numberLike = zod.union([zod.coerce.string().regex(/^\d+$/), zod.literal("")]).transform((value) => value === "" ? void 0 : Number(value));
|
|
771
825
|
const booleanLike = zod.union([zod.coerce.boolean(), zod.literal("")]);
|
|
@@ -784,6 +838,46 @@ const dateLike = zod.union([zod.coerce.string(), zod.literal("")]).transform((va
|
|
|
784
838
|
return void 0;
|
|
785
839
|
return date;
|
|
786
840
|
});
|
|
841
|
+
const cssValueLike = zod.union([zod.coerce.string(), zod.literal(""), zod.number()]).transform((value) => {
|
|
842
|
+
if (value === "" || value === 0 || value === "0")
|
|
843
|
+
return void 0;
|
|
844
|
+
if (numberLike.parse(value))
|
|
845
|
+
return `${numberLike.parse(value)}px`;
|
|
846
|
+
return String(value);
|
|
847
|
+
});
|
|
848
|
+
const isJson = zod.string().transform((value, { addIssue }) => {
|
|
849
|
+
try {
|
|
850
|
+
return JSON.parse(value.replaceAll("'", '"'));
|
|
851
|
+
} catch (error) {
|
|
852
|
+
addIssue({
|
|
853
|
+
code: zod.ZodIssueCode.custom,
|
|
854
|
+
message: `Invalid JSON: ${error.message}`
|
|
855
|
+
});
|
|
856
|
+
return zod.NEVER;
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
const isHtmlString = zod.string().transform((value, { addIssue }) => {
|
|
860
|
+
var _a;
|
|
861
|
+
const htmlParser = new DOMParser();
|
|
862
|
+
try {
|
|
863
|
+
const html = htmlParser.parseFromString(value, "text/html");
|
|
864
|
+
if (((_a = html.body) == null ? void 0 : _a.children.length) === 0)
|
|
865
|
+
throw new Error("Invalid HTML");
|
|
866
|
+
return value;
|
|
867
|
+
} catch (error) {
|
|
868
|
+
addIssue({
|
|
869
|
+
code: zod.ZodIssueCode.custom,
|
|
870
|
+
message: error.message
|
|
871
|
+
});
|
|
872
|
+
return zod.NEVER;
|
|
873
|
+
}
|
|
874
|
+
});
|
|
875
|
+
const isJsonOrHtmlString = zod.union([isJson, isHtmlString]);
|
|
876
|
+
const isJsonOrHtmlOptionalString = zod.union([zod.coerce.string(), isJsonOrHtmlString]).transform((value) => {
|
|
877
|
+
if (value === "")
|
|
878
|
+
return void 0;
|
|
879
|
+
return value;
|
|
880
|
+
}).optional();
|
|
787
881
|
const baseSchema = zod.object({
|
|
788
882
|
adDuration: numberLike.optional(),
|
|
789
883
|
adFormat: zod.string().optional(),
|
|
@@ -797,7 +891,7 @@ const baseSchema = zod.object({
|
|
|
797
891
|
advertiserId: zod.string().optional(),
|
|
798
892
|
altText: zod.string().optional(),
|
|
799
893
|
auctionable: booleanLike.optional(),
|
|
800
|
-
body:
|
|
894
|
+
body: isJsonOrHtmlOptionalString,
|
|
801
895
|
clickTag: urlLike.optional(),
|
|
802
896
|
comment: zod.string().optional(),
|
|
803
897
|
creativeName: zod.string().optional(),
|
|
@@ -808,7 +902,7 @@ const baseSchema = zod.object({
|
|
|
808
902
|
mediaType: zod.string(),
|
|
809
903
|
prebid: zod.unknown().optional()
|
|
810
904
|
}).optional(),
|
|
811
|
-
height:
|
|
905
|
+
height: cssValueLike.optional(),
|
|
812
906
|
id: zod.string().optional(),
|
|
813
907
|
impressionCounter: urlLike.optional(),
|
|
814
908
|
libId: zod.string().optional(),
|
|
@@ -826,7 +920,7 @@ const baseSchema = zod.object({
|
|
|
826
920
|
slotID: zod.string(),
|
|
827
921
|
slotName: zod.string(),
|
|
828
922
|
swfSrc: urlLike.optional(),
|
|
829
|
-
tag:
|
|
923
|
+
tag: isJsonOrHtmlOptionalString,
|
|
830
924
|
tagUrl: urlLike.optional(),
|
|
831
925
|
timeStamp: dateLike.optional(),
|
|
832
926
|
trackedImpressionCounter: urlLike.optional(),
|
|
@@ -834,16 +928,16 @@ const baseSchema = zod.object({
|
|
|
834
928
|
trackingUrl: urlLike.optional(),
|
|
835
929
|
url: urlLike.optional(),
|
|
836
930
|
viewableImpressionCounter: urlLike.optional(),
|
|
837
|
-
width:
|
|
838
|
-
widthLarge:
|
|
931
|
+
width: cssValueLike.optional(),
|
|
932
|
+
widthLarge: cssValueLike.optional()
|
|
839
933
|
});
|
|
840
934
|
const jerliciaSchema = zod.object({
|
|
841
935
|
origin: zod.literal("JERLICIA"),
|
|
842
|
-
tag:
|
|
936
|
+
tag: isJsonOrHtmlString
|
|
843
937
|
}).passthrough();
|
|
844
938
|
const daleSchema = zod.object({
|
|
845
939
|
origin: zod.literal("DALE"),
|
|
846
|
-
body:
|
|
940
|
+
body: isJsonOrHtmlString
|
|
847
941
|
}).passthrough().transform(({ body, ...data }) => ({
|
|
848
942
|
...data,
|
|
849
943
|
tag: body
|
|
@@ -923,16 +1017,16 @@ function getPreviewObjects() {
|
|
|
923
1017
|
return previewObjects;
|
|
924
1018
|
}
|
|
925
1019
|
function requestWithPost({
|
|
926
|
-
host,
|
|
1020
|
+
context: { options: { host }, parameters },
|
|
927
1021
|
...options
|
|
928
1022
|
}) {
|
|
929
1023
|
const payload = {
|
|
930
1024
|
...options,
|
|
931
1025
|
slots: options.slots.map((slot) => ({
|
|
932
|
-
slotname: slot.
|
|
1026
|
+
slotname: runtimeCore.toValue(slot.name),
|
|
933
1027
|
parameters: parseParameters(slot.parameters)
|
|
934
1028
|
})),
|
|
935
|
-
parameters:
|
|
1029
|
+
parameters: parameters && parseParameters(parameters)
|
|
936
1030
|
};
|
|
937
1031
|
return fetch(`${new URL(host).href}json`, {
|
|
938
1032
|
method: "POST",
|
|
@@ -943,8 +1037,8 @@ function requestWithPost({
|
|
|
943
1037
|
}
|
|
944
1038
|
});
|
|
945
1039
|
}
|
|
946
|
-
async function requestWithGet(
|
|
947
|
-
return fetch(new URL(`${options.host}/json/sl${
|
|
1040
|
+
async function requestWithGet({ context, slots }) {
|
|
1041
|
+
return fetch(new URL(`${context.options.host}/json/sl${slots.map((slot) => runtimeCore.toValue(slot.name)).join("/sl")}`), {
|
|
948
1042
|
method: "GET",
|
|
949
1043
|
headers: {
|
|
950
1044
|
// eslint-disable-next-line ts/naming-convention
|
|
@@ -960,19 +1054,15 @@ function parseParameters(parameters) {
|
|
|
960
1054
|
return false;
|
|
961
1055
|
}));
|
|
962
1056
|
}
|
|
963
|
-
async function requestAds({
|
|
964
|
-
|
|
965
|
-
context
|
|
966
|
-
...options
|
|
967
|
-
}) {
|
|
968
|
-
var _a, _b, _c, _d;
|
|
1057
|
+
async function requestAds(options) {
|
|
1058
|
+
var _a, _b, _c, _d, _e;
|
|
1059
|
+
const { context } = options;
|
|
969
1060
|
try {
|
|
970
1061
|
(_a = context.events) == null ? void 0 : _a.requestAd.dispatch({
|
|
971
1062
|
...options,
|
|
972
|
-
context
|
|
973
|
-
method
|
|
1063
|
+
context
|
|
974
1064
|
});
|
|
975
|
-
const [response, previews] = await Promise.all([(
|
|
1065
|
+
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
1066
|
logger.debug("Received response", response);
|
|
977
1067
|
if (!response.ok)
|
|
978
1068
|
throw new Error(`Failed to request ad: ${response.status} ${response.statusText}`);
|
|
@@ -988,18 +1078,18 @@ async function requestAds({
|
|
|
988
1078
|
};
|
|
989
1079
|
});
|
|
990
1080
|
if (matchedPreviews.length > 0)
|
|
991
|
-
(
|
|
1081
|
+
(_c = context.events) == null ? void 0 : _c.previewReceived.dispatch(matchedPreviews);
|
|
992
1082
|
const mergedResult = [
|
|
993
1083
|
...result.filter((ad) => !previews.some((preview) => preview.libId === ad.libId)),
|
|
994
1084
|
...matchedPreviews
|
|
995
1085
|
];
|
|
996
1086
|
if (mergedResult.length === 0)
|
|
997
1087
|
throw new Error("No ads found");
|
|
998
|
-
(
|
|
1088
|
+
(_d = context.events) == null ? void 0 : _d.responseReceived.dispatch(mergedResult);
|
|
999
1089
|
return mergedResult;
|
|
1000
1090
|
} catch (error) {
|
|
1001
1091
|
logger.error(String(error));
|
|
1002
|
-
(
|
|
1092
|
+
(_e = context.events) == null ? void 0 : _e.requestError.dispatch(error);
|
|
1003
1093
|
throw error;
|
|
1004
1094
|
}
|
|
1005
1095
|
}
|