@adhese/sdk 0.6.1 → 0.6.3
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/index.cjs +2311 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +2311 -0
- package/dist/index.js.map +1 -0
- package/package.json +5 -5
- package/dist/cjs/index.js +0 -1171
- package/dist/cjs/index.js.map +0 -1
- package/dist/es/index.js +0 -1171
- package/dist/es/index.js.map +0 -1
package/dist/cjs/index.js
DELETED
|
@@ -1,1171 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const sdkDevtools = require("@adhese/sdk-devtools");
|
|
4
|
-
const runtimeCore = require("@vue/runtime-core");
|
|
5
|
-
const lodashEs = require("lodash-es");
|
|
6
|
-
const zod = require("zod");
|
|
7
|
-
async function waitForDomLoad() {
|
|
8
|
-
return new Promise((resolve) => {
|
|
9
|
-
function onDomLoad() {
|
|
10
|
-
resolve();
|
|
11
|
-
window.removeEventListener("DOMContentLoaded", onDomLoad);
|
|
12
|
-
}
|
|
13
|
-
if (document.readyState === "loading")
|
|
14
|
-
document.addEventListener("DOMContentLoaded", onDomLoad);
|
|
15
|
-
else
|
|
16
|
-
resolve();
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
function createEventManager() {
|
|
20
|
-
const disposables = /* @__PURE__ */ new Set();
|
|
21
|
-
function dispose() {
|
|
22
|
-
for (const disposable of disposables)
|
|
23
|
-
disposable();
|
|
24
|
-
}
|
|
25
|
-
return new Proxy({
|
|
26
|
-
dispose
|
|
27
|
-
}, {
|
|
28
|
-
// eslint-disable-next-line ts/explicit-function-return-type
|
|
29
|
-
get(target, key, receiver) {
|
|
30
|
-
if (!(key in target) && typeof key === "string") {
|
|
31
|
-
const event = createEvent();
|
|
32
|
-
disposables.add(() => {
|
|
33
|
-
event.listeners.clear();
|
|
34
|
-
});
|
|
35
|
-
Reflect.set(target, key, event, receiver);
|
|
36
|
-
}
|
|
37
|
-
return Reflect.get(target, key, receiver);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
function createEvent() {
|
|
42
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
43
|
-
function dispatch(data) {
|
|
44
|
-
for (const listener of listeners)
|
|
45
|
-
void listener(data);
|
|
46
|
-
}
|
|
47
|
-
async function dispatchAsync(data) {
|
|
48
|
-
await Promise.allSettled(
|
|
49
|
-
Array.from(listeners).map((listener) => listener(data))
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
function addListener(listener) {
|
|
53
|
-
listeners.add(listener);
|
|
54
|
-
}
|
|
55
|
-
function removeListener(listener) {
|
|
56
|
-
listeners.delete(listener);
|
|
57
|
-
}
|
|
58
|
-
return {
|
|
59
|
-
listeners,
|
|
60
|
-
dispatch,
|
|
61
|
-
dispatchAsync,
|
|
62
|
-
addListener,
|
|
63
|
-
removeListener
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
function createSafeFrame({
|
|
67
|
-
renderFile,
|
|
68
|
-
context
|
|
69
|
-
}) {
|
|
70
|
-
const safeFrame = window.$sf;
|
|
71
|
-
if (!safeFrame)
|
|
72
|
-
throw new Error("SafeFrame not found");
|
|
73
|
-
const adhesePositions = /* @__PURE__ */ new Set();
|
|
74
|
-
const config = new safeFrame.host.Config({
|
|
75
|
-
auto: false,
|
|
76
|
-
debug: context.debug,
|
|
77
|
-
renderFile
|
|
78
|
-
});
|
|
79
|
-
function addPosition(ad, element) {
|
|
80
|
-
var _a;
|
|
81
|
-
if (!safeFrame)
|
|
82
|
-
throw new Error("SafeFrame not found");
|
|
83
|
-
const html = ad.ext === "js" && ad.body ? ad.body : ad.tag;
|
|
84
|
-
if (typeof html !== "string")
|
|
85
|
-
throw new Error("Ad tag is not a string");
|
|
86
|
-
const elementId = element.id || `ad-${ad.id}-${lodashEs.uniqueId()}`;
|
|
87
|
-
element.id = elementId;
|
|
88
|
-
const position = new safeFrame.host.Position({
|
|
89
|
-
id: elementId,
|
|
90
|
-
html,
|
|
91
|
-
src: ad.ext === "js" ? (_a = ad.swfSrc) == null ? void 0 : _a.href : void 0,
|
|
92
|
-
config: new safeFrame.host.PosConfig({
|
|
93
|
-
id: elementId,
|
|
94
|
-
w: Number(ad.width),
|
|
95
|
-
h: Number(ad.height),
|
|
96
|
-
size: `${Number(ad.width)}x${Number(ad.height)}`,
|
|
97
|
-
tgt: html.includes('target="_self"') ? "_self" : "_blank",
|
|
98
|
-
dest: elementId
|
|
99
|
-
})
|
|
100
|
-
});
|
|
101
|
-
adhesePositions.add(position);
|
|
102
|
-
return position;
|
|
103
|
-
}
|
|
104
|
-
async function render(position) {
|
|
105
|
-
if (!safeFrame)
|
|
106
|
-
throw new Error("SafeFrame not found");
|
|
107
|
-
safeFrame.host.render(position);
|
|
108
|
-
}
|
|
109
|
-
function dispose() {
|
|
110
|
-
}
|
|
111
|
-
return {
|
|
112
|
-
config,
|
|
113
|
-
addPosition,
|
|
114
|
-
render,
|
|
115
|
-
dispose
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
function renderIframe(ad, element) {
|
|
119
|
-
const iframe = document.createElement("iframe");
|
|
120
|
-
iframe.srcdoc = `
|
|
121
|
-
<!DOCTYPE html>
|
|
122
|
-
<html>
|
|
123
|
-
<head>
|
|
124
|
-
<style>
|
|
125
|
-
body {
|
|
126
|
-
margin: 0;
|
|
127
|
-
padding: 0;
|
|
128
|
-
overflow: hidden;
|
|
129
|
-
}
|
|
130
|
-
</style>
|
|
131
|
-
</head>
|
|
132
|
-
<body>
|
|
133
|
-
${String(ad.tag)}
|
|
134
|
-
</body>
|
|
135
|
-
`.replaceAll(/\s+/g, " ").trim();
|
|
136
|
-
iframe.style.border = "none";
|
|
137
|
-
iframe.style.width = ad.width ? `${ad.width}px` : "auto";
|
|
138
|
-
iframe.style.height = ad.height ? `${ad.height}px` : "auto";
|
|
139
|
-
element.replaceChildren(iframe);
|
|
140
|
-
}
|
|
141
|
-
function renderInline(ad, element) {
|
|
142
|
-
element.innerHTML = String(ad.tag);
|
|
143
|
-
}
|
|
144
|
-
function generateName(location, format, slot) {
|
|
145
|
-
return `${location}${slot ? `${slot}` : ""}-${format}`;
|
|
146
|
-
}
|
|
147
|
-
async function findDomSlots(context) {
|
|
148
|
-
await waitForDomLoad();
|
|
149
|
-
return Array.from(document.querySelectorAll(".adunit")).filter((element) => {
|
|
150
|
-
var _a;
|
|
151
|
-
if (!element.dataset.format)
|
|
152
|
-
return false;
|
|
153
|
-
const name = generateName(
|
|
154
|
-
context.location,
|
|
155
|
-
element.dataset.format,
|
|
156
|
-
element.dataset.slot
|
|
157
|
-
);
|
|
158
|
-
return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === name));
|
|
159
|
-
}).map((element) => createSlot({
|
|
160
|
-
format: element.dataset.format,
|
|
161
|
-
containingElement: element,
|
|
162
|
-
slot: element.dataset.slot,
|
|
163
|
-
context
|
|
164
|
-
})).filter((slot) => {
|
|
165
|
-
var _a;
|
|
166
|
-
return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === slot.name.value));
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
function createSlotManager({
|
|
170
|
-
initialSlots = [],
|
|
171
|
-
context
|
|
172
|
-
}) {
|
|
173
|
-
const scope = runtimeCore.effectScope();
|
|
174
|
-
return scope.run(() => {
|
|
175
|
-
const slots = runtimeCore.shallowReactive(/* @__PURE__ */ new Map());
|
|
176
|
-
runtimeCore.watchEffect(() => {
|
|
177
|
-
var _a;
|
|
178
|
-
(_a = context.events) == null ? void 0 : _a.changeSlots.dispatch(Array.from(slots.values()));
|
|
179
|
-
});
|
|
180
|
-
function getAll() {
|
|
181
|
-
return Array.from(slots).map(([, slot]) => slot);
|
|
182
|
-
}
|
|
183
|
-
function add(options) {
|
|
184
|
-
var _a;
|
|
185
|
-
const slot = createSlot({
|
|
186
|
-
...options,
|
|
187
|
-
onDispose,
|
|
188
|
-
context
|
|
189
|
-
});
|
|
190
|
-
function onDispose() {
|
|
191
|
-
var _a2;
|
|
192
|
-
slots.delete(slot.name.value);
|
|
193
|
-
logger.debug("Slot removed", {
|
|
194
|
-
slot,
|
|
195
|
-
slots: Array.from(slots)
|
|
196
|
-
});
|
|
197
|
-
(_a2 = context.events) == null ? void 0 : _a2.removeSlot.dispatch(slot);
|
|
198
|
-
}
|
|
199
|
-
slots.set(slot.name.value, slot);
|
|
200
|
-
runtimeCore.watch(slot.name, (newName, previousName) => {
|
|
201
|
-
slots.set(newName, slot);
|
|
202
|
-
slots.delete(previousName);
|
|
203
|
-
});
|
|
204
|
-
logger.debug("Slot added", {
|
|
205
|
-
slot,
|
|
206
|
-
slots: Array.from(slots.values())
|
|
207
|
-
});
|
|
208
|
-
(_a = context.events) == null ? void 0 : _a.addSlot.dispatch(slot);
|
|
209
|
-
return slot;
|
|
210
|
-
}
|
|
211
|
-
async function findDomSlots$1() {
|
|
212
|
-
const domSlots = await findDomSlots(
|
|
213
|
-
context
|
|
214
|
-
);
|
|
215
|
-
for (const slot of domSlots)
|
|
216
|
-
slots.set(slot.name.value, slot);
|
|
217
|
-
return domSlots;
|
|
218
|
-
}
|
|
219
|
-
function get(name) {
|
|
220
|
-
return slots.get(name);
|
|
221
|
-
}
|
|
222
|
-
function dispose() {
|
|
223
|
-
for (const slot of slots.values())
|
|
224
|
-
slot.dispose();
|
|
225
|
-
slots.clear();
|
|
226
|
-
scope.stop();
|
|
227
|
-
}
|
|
228
|
-
for (const options of initialSlots) {
|
|
229
|
-
add({
|
|
230
|
-
...options,
|
|
231
|
-
lazyLoading: false
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
return {
|
|
235
|
-
getAll,
|
|
236
|
-
add,
|
|
237
|
-
findDomSlots: findDomSlots$1,
|
|
238
|
-
get,
|
|
239
|
-
dispose
|
|
240
|
-
};
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
function onTcfConsentChange(callback) {
|
|
244
|
-
var _a;
|
|
245
|
-
(_a = window.__tcfapi) == null ? void 0 : _a.call(window, "addEventListener", 2, callback);
|
|
246
|
-
return () => {
|
|
247
|
-
var _a2;
|
|
248
|
-
return (_a2 = window.__tcfapi) == null ? void 0 : _a2.call(window, "removeEventListener", 2, callback);
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
function createQueryDetector({
|
|
252
|
-
onChange,
|
|
253
|
-
queries = {
|
|
254
|
-
mobile: "(max-width: 768px) and (pointer: coarse)",
|
|
255
|
-
tablet: "(min-width: 769px) and (max-width: 1024px) and (pointer: coarse)",
|
|
256
|
-
desktop: "(min-width: 1025px) and (pointer: fine)"
|
|
257
|
-
}
|
|
258
|
-
} = {}) {
|
|
259
|
-
const mediaMap = new Map(
|
|
260
|
-
Object.entries(queries).map(([key, query]) => [key, window.matchMedia(query)])
|
|
261
|
-
);
|
|
262
|
-
function getQuery() {
|
|
263
|
-
for (const [device, query] of Object.entries(queries)) {
|
|
264
|
-
if (window.matchMedia(query).matches)
|
|
265
|
-
return device;
|
|
266
|
-
}
|
|
267
|
-
return "unknown";
|
|
268
|
-
}
|
|
269
|
-
const handleOnChange = lodashEs.debounce(() => {
|
|
270
|
-
void (onChange == null ? void 0 : onChange(getQuery()));
|
|
271
|
-
logger.debug(`Change device ${getQuery()}`);
|
|
272
|
-
}, 50);
|
|
273
|
-
if (onChange) {
|
|
274
|
-
for (const query of mediaMap.values())
|
|
275
|
-
query.addEventListener("change", handleOnChange);
|
|
276
|
-
}
|
|
277
|
-
function dispose() {
|
|
278
|
-
for (const query of mediaMap.values())
|
|
279
|
-
query.removeEventListener("change", handleOnChange);
|
|
280
|
-
}
|
|
281
|
-
return {
|
|
282
|
-
queries: mediaMap,
|
|
283
|
-
getQuery,
|
|
284
|
-
dispose
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
const defaultLogLevels = ["trace", "debug", "info", "warn", "error"];
|
|
288
|
-
function createLogger({
|
|
289
|
-
scope,
|
|
290
|
-
logLevels = defaultLogLevels,
|
|
291
|
-
minLogLevelThreshold = logLevels[2]
|
|
292
|
-
}) {
|
|
293
|
-
const logs = /* @__PURE__ */ new Set();
|
|
294
|
-
let currentMinLogLevelThreshold = minLogLevelThreshold;
|
|
295
|
-
const events = createEventManager();
|
|
296
|
-
const logFunctions = Object.fromEntries(logLevels.map((level, index) => {
|
|
297
|
-
const logFunction = (message, attributes) => {
|
|
298
|
-
logs.add({
|
|
299
|
-
scope,
|
|
300
|
-
level,
|
|
301
|
-
message,
|
|
302
|
-
attributes,
|
|
303
|
-
timestamp: Date.now(),
|
|
304
|
-
id: lodashEs.uniqueId()
|
|
305
|
-
});
|
|
306
|
-
events.log.dispatch({
|
|
307
|
-
scope,
|
|
308
|
-
level,
|
|
309
|
-
message,
|
|
310
|
-
attributes,
|
|
311
|
-
timestamp: Date.now(),
|
|
312
|
-
id: lodashEs.uniqueId()
|
|
313
|
-
});
|
|
314
|
-
if (index >= logLevels.indexOf(currentMinLogLevelThreshold)) {
|
|
315
|
-
if (["warn", "error", "trace"].includes(level)) {
|
|
316
|
-
console[level](...[
|
|
317
|
-
`%c${scope}`,
|
|
318
|
-
"color: red; font-weight: bold;",
|
|
319
|
-
message,
|
|
320
|
-
attributes
|
|
321
|
-
].filter(Boolean));
|
|
322
|
-
} else {
|
|
323
|
-
console.log(...[
|
|
324
|
-
`%c${scope} %c${level.toUpperCase()}`,
|
|
325
|
-
"color: red; font-weight: bold;",
|
|
326
|
-
"font-weight: bold;",
|
|
327
|
-
message,
|
|
328
|
-
attributes
|
|
329
|
-
].filter(Boolean));
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
return [level, logFunction];
|
|
334
|
-
}));
|
|
335
|
-
return {
|
|
336
|
-
...logFunctions,
|
|
337
|
-
scope,
|
|
338
|
-
events,
|
|
339
|
-
setMinLogLevelThreshold(level) {
|
|
340
|
-
currentMinLogLevelThreshold = level;
|
|
341
|
-
},
|
|
342
|
-
resetMinLogLevelThreshold() {
|
|
343
|
-
currentMinLogLevelThreshold = minLogLevelThreshold;
|
|
344
|
-
},
|
|
345
|
-
getMinLogLevelThreshold() {
|
|
346
|
-
return currentMinLogLevelThreshold;
|
|
347
|
-
},
|
|
348
|
-
getLogs() {
|
|
349
|
-
return Array.from(logs);
|
|
350
|
-
},
|
|
351
|
-
resetLogs() {
|
|
352
|
-
events.reset.dispatch();
|
|
353
|
-
logs.clear();
|
|
354
|
-
}
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
const logger = createLogger({
|
|
358
|
-
scope: "Adhese SDK"
|
|
359
|
-
});
|
|
360
|
-
function createParameters(options, queryDetector) {
|
|
361
|
-
const parameters = /* @__PURE__ */ new Map();
|
|
362
|
-
if (options.logReferrer)
|
|
363
|
-
parameters.set("re", btoa(document.referrer));
|
|
364
|
-
if (options.logUrl)
|
|
365
|
-
parameters.set("ur", btoa(window.location.href));
|
|
366
|
-
for (const [key, value] of Object.entries({
|
|
367
|
-
...options.parameters ?? {},
|
|
368
|
-
tl: options.consent ? "all" : "none",
|
|
369
|
-
dt: queryDetector.getQuery(),
|
|
370
|
-
br: queryDetector.getQuery(),
|
|
371
|
-
rn: lodashEs.random(1e4).toString()
|
|
372
|
-
}))
|
|
373
|
-
parameters.set(key, value);
|
|
374
|
-
return parameters;
|
|
375
|
-
}
|
|
376
|
-
function setupLogging(mergedOptions) {
|
|
377
|
-
if (mergedOptions.debug || window.location.search.includes("adhese_debug=true")) {
|
|
378
|
-
logger.setMinLogLevelThreshold("debug");
|
|
379
|
-
logger.debug("Debug logging enabled");
|
|
380
|
-
}
|
|
381
|
-
logger.debug("Created Adhese SDK instance", {
|
|
382
|
-
mergedOptions
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
function isPreviewMode() {
|
|
386
|
-
return window.location.search.includes("adhesePreviewCreativeId");
|
|
387
|
-
}
|
|
388
|
-
function createHook({
|
|
389
|
-
onRun,
|
|
390
|
-
onAdd
|
|
391
|
-
}) {
|
|
392
|
-
const callbacks = /* @__PURE__ */ new Set();
|
|
393
|
-
function run() {
|
|
394
|
-
for (const callback of callbacks)
|
|
395
|
-
callback();
|
|
396
|
-
onRun == null ? void 0 : onRun(callbacks);
|
|
397
|
-
}
|
|
398
|
-
function add(callback) {
|
|
399
|
-
callbacks.add(callback);
|
|
400
|
-
onAdd == null ? void 0 : onAdd(callbacks);
|
|
401
|
-
}
|
|
402
|
-
return [run, add];
|
|
403
|
-
}
|
|
404
|
-
let resolveOnInitPromise = () => {
|
|
405
|
-
};
|
|
406
|
-
let isInit = false;
|
|
407
|
-
const waitOnInit = new Promise((resolve) => {
|
|
408
|
-
resolveOnInitPromise = resolve;
|
|
409
|
-
});
|
|
410
|
-
const [runOnInit, onInit] = createHook({
|
|
411
|
-
onRun(callbacks) {
|
|
412
|
-
isInit = true;
|
|
413
|
-
resolveOnInitPromise();
|
|
414
|
-
logger.debug("Initialization completed");
|
|
415
|
-
callbacks.clear();
|
|
416
|
-
},
|
|
417
|
-
onAdd() {
|
|
418
|
-
if (isInit)
|
|
419
|
-
runOnInit();
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
function createAdhese(options) {
|
|
423
|
-
const scope = runtimeCore.effectScope();
|
|
424
|
-
return scope.run(() => {
|
|
425
|
-
const mergedOptions = {
|
|
426
|
-
host: `https://ads-${options.account}.adhese.com`,
|
|
427
|
-
poolHost: `https://pool-${options.account}.adhese.com`,
|
|
428
|
-
location: "homepage",
|
|
429
|
-
requestType: "POST",
|
|
430
|
-
debug: false,
|
|
431
|
-
initialSlots: [],
|
|
432
|
-
findDomSlotsOnLoad: false,
|
|
433
|
-
consent: false,
|
|
434
|
-
logReferrer: true,
|
|
435
|
-
logUrl: true,
|
|
436
|
-
safeFrame: false,
|
|
437
|
-
eagerRendering: false,
|
|
438
|
-
viewabilityTracking: true,
|
|
439
|
-
...options
|
|
440
|
-
};
|
|
441
|
-
setupLogging(mergedOptions);
|
|
442
|
-
const context = runtimeCore.reactive({
|
|
443
|
-
location: mergedOptions.location,
|
|
444
|
-
consent: mergedOptions.consent,
|
|
445
|
-
debug: mergedOptions.debug,
|
|
446
|
-
getAll,
|
|
447
|
-
get,
|
|
448
|
-
options: mergedOptions,
|
|
449
|
-
logger
|
|
450
|
-
});
|
|
451
|
-
context.events = createEventManager();
|
|
452
|
-
context.safeFrame = options.safeFrame ? createSafeFrame({
|
|
453
|
-
renderFile: `${mergedOptions.poolHost}/sf/r.html`,
|
|
454
|
-
context
|
|
455
|
-
}) : void 0;
|
|
456
|
-
function getLocation() {
|
|
457
|
-
return context.location;
|
|
458
|
-
}
|
|
459
|
-
function setLocation(newLocation) {
|
|
460
|
-
var _a;
|
|
461
|
-
context.location = newLocation;
|
|
462
|
-
(_a = context.events) == null ? void 0 : _a.locationChange.dispatch(newLocation);
|
|
463
|
-
}
|
|
464
|
-
const queryDetector = createQueryDetector({
|
|
465
|
-
onChange: onQueryChange,
|
|
466
|
-
queries: mergedOptions.queries
|
|
467
|
-
});
|
|
468
|
-
context.parameters = createParameters(mergedOptions, queryDetector);
|
|
469
|
-
runtimeCore.watch(
|
|
470
|
-
context.parameters,
|
|
471
|
-
onParametersChange,
|
|
472
|
-
{
|
|
473
|
-
deep: true,
|
|
474
|
-
immediate: true
|
|
475
|
-
}
|
|
476
|
-
);
|
|
477
|
-
function onParametersChange() {
|
|
478
|
-
var _a;
|
|
479
|
-
if (context.parameters)
|
|
480
|
-
(_a = context.events) == null ? void 0 : _a.parametersChange.dispatch(context.parameters);
|
|
481
|
-
}
|
|
482
|
-
async function onQueryChange() {
|
|
483
|
-
var _a, _b;
|
|
484
|
-
const query = queryDetector.getQuery();
|
|
485
|
-
(_a = context.parameters) == null ? void 0 : _a.set("dt", query);
|
|
486
|
-
(_b = context.parameters) == null ? void 0 : _b.set("br", query);
|
|
487
|
-
await fetchAndRenderAllSlots();
|
|
488
|
-
}
|
|
489
|
-
function getConsent() {
|
|
490
|
-
return context.consent;
|
|
491
|
-
}
|
|
492
|
-
function setConsent(newConsent) {
|
|
493
|
-
var _a, _b;
|
|
494
|
-
(_a = context.parameters) == null ? void 0 : _a.set("tl", newConsent ? "all" : "none");
|
|
495
|
-
context.consent = newConsent;
|
|
496
|
-
(_b = context.events) == null ? void 0 : _b.consentChange.dispatch(newConsent);
|
|
497
|
-
}
|
|
498
|
-
const slotManager = createSlotManager({
|
|
499
|
-
initialSlots: mergedOptions.initialSlots,
|
|
500
|
-
context
|
|
501
|
-
});
|
|
502
|
-
function getAll() {
|
|
503
|
-
return slotManager.getAll() ?? [];
|
|
504
|
-
}
|
|
505
|
-
function get(name) {
|
|
506
|
-
return slotManager.get(name);
|
|
507
|
-
}
|
|
508
|
-
async function addSlot(slotOptions) {
|
|
509
|
-
if (!slotManager)
|
|
510
|
-
throw new Error("Slot manager not initialized");
|
|
511
|
-
const slot = slotManager.add(slotOptions);
|
|
512
|
-
if (!slot.lazyLoading) {
|
|
513
|
-
slot.ad.value = await requestAd({
|
|
514
|
-
slot,
|
|
515
|
-
context
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
|
-
return slot;
|
|
519
|
-
}
|
|
520
|
-
async function findDomSlots2() {
|
|
521
|
-
const domSlots = (await slotManager.findDomSlots() ?? []).filter((slot) => !slot.lazyLoading);
|
|
522
|
-
if (domSlots.length <= 0)
|
|
523
|
-
return [];
|
|
524
|
-
const ads = await requestAds({
|
|
525
|
-
slots: domSlots,
|
|
526
|
-
context
|
|
527
|
-
});
|
|
528
|
-
for (const ad of ads) {
|
|
529
|
-
const slot = slotManager.get(ad.slotName);
|
|
530
|
-
if (slot)
|
|
531
|
-
slot.ad.value = ad;
|
|
532
|
-
}
|
|
533
|
-
return domSlots;
|
|
534
|
-
}
|
|
535
|
-
let unmountDevtools;
|
|
536
|
-
async function toggleDebug() {
|
|
537
|
-
var _a, _b;
|
|
538
|
-
context.debug = !context.debug;
|
|
539
|
-
if (context.debug && !unmountDevtools) {
|
|
540
|
-
unmountDevtools = await sdkDevtools.createDevtools(context);
|
|
541
|
-
logger.setMinLogLevelThreshold("debug");
|
|
542
|
-
logger.debug("Debug mode enabled");
|
|
543
|
-
(_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
|
|
544
|
-
} else {
|
|
545
|
-
logger.debug("Debug mode disabled");
|
|
546
|
-
unmountDevtools == null ? void 0 : unmountDevtools();
|
|
547
|
-
unmountDevtools = void 0;
|
|
548
|
-
logger.setMinLogLevelThreshold("info");
|
|
549
|
-
(_b = context.events) == null ? void 0 : _b.debugChange.dispatch(false);
|
|
550
|
-
}
|
|
551
|
-
return context.debug;
|
|
552
|
-
}
|
|
553
|
-
async function fetchAndRenderAllSlots() {
|
|
554
|
-
const slots = (slotManager.getAll() ?? []).filter((slot) => !slot.lazyLoading);
|
|
555
|
-
if (slots.length === 0)
|
|
556
|
-
return;
|
|
557
|
-
const ads = await requestAds({
|
|
558
|
-
slots,
|
|
559
|
-
context
|
|
560
|
-
});
|
|
561
|
-
for (const ad of ads) {
|
|
562
|
-
const slot = slotManager.get(ad.slotName);
|
|
563
|
-
if (slot)
|
|
564
|
-
slot.ad.value = ad;
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
const disposeOnTcfConsentChange = onTcfConsentChange(async (data) => {
|
|
568
|
-
var _a, _b;
|
|
569
|
-
if (!data.tcString)
|
|
570
|
-
return;
|
|
571
|
-
logger.debug("TCF v2 consent data received", {
|
|
572
|
-
data
|
|
573
|
-
});
|
|
574
|
-
(_a = context.parameters) == null ? void 0 : _a.set("xt", data.tcString);
|
|
575
|
-
(_b = context.parameters) == null ? void 0 : _b.delete("tl");
|
|
576
|
-
await fetchAndRenderAllSlots();
|
|
577
|
-
});
|
|
578
|
-
function dispose() {
|
|
579
|
-
var _a, _b;
|
|
580
|
-
unmountDevtools == null ? void 0 : unmountDevtools();
|
|
581
|
-
queryDetector.dispose();
|
|
582
|
-
slotManager.dispose();
|
|
583
|
-
queryDetector.dispose();
|
|
584
|
-
disposeOnTcfConsentChange();
|
|
585
|
-
(_a = context.parameters) == null ? void 0 : _a.clear();
|
|
586
|
-
logger.resetLogs();
|
|
587
|
-
(_b = context.events) == null ? void 0 : _b.dispose();
|
|
588
|
-
logger.info("Adhese instance disposed");
|
|
589
|
-
scope.stop();
|
|
590
|
-
}
|
|
591
|
-
onInit(async () => {
|
|
592
|
-
var _a;
|
|
593
|
-
if ((slotManager.getAll().length ?? 0) > 0)
|
|
594
|
-
await fetchAndRenderAllSlots().catch(logger.error);
|
|
595
|
-
if (mergedOptions.findDomSlotsOnLoad)
|
|
596
|
-
await findDomSlots2();
|
|
597
|
-
if (mergedOptions.debug || window.location.search.includes("adhese_debug=true") || isPreviewMode()) {
|
|
598
|
-
unmountDevtools = await sdkDevtools.createDevtools(context);
|
|
599
|
-
(_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
|
|
600
|
-
}
|
|
601
|
-
if (!scope.active)
|
|
602
|
-
dispose();
|
|
603
|
-
});
|
|
604
|
-
runOnInit();
|
|
605
|
-
return {
|
|
606
|
-
...mergedOptions,
|
|
607
|
-
...slotManager,
|
|
608
|
-
parameters: context.parameters,
|
|
609
|
-
events: context.events,
|
|
610
|
-
getLocation,
|
|
611
|
-
setLocation,
|
|
612
|
-
getConsent,
|
|
613
|
-
setConsent,
|
|
614
|
-
addSlot,
|
|
615
|
-
findDomSlots: findDomSlots2,
|
|
616
|
-
dispose,
|
|
617
|
-
toggleDebug,
|
|
618
|
-
context
|
|
619
|
-
};
|
|
620
|
-
});
|
|
621
|
-
}
|
|
622
|
-
function addTrackingPixel(url) {
|
|
623
|
-
const img = document.createElement("img");
|
|
624
|
-
img.src = url.toString();
|
|
625
|
-
img.style.height = "1px";
|
|
626
|
-
img.style.width = "1px";
|
|
627
|
-
img.style.margin = "-1px";
|
|
628
|
-
img.style.border = "0";
|
|
629
|
-
img.style.position = "absolute";
|
|
630
|
-
img.style.top = "0";
|
|
631
|
-
return document.body.appendChild(img);
|
|
632
|
-
}
|
|
633
|
-
function useViewabilityObserver({ context, ad, name, element }) {
|
|
634
|
-
let timeoutId = null;
|
|
635
|
-
const {
|
|
636
|
-
threshold,
|
|
637
|
-
duration,
|
|
638
|
-
rootMargin
|
|
639
|
-
} = {
|
|
640
|
-
threshold: 0.2,
|
|
641
|
-
duration: 1e3,
|
|
642
|
-
rootMargin: "0px",
|
|
643
|
-
...context.options.viewabilityTrackingOptions
|
|
644
|
-
};
|
|
645
|
-
const trackingPixel = runtimeCore.ref(null);
|
|
646
|
-
const isTracked = runtimeCore.computed(() => Boolean(trackingPixel.value));
|
|
647
|
-
const viewabilityObserver = new IntersectionObserver(([entry]) => {
|
|
648
|
-
if (context.options.viewabilityTracking && !trackingPixel.value && ad) {
|
|
649
|
-
const ratio = lodashEs.round(entry.intersectionRatio, 1);
|
|
650
|
-
if (ratio >= threshold && !timeoutId) {
|
|
651
|
-
timeoutId = setTimeout(() => {
|
|
652
|
-
var _a, _b, _c;
|
|
653
|
-
timeoutId = null;
|
|
654
|
-
if ((_a = ad.value) == null ? void 0 : _a.viewableImpressionCounter) {
|
|
655
|
-
trackingPixel.value = addTrackingPixel(ad.value.viewableImpressionCounter);
|
|
656
|
-
logger.debug(`Viewability tracking pixel fired for ${name.value}`);
|
|
657
|
-
(_c = context.events) == null ? void 0 : _c.changeSlots.dispatch(Array.from(((_b = context.getAll) == null ? void 0 : _b.call(context)) ?? []));
|
|
658
|
-
}
|
|
659
|
-
}, duration);
|
|
660
|
-
} else if (ratio < threshold && timeoutId) {
|
|
661
|
-
clearTimeout(timeoutId);
|
|
662
|
-
timeoutId = null;
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
}, {
|
|
666
|
-
rootMargin,
|
|
667
|
-
threshold: Array.from({ length: 11 }, (_, i) => i * 0.1)
|
|
668
|
-
});
|
|
669
|
-
function observe(newElement, oldElement) {
|
|
670
|
-
if (oldElement)
|
|
671
|
-
viewabilityObserver.unobserve(oldElement);
|
|
672
|
-
if (newElement && context.options.viewabilityTracking)
|
|
673
|
-
viewabilityObserver.observe(newElement);
|
|
674
|
-
return () => {
|
|
675
|
-
if (newElement)
|
|
676
|
-
viewabilityObserver.unobserve(newElement);
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
runtimeCore.watch(element, observe);
|
|
680
|
-
observe(element.value);
|
|
681
|
-
return [isTracked, () => {
|
|
682
|
-
var _a;
|
|
683
|
-
(_a = trackingPixel.value) == null ? void 0 : _a.remove();
|
|
684
|
-
viewabilityObserver.disconnect();
|
|
685
|
-
}];
|
|
686
|
-
}
|
|
687
|
-
function useRenderIntersectionObserver({ ad, options, element, render }) {
|
|
688
|
-
var _a;
|
|
689
|
-
const isInViewport = runtimeCore.ref(false);
|
|
690
|
-
const renderIntersectionObserver = new IntersectionObserver((entries) => {
|
|
691
|
-
isInViewport.value = entries.some((entry) => entry.isIntersecting);
|
|
692
|
-
if (isInViewport.value) {
|
|
693
|
-
(async () => {
|
|
694
|
-
if (!ad.value && options.lazyLoading)
|
|
695
|
-
await render();
|
|
696
|
-
await render(ad.value ?? void 0);
|
|
697
|
-
})().catch(logger.error);
|
|
698
|
-
}
|
|
699
|
-
}, {
|
|
700
|
-
rootMargin: ((_a = options.lazyLoadingOptions) == null ? void 0 : _a.rootMargin) ?? "200px",
|
|
701
|
-
threshold: 0
|
|
702
|
-
});
|
|
703
|
-
function observe(newElement, oldElement) {
|
|
704
|
-
if (oldElement)
|
|
705
|
-
renderIntersectionObserver.unobserve(oldElement);
|
|
706
|
-
if (newElement)
|
|
707
|
-
renderIntersectionObserver.observe(newElement);
|
|
708
|
-
return () => {
|
|
709
|
-
if (newElement)
|
|
710
|
-
renderIntersectionObserver.unobserve(newElement);
|
|
711
|
-
};
|
|
712
|
-
}
|
|
713
|
-
runtimeCore.watch(element, observe);
|
|
714
|
-
observe(element.value);
|
|
715
|
-
return [isInViewport, () => {
|
|
716
|
-
renderIntersectionObserver.disconnect();
|
|
717
|
-
}];
|
|
718
|
-
}
|
|
719
|
-
const renderFunctions = {
|
|
720
|
-
iframe: renderIframe,
|
|
721
|
-
inline: renderInline
|
|
722
|
-
};
|
|
723
|
-
function createSlot(options) {
|
|
724
|
-
const scope = runtimeCore.effectScope();
|
|
725
|
-
return scope.run(() => {
|
|
726
|
-
const {
|
|
727
|
-
containingElement,
|
|
728
|
-
slot,
|
|
729
|
-
context,
|
|
730
|
-
renderMode = "iframe"
|
|
731
|
-
} = options;
|
|
732
|
-
const parameters = runtimeCore.reactive(new Map(Object.entries(options.parameters ?? {})));
|
|
733
|
-
let queryDetector = null;
|
|
734
|
-
if (typeof options.format !== "string") {
|
|
735
|
-
queryDetector = createQueryDetector({
|
|
736
|
-
onChange: onQueryChange,
|
|
737
|
-
queries: Object.fromEntries(options.format.map((item) => [item.format, item.query]))
|
|
738
|
-
});
|
|
739
|
-
}
|
|
740
|
-
const format = runtimeCore.ref(queryDetector ? queryDetector.getQuery() : options.format);
|
|
741
|
-
function onQueryChange(newFormat) {
|
|
742
|
-
format.value = newFormat;
|
|
743
|
-
}
|
|
744
|
-
const ad = runtimeCore.ref(null);
|
|
745
|
-
const originalAd = runtimeCore.ref(ad.value);
|
|
746
|
-
const name = runtimeCore.computed(() => generateName(context.location, format.value, slot));
|
|
747
|
-
runtimeCore.watch(name, async (newName, oldName) => {
|
|
748
|
-
var _a;
|
|
749
|
-
if (newName === oldName)
|
|
750
|
-
return;
|
|
751
|
-
(_a = options.onNameChange) == null ? void 0 : _a.call(options, newName, oldName);
|
|
752
|
-
const newAd = await requestAd$1();
|
|
753
|
-
cleanElement();
|
|
754
|
-
ad.value = newAd;
|
|
755
|
-
originalAd.value = newAd;
|
|
756
|
-
});
|
|
757
|
-
const isDomLoaded = useDomLoaded();
|
|
758
|
-
const element = runtimeCore.computed(
|
|
759
|
-
() => {
|
|
760
|
-
if (!(typeof containingElement === "string" || !containingElement))
|
|
761
|
-
return containingElement;
|
|
762
|
-
if (!isDomLoaded.value)
|
|
763
|
-
return null;
|
|
764
|
-
return document.querySelector(`.adunit[data-format="${format.value}"]#${containingElement}${slot ? `[data-slot="${slot}"]` : ""}`);
|
|
765
|
-
}
|
|
766
|
-
);
|
|
767
|
-
function getElement() {
|
|
768
|
-
var _a, _b;
|
|
769
|
-
if (renderMode === "iframe")
|
|
770
|
-
return ((_a = element.value) == null ? void 0 : _a.querySelector("iframe")) ?? null;
|
|
771
|
-
return ((_b = element.value) == null ? void 0 : _b.innerHTML) ? element.value.firstElementChild : null;
|
|
772
|
-
}
|
|
773
|
-
const [isInViewport, disposeRenderIntersectionObserver] = useRenderIntersectionObserver({
|
|
774
|
-
ad,
|
|
775
|
-
options,
|
|
776
|
-
element,
|
|
777
|
-
render
|
|
778
|
-
});
|
|
779
|
-
runtimeCore.watch([ad, isInViewport], async ([newAd, newIsInViewport], [oldAd]) => {
|
|
780
|
-
var _a, _b;
|
|
781
|
-
if (!newAd || lodashEs.isEqual(newAd, oldAd))
|
|
782
|
-
return;
|
|
783
|
-
if (newIsInViewport || context.options.eagerRendering)
|
|
784
|
-
await render(newAd);
|
|
785
|
-
(_b = context.events) == null ? void 0 : _b.changeSlots.dispatch(Array.from(((_a = context.getAll) == null ? void 0 : _a.call(context)) ?? []));
|
|
786
|
-
});
|
|
787
|
-
const [
|
|
788
|
-
isViewabilityTracked,
|
|
789
|
-
disposeViewabilityObserver
|
|
790
|
-
] = useViewabilityObserver({
|
|
791
|
-
context,
|
|
792
|
-
ad,
|
|
793
|
-
name,
|
|
794
|
-
element
|
|
795
|
-
});
|
|
796
|
-
const impressionTrackingPixelElement = runtimeCore.ref(null);
|
|
797
|
-
const isImpressionTracked = runtimeCore.computed(() => Boolean(impressionTrackingPixelElement.value));
|
|
798
|
-
async function requestAd$1() {
|
|
799
|
-
const response = await requestAd({
|
|
800
|
-
slot: {
|
|
801
|
-
name: name.value,
|
|
802
|
-
parameters
|
|
803
|
-
},
|
|
804
|
-
context
|
|
805
|
-
});
|
|
806
|
-
originalAd.value = response;
|
|
807
|
-
return response;
|
|
808
|
-
}
|
|
809
|
-
async function render(adToRender) {
|
|
810
|
-
var _a, _b;
|
|
811
|
-
await waitForDomLoad();
|
|
812
|
-
await waitOnInit;
|
|
813
|
-
const renderAd = adToRender ?? ad.value ?? await requestAd$1();
|
|
814
|
-
if (originalAd.value) {
|
|
815
|
-
ad.value = ((_a = options.onBeforeRender) == null ? void 0 : _a.call(options, adToRender ?? originalAd.value)) ?? renderAd;
|
|
816
|
-
}
|
|
817
|
-
if (!element.value) {
|
|
818
|
-
const error = `Could not create slot for format ${format.value}. No element found.`;
|
|
819
|
-
logger.error(error, options);
|
|
820
|
-
throw new Error(error);
|
|
821
|
-
}
|
|
822
|
-
if (context.debug)
|
|
823
|
-
element.value.style.position = "relative";
|
|
824
|
-
if (context.safeFrame && ad.value && renderMode === "iframe") {
|
|
825
|
-
const position = context.safeFrame.addPosition(ad.value, element.value);
|
|
826
|
-
await context.safeFrame.render(position);
|
|
827
|
-
} else {
|
|
828
|
-
renderFunctions[renderMode](renderAd, element.value);
|
|
829
|
-
}
|
|
830
|
-
if (renderAd.impressionCounter && !impressionTrackingPixelElement.value) {
|
|
831
|
-
impressionTrackingPixelElement.value = addTrackingPixel(renderAd.impressionCounter);
|
|
832
|
-
logger.debug(`Impression tracking pixel fired for ${name.value}`);
|
|
833
|
-
}
|
|
834
|
-
logger.debug("Slot rendered", {
|
|
835
|
-
renderedElement: element,
|
|
836
|
-
location: context.location,
|
|
837
|
-
format,
|
|
838
|
-
containingElement
|
|
839
|
-
});
|
|
840
|
-
(_b = options.onRender) == null ? void 0 : _b.call(options, element.value);
|
|
841
|
-
disposeRenderIntersectionObserver();
|
|
842
|
-
return element.value;
|
|
843
|
-
}
|
|
844
|
-
function cleanElement() {
|
|
845
|
-
if (!element.value)
|
|
846
|
-
return;
|
|
847
|
-
element.value.innerHTML = "";
|
|
848
|
-
element.value.style.position = "";
|
|
849
|
-
element.value.style.width = "";
|
|
850
|
-
element.value.style.height = "";
|
|
851
|
-
}
|
|
852
|
-
function dispose() {
|
|
853
|
-
var _a, _b;
|
|
854
|
-
cleanElement();
|
|
855
|
-
(_a = impressionTrackingPixelElement.value) == null ? void 0 : _a.remove();
|
|
856
|
-
ad.value = null;
|
|
857
|
-
disposeRenderIntersectionObserver();
|
|
858
|
-
disposeViewabilityObserver();
|
|
859
|
-
(_b = options.onDispose) == null ? void 0 : _b.call(options);
|
|
860
|
-
queryDetector == null ? void 0 : queryDetector.dispose();
|
|
861
|
-
scope.stop();
|
|
862
|
-
}
|
|
863
|
-
return {
|
|
864
|
-
location: context.location,
|
|
865
|
-
lazyLoading: options.lazyLoading ?? false,
|
|
866
|
-
slot,
|
|
867
|
-
parameters,
|
|
868
|
-
format,
|
|
869
|
-
name,
|
|
870
|
-
ad,
|
|
871
|
-
isViewabilityTracked,
|
|
872
|
-
isImpressionTracked,
|
|
873
|
-
render,
|
|
874
|
-
getElement,
|
|
875
|
-
dispose
|
|
876
|
-
};
|
|
877
|
-
});
|
|
878
|
-
}
|
|
879
|
-
function useDomLoaded() {
|
|
880
|
-
const isDomLoaded = runtimeCore.ref(false);
|
|
881
|
-
onInit(async () => {
|
|
882
|
-
await waitForDomLoad();
|
|
883
|
-
isDomLoaded.value = true;
|
|
884
|
-
});
|
|
885
|
-
return isDomLoaded;
|
|
886
|
-
}
|
|
887
|
-
const numberLike = zod.union([zod.coerce.string().regex(/^\d+$/), zod.literal("")]).transform((value) => value === "" ? void 0 : Number(value));
|
|
888
|
-
const booleanLike = zod.union([zod.coerce.boolean(), zod.literal("")]);
|
|
889
|
-
const urlLike = zod.union([zod.coerce.string(), zod.literal("")]).transform((value) => {
|
|
890
|
-
try {
|
|
891
|
-
return new URL(value);
|
|
892
|
-
} catch {
|
|
893
|
-
return void 0;
|
|
894
|
-
}
|
|
895
|
-
});
|
|
896
|
-
const dateLike = zod.union([zod.coerce.string(), zod.literal("")]).transform((value) => {
|
|
897
|
-
if (value === "")
|
|
898
|
-
return void 0;
|
|
899
|
-
const date = new Date(numberLike.safeParse(value).success ? Number(value) : value);
|
|
900
|
-
if (Number.isNaN(date.getTime()))
|
|
901
|
-
return void 0;
|
|
902
|
-
return date;
|
|
903
|
-
});
|
|
904
|
-
const cssValueLike = zod.union([zod.coerce.string(), zod.literal(""), zod.number()]).transform((value) => {
|
|
905
|
-
if (value === "" || value === 0 || value === "0")
|
|
906
|
-
return void 0;
|
|
907
|
-
if (numberLike.parse(value))
|
|
908
|
-
return `${numberLike.parse(value)}px`;
|
|
909
|
-
return String(value);
|
|
910
|
-
});
|
|
911
|
-
const isJson = zod.string().transform((value, { addIssue }) => {
|
|
912
|
-
try {
|
|
913
|
-
return JSON.parse(value.replaceAll("'", '"'));
|
|
914
|
-
} catch (error) {
|
|
915
|
-
addIssue({
|
|
916
|
-
code: zod.ZodIssueCode.custom,
|
|
917
|
-
message: `Invalid JSON: ${error.message}`
|
|
918
|
-
});
|
|
919
|
-
return zod.NEVER;
|
|
920
|
-
}
|
|
921
|
-
});
|
|
922
|
-
const isHtmlString = zod.string().transform((value, { addIssue }) => {
|
|
923
|
-
var _a;
|
|
924
|
-
const htmlParser = new DOMParser();
|
|
925
|
-
try {
|
|
926
|
-
const html = htmlParser.parseFromString(value, "text/html");
|
|
927
|
-
if (((_a = html.body) == null ? void 0 : _a.children.length) === 0)
|
|
928
|
-
throw new Error("Invalid HTML");
|
|
929
|
-
return value;
|
|
930
|
-
} catch (error) {
|
|
931
|
-
addIssue({
|
|
932
|
-
code: zod.ZodIssueCode.custom,
|
|
933
|
-
message: error.message
|
|
934
|
-
});
|
|
935
|
-
return zod.NEVER;
|
|
936
|
-
}
|
|
937
|
-
});
|
|
938
|
-
const isJsonOrHtmlString = zod.union([isJson, isHtmlString]);
|
|
939
|
-
const isJsonOrHtmlOptionalString = zod.union([zod.coerce.string(), isJsonOrHtmlString]).transform((value) => {
|
|
940
|
-
if (value === "")
|
|
941
|
-
return void 0;
|
|
942
|
-
return value;
|
|
943
|
-
}).optional();
|
|
944
|
-
const baseSchema = zod.object({
|
|
945
|
-
adDuration: numberLike.optional(),
|
|
946
|
-
adFormat: zod.string().optional(),
|
|
947
|
-
adType: zod.string(),
|
|
948
|
-
additionalCreativeTracker: urlLike.optional(),
|
|
949
|
-
additionalViewableTracker: zod.string().optional(),
|
|
950
|
-
adspaceEnd: dateLike.optional(),
|
|
951
|
-
adspaceId: zod.string().optional(),
|
|
952
|
-
adspaceKey: zod.string().optional(),
|
|
953
|
-
adspaceStart: dateLike.optional(),
|
|
954
|
-
advertiserId: zod.string().optional(),
|
|
955
|
-
altText: zod.string().optional(),
|
|
956
|
-
auctionable: booleanLike.optional(),
|
|
957
|
-
body: isJsonOrHtmlOptionalString,
|
|
958
|
-
clickTag: urlLike.optional(),
|
|
959
|
-
comment: zod.string().optional(),
|
|
960
|
-
creativeName: zod.string().optional(),
|
|
961
|
-
deliveryGroupId: zod.string().optional(),
|
|
962
|
-
deliveryMultiples: zod.string().optional(),
|
|
963
|
-
ext: zod.string().optional(),
|
|
964
|
-
extension: zod.object({
|
|
965
|
-
mediaType: zod.string(),
|
|
966
|
-
prebid: zod.unknown().optional()
|
|
967
|
-
}).optional(),
|
|
968
|
-
height: numberLike.optional(),
|
|
969
|
-
id: zod.string(),
|
|
970
|
-
impressionCounter: urlLike.optional(),
|
|
971
|
-
libId: zod.string().optional(),
|
|
972
|
-
orderId: zod.string().optional(),
|
|
973
|
-
orderName: zod.string().optional(),
|
|
974
|
-
orderProperty: zod.string().optional(),
|
|
975
|
-
origin: zod.union([zod.literal("JERLICIA"), zod.literal("DALE")]),
|
|
976
|
-
originData: zod.unknown().optional(),
|
|
977
|
-
originInstance: zod.string().optional(),
|
|
978
|
-
poolPath: urlLike.optional(),
|
|
979
|
-
preview: booleanLike.optional(),
|
|
980
|
-
priority: numberLike.optional(),
|
|
981
|
-
sfSrc: urlLike.optional(),
|
|
982
|
-
share: zod.string().optional(),
|
|
983
|
-
// eslint-disable-next-line ts/naming-convention
|
|
984
|
-
slotID: zod.string(),
|
|
985
|
-
slotName: zod.string(),
|
|
986
|
-
swfSrc: urlLike.optional(),
|
|
987
|
-
tag: isJsonOrHtmlOptionalString,
|
|
988
|
-
tagUrl: urlLike.optional(),
|
|
989
|
-
timeStamp: dateLike.optional(),
|
|
990
|
-
trackedImpressionCounter: urlLike.optional(),
|
|
991
|
-
tracker: urlLike.optional(),
|
|
992
|
-
trackingUrl: urlLike.optional(),
|
|
993
|
-
url: urlLike.optional(),
|
|
994
|
-
viewableImpressionCounter: urlLike.optional(),
|
|
995
|
-
width: numberLike.optional(),
|
|
996
|
-
widthLarge: cssValueLike.optional()
|
|
997
|
-
});
|
|
998
|
-
const jerliciaSchema = zod.object({
|
|
999
|
-
origin: zod.literal("JERLICIA"),
|
|
1000
|
-
tag: isJsonOrHtmlString
|
|
1001
|
-
}).passthrough();
|
|
1002
|
-
const daleSchema = zod.object({
|
|
1003
|
-
origin: zod.literal("DALE"),
|
|
1004
|
-
body: isJsonOrHtmlString
|
|
1005
|
-
}).passthrough().transform(({ body, ...data }) => ({
|
|
1006
|
-
...data,
|
|
1007
|
-
tag: body
|
|
1008
|
-
}));
|
|
1009
|
-
const adResponseSchema = baseSchema.extend({
|
|
1010
|
-
additionalCreatives: zod.lazy(() => zod.union([adResponseSchema.array(), zod.string()]).optional())
|
|
1011
|
-
});
|
|
1012
|
-
const adSchema = adResponseSchema.transform(({
|
|
1013
|
-
additionalCreatives,
|
|
1014
|
-
...data
|
|
1015
|
-
}) => {
|
|
1016
|
-
const filteredValue = Object.fromEntries(
|
|
1017
|
-
Object.entries(data).filter(([, value]) => Boolean(value) && JSON.stringify(value) !== "{}" && JSON.stringify(value) !== "[]")
|
|
1018
|
-
);
|
|
1019
|
-
return {
|
|
1020
|
-
...filteredValue,
|
|
1021
|
-
additionalCreatives: Array.isArray(additionalCreatives) ? additionalCreatives.map((creative) => adSchema.parse(creative)) : additionalCreatives
|
|
1022
|
-
};
|
|
1023
|
-
});
|
|
1024
|
-
function parseResponse(response) {
|
|
1025
|
-
const schemaMap = {
|
|
1026
|
-
/* eslint-disable ts/naming-convention */
|
|
1027
|
-
JERLICIA: jerliciaSchema,
|
|
1028
|
-
DALE: daleSchema
|
|
1029
|
-
/* eslint-enable ts/naming-convention */
|
|
1030
|
-
};
|
|
1031
|
-
const preParsed = adResponseSchema.array().parse(response);
|
|
1032
|
-
return preParsed.map((item) => {
|
|
1033
|
-
const schema = schemaMap[item.origin];
|
|
1034
|
-
if (!schema)
|
|
1035
|
-
return adSchema.parse(item);
|
|
1036
|
-
return schema.parse(item);
|
|
1037
|
-
});
|
|
1038
|
-
}
|
|
1039
|
-
async function requestPreviews(account) {
|
|
1040
|
-
const previewObjects = getPreviewObjects();
|
|
1041
|
-
const list = (await Promise.allSettled(previewObjects.filter((previewObject) => "adhesePreviewCreativeId" in previewObject).map(async (previewObject) => {
|
|
1042
|
-
const endpoint = new URL(`https://${account}-preview.adhese.org/creatives/preview/json/tag.do`);
|
|
1043
|
-
endpoint.searchParams.set(
|
|
1044
|
-
"id",
|
|
1045
|
-
previewObject.adhesePreviewCreativeId
|
|
1046
|
-
);
|
|
1047
|
-
const response = await fetch(endpoint.href, {
|
|
1048
|
-
method: "GET",
|
|
1049
|
-
headers: {
|
|
1050
|
-
accept: "application/json"
|
|
1051
|
-
}
|
|
1052
|
-
});
|
|
1053
|
-
if (!response.ok)
|
|
1054
|
-
return Promise.reject(new Error(`Failed to request preview ad with ID: ${previewObject.adhesePreviewCreativeId}`));
|
|
1055
|
-
return await response.json();
|
|
1056
|
-
}))).filter((response) => {
|
|
1057
|
-
if (response.status === "rejected") {
|
|
1058
|
-
logger.error(response.reason);
|
|
1059
|
-
return false;
|
|
1060
|
-
}
|
|
1061
|
-
return response.status === "fulfilled";
|
|
1062
|
-
}).map((response) => response.value.map((item) => ({
|
|
1063
|
-
...item,
|
|
1064
|
-
preview: true
|
|
1065
|
-
})));
|
|
1066
|
-
return adSchema.array().parse(list.flat());
|
|
1067
|
-
}
|
|
1068
|
-
function getPreviewObjects() {
|
|
1069
|
-
const currentUrl = new URL(window.location.href);
|
|
1070
|
-
const previewObjects = [];
|
|
1071
|
-
let currentObject = {};
|
|
1072
|
-
for (const [key, value] of currentUrl.searchParams.entries()) {
|
|
1073
|
-
if (key === "adhesePreviewCreativeId" && Object.keys(currentObject).length > 0) {
|
|
1074
|
-
previewObjects.push(currentObject);
|
|
1075
|
-
currentObject = {};
|
|
1076
|
-
}
|
|
1077
|
-
currentObject[key] = value;
|
|
1078
|
-
}
|
|
1079
|
-
if (Object.keys(currentObject).length > 0)
|
|
1080
|
-
previewObjects.push(currentObject);
|
|
1081
|
-
return previewObjects;
|
|
1082
|
-
}
|
|
1083
|
-
function requestWithPost({
|
|
1084
|
-
context: { options: { host }, parameters },
|
|
1085
|
-
...options
|
|
1086
|
-
}) {
|
|
1087
|
-
const payload = {
|
|
1088
|
-
...options,
|
|
1089
|
-
slots: options.slots.map((slot) => ({
|
|
1090
|
-
slotname: runtimeCore.toValue(slot.name),
|
|
1091
|
-
parameters: parseParameters(slot.parameters)
|
|
1092
|
-
})),
|
|
1093
|
-
parameters: parameters && parseParameters(parameters)
|
|
1094
|
-
};
|
|
1095
|
-
return fetch(`${new URL(host).href}json`, {
|
|
1096
|
-
method: "POST",
|
|
1097
|
-
body: JSON.stringify(payload),
|
|
1098
|
-
headers: {
|
|
1099
|
-
// eslint-disable-next-line ts/naming-convention
|
|
1100
|
-
"Content-Type": "application/json"
|
|
1101
|
-
}
|
|
1102
|
-
});
|
|
1103
|
-
}
|
|
1104
|
-
async function requestWithGet({ context, slots }) {
|
|
1105
|
-
return fetch(new URL(`${context.options.host}/json/sl${slots.map((slot) => runtimeCore.toValue(slot.name)).join("/sl")}`), {
|
|
1106
|
-
method: "GET",
|
|
1107
|
-
headers: {
|
|
1108
|
-
// eslint-disable-next-line ts/naming-convention
|
|
1109
|
-
"Content-Type": "application/json"
|
|
1110
|
-
}
|
|
1111
|
-
});
|
|
1112
|
-
}
|
|
1113
|
-
function parseParameters(parameters) {
|
|
1114
|
-
return Object.fromEntries(Array.from(parameters.entries()).filter(([key]) => {
|
|
1115
|
-
if (key.length === 2)
|
|
1116
|
-
return true;
|
|
1117
|
-
logger.warn(`Invalid parameter key: ${key}. Key should be exactly 2 characters long. Key will be ignored.`);
|
|
1118
|
-
return false;
|
|
1119
|
-
}));
|
|
1120
|
-
}
|
|
1121
|
-
async function requestAds(options) {
|
|
1122
|
-
var _a, _b, _c, _d, _e;
|
|
1123
|
-
const { context } = options;
|
|
1124
|
-
try {
|
|
1125
|
-
(_a = context.events) == null ? void 0 : _a.requestAd.dispatch({
|
|
1126
|
-
...options,
|
|
1127
|
-
context
|
|
1128
|
-
});
|
|
1129
|
-
const [response, previews] = await Promise.all([((_b = context.options.requestType) == null ? void 0 : _b.toUpperCase()) === "POST" ? requestWithPost(options) : requestWithGet(options), requestPreviews(context.options.account)]);
|
|
1130
|
-
logger.debug("Received response", response);
|
|
1131
|
-
if (!response.ok)
|
|
1132
|
-
throw new Error(`Failed to request ad: ${response.status} ${response.statusText}`);
|
|
1133
|
-
const result = parseResponse(await response.json());
|
|
1134
|
-
logger.debug("Parsed ad", result);
|
|
1135
|
-
if (previews.length > 0)
|
|
1136
|
-
logger.info(`Found ${previews.length} ${previews.length === 1 ? "preview" : "previews"}. Replacing ads in response with preview items`, previews);
|
|
1137
|
-
const matchedPreviews = previews.map(({ slotName, ...preview }) => {
|
|
1138
|
-
const partnerAd = result.find((ad) => ad.libId === preview.libId);
|
|
1139
|
-
return {
|
|
1140
|
-
slotName: `${(partnerAd == null ? void 0 : partnerAd.slotName) ?? slotName}`,
|
|
1141
|
-
...preview
|
|
1142
|
-
};
|
|
1143
|
-
});
|
|
1144
|
-
if (matchedPreviews.length > 0)
|
|
1145
|
-
(_c = context.events) == null ? void 0 : _c.previewReceived.dispatch(matchedPreviews);
|
|
1146
|
-
const mergedResult = [
|
|
1147
|
-
...result.filter((ad) => !previews.some((preview) => preview.libId === ad.libId)),
|
|
1148
|
-
...matchedPreviews
|
|
1149
|
-
];
|
|
1150
|
-
if (mergedResult.length === 0)
|
|
1151
|
-
throw new Error("No ads found");
|
|
1152
|
-
(_d = context.events) == null ? void 0 : _d.responseReceived.dispatch(mergedResult);
|
|
1153
|
-
return mergedResult;
|
|
1154
|
-
} catch (error) {
|
|
1155
|
-
logger.error(String(error));
|
|
1156
|
-
(_e = context.events) == null ? void 0 : _e.requestError.dispatch(error);
|
|
1157
|
-
throw error;
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
async function requestAd({
|
|
1161
|
-
slot,
|
|
1162
|
-
...options
|
|
1163
|
-
}) {
|
|
1164
|
-
const [ad] = await requestAds({
|
|
1165
|
-
slots: [slot],
|
|
1166
|
-
...options
|
|
1167
|
-
});
|
|
1168
|
-
return ad;
|
|
1169
|
-
}
|
|
1170
|
-
exports.createAdhese = createAdhese;
|
|
1171
|
-
//# sourceMappingURL=index.js.map
|