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