@adhese/sdk 0.6.4 → 0.8.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/README.md +71 -41
- package/dist/index.cjs +705 -657
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +87 -39
- package/dist/index.js +705 -657
- package/dist/index.js.map +1 -1
- package/package.json +12 -7
package/dist/index.cjs
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const sdkDevtools = require("@adhese/sdk-devtools");
|
|
4
3
|
const runtimeCore = require("@vue/runtime-core");
|
|
5
|
-
const
|
|
6
|
-
const debounce = require("lodash/debounce");
|
|
7
|
-
const random = require("lodash/random");
|
|
8
|
-
const isEqual = require("lodash/isEqual");
|
|
9
|
-
const round = require("lodash/round");
|
|
4
|
+
const remeda = require("remeda");
|
|
10
5
|
const zod = require("zod");
|
|
11
6
|
async function waitForDomLoad() {
|
|
12
7
|
return new Promise((resolve) => {
|
|
@@ -67,6 +62,15 @@ function createEvent() {
|
|
|
67
62
|
removeListener
|
|
68
63
|
};
|
|
69
64
|
}
|
|
65
|
+
const savedIds = /* @__PURE__ */ new Set();
|
|
66
|
+
function uniqueId() {
|
|
67
|
+
let id;
|
|
68
|
+
do
|
|
69
|
+
id = Math.random().toString(36).slice(2);
|
|
70
|
+
while (savedIds.has(id));
|
|
71
|
+
savedIds.add(id);
|
|
72
|
+
return id;
|
|
73
|
+
}
|
|
70
74
|
function createSafeFrame({
|
|
71
75
|
renderFile,
|
|
72
76
|
context
|
|
@@ -148,109 +152,16 @@ function renderInline(ad, element) {
|
|
|
148
152
|
function generateName(location, format, slot) {
|
|
149
153
|
return `${location}${slot ? `${slot}` : ""}-${format}`;
|
|
150
154
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
);
|
|
162
|
-
return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === name));
|
|
163
|
-
}).map((element) => createSlot({
|
|
164
|
-
format: element.dataset.format,
|
|
165
|
-
containingElement: element,
|
|
166
|
-
slot: element.dataset.slot,
|
|
167
|
-
context
|
|
168
|
-
})).filter((slot) => {
|
|
169
|
-
var _a;
|
|
170
|
-
return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === slot.name.value));
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
function createSlotManager({
|
|
174
|
-
initialSlots = [],
|
|
175
|
-
context
|
|
176
|
-
}) {
|
|
177
|
-
const scope = runtimeCore.effectScope();
|
|
178
|
-
return scope.run(() => {
|
|
179
|
-
const slots = runtimeCore.shallowReactive(/* @__PURE__ */ new Map());
|
|
180
|
-
runtimeCore.watchEffect(() => {
|
|
181
|
-
var _a;
|
|
182
|
-
(_a = context.events) == null ? void 0 : _a.changeSlots.dispatch(Array.from(slots.values()));
|
|
183
|
-
});
|
|
184
|
-
function getAll() {
|
|
185
|
-
return Array.from(slots).map(([, slot]) => slot);
|
|
186
|
-
}
|
|
187
|
-
function add(options) {
|
|
188
|
-
var _a;
|
|
189
|
-
const slot = createSlot({
|
|
190
|
-
...options,
|
|
191
|
-
onDispose,
|
|
192
|
-
context
|
|
193
|
-
});
|
|
194
|
-
function onDispose() {
|
|
195
|
-
var _a2;
|
|
196
|
-
slots.delete(slot.name.value);
|
|
197
|
-
logger.debug("Slot removed", {
|
|
198
|
-
slot,
|
|
199
|
-
slots: Array.from(slots)
|
|
200
|
-
});
|
|
201
|
-
(_a2 = context.events) == null ? void 0 : _a2.removeSlot.dispatch(slot);
|
|
202
|
-
}
|
|
203
|
-
slots.set(slot.name.value, slot);
|
|
204
|
-
runtimeCore.watch(slot.name, (newName, previousName) => {
|
|
205
|
-
slots.set(newName, slot);
|
|
206
|
-
slots.delete(previousName);
|
|
207
|
-
});
|
|
208
|
-
logger.debug("Slot added", {
|
|
209
|
-
slot,
|
|
210
|
-
slots: Array.from(slots.values())
|
|
211
|
-
});
|
|
212
|
-
(_a = context.events) == null ? void 0 : _a.addSlot.dispatch(slot);
|
|
213
|
-
return slot;
|
|
214
|
-
}
|
|
215
|
-
async function findDomSlots$1() {
|
|
216
|
-
const domSlots = await findDomSlots(
|
|
217
|
-
context
|
|
218
|
-
);
|
|
219
|
-
for (const slot of domSlots)
|
|
220
|
-
slots.set(slot.name.value, slot);
|
|
221
|
-
return domSlots;
|
|
222
|
-
}
|
|
223
|
-
function get(name) {
|
|
224
|
-
return slots.get(name);
|
|
225
|
-
}
|
|
226
|
-
function dispose() {
|
|
227
|
-
for (const slot of slots.values())
|
|
228
|
-
slot.dispose();
|
|
229
|
-
slots.clear();
|
|
230
|
-
scope.stop();
|
|
231
|
-
}
|
|
232
|
-
for (const options of initialSlots) {
|
|
233
|
-
add({
|
|
234
|
-
...options,
|
|
235
|
-
lazyLoading: false
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
return {
|
|
239
|
-
getAll,
|
|
240
|
-
add,
|
|
241
|
-
findDomSlots: findDomSlots$1,
|
|
242
|
-
get,
|
|
243
|
-
dispose
|
|
244
|
-
};
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
function onTcfConsentChange(callback) {
|
|
248
|
-
var _a;
|
|
249
|
-
(_a = window.__tcfapi) == null ? void 0 : _a.call(window, "addEventListener", 2, callback);
|
|
250
|
-
return () => {
|
|
251
|
-
var _a2;
|
|
252
|
-
return (_a2 = window.__tcfapi) == null ? void 0 : _a2.call(window, "removeEventListener", 2, callback);
|
|
253
|
-
};
|
|
155
|
+
function addTrackingPixel(url) {
|
|
156
|
+
const img = document.createElement("img");
|
|
157
|
+
img.src = url.toString();
|
|
158
|
+
img.style.height = "1px";
|
|
159
|
+
img.style.width = "1px";
|
|
160
|
+
img.style.margin = "-1px";
|
|
161
|
+
img.style.border = "0";
|
|
162
|
+
img.style.position = "absolute";
|
|
163
|
+
img.style.top = "0";
|
|
164
|
+
return document.body.appendChild(img);
|
|
254
165
|
}
|
|
255
166
|
function createQueryDetector({
|
|
256
167
|
onChange,
|
|
@@ -270,17 +181,19 @@ function createQueryDetector({
|
|
|
270
181
|
}
|
|
271
182
|
return "unknown";
|
|
272
183
|
}
|
|
273
|
-
const handleOnChange = debounce(() => {
|
|
184
|
+
const handleOnChange = remeda.debounce(() => {
|
|
274
185
|
void (onChange == null ? void 0 : onChange(getQuery()));
|
|
275
186
|
logger.debug(`Change device ${getQuery()}`);
|
|
276
|
-
},
|
|
187
|
+
}, {
|
|
188
|
+
waitMs: 50
|
|
189
|
+
});
|
|
277
190
|
if (onChange) {
|
|
278
191
|
for (const query of mediaMap.values())
|
|
279
|
-
query.addEventListener("change", handleOnChange);
|
|
192
|
+
query.addEventListener("change", handleOnChange.call);
|
|
280
193
|
}
|
|
281
194
|
function dispose() {
|
|
282
195
|
for (const query of mediaMap.values())
|
|
283
|
-
query.removeEventListener("change", handleOnChange);
|
|
196
|
+
query.removeEventListener("change", handleOnChange.call);
|
|
284
197
|
}
|
|
285
198
|
return {
|
|
286
199
|
queries: mediaMap,
|
|
@@ -361,47 +274,33 @@ function createLogger({
|
|
|
361
274
|
const logger = createLogger({
|
|
362
275
|
scope: "Adhese SDK"
|
|
363
276
|
});
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
parameters.set("re", btoa(document.referrer));
|
|
368
|
-
if (options.logUrl)
|
|
369
|
-
parameters.set("ur", btoa(window.location.href));
|
|
370
|
-
for (const [key, value] of Object.entries({
|
|
371
|
-
...options.parameters ?? {},
|
|
372
|
-
tl: options.consent ? "all" : "none",
|
|
373
|
-
dt: queryDetector.getQuery(),
|
|
374
|
-
br: queryDetector.getQuery(),
|
|
375
|
-
rn: random(1e4).toString()
|
|
376
|
-
}))
|
|
377
|
-
parameters.set(key, value);
|
|
378
|
-
return parameters;
|
|
277
|
+
const hookMap = /* @__PURE__ */ new Map();
|
|
278
|
+
function clearAllHooks() {
|
|
279
|
+
hookMap.clear();
|
|
379
280
|
}
|
|
380
|
-
function
|
|
381
|
-
if (mergedOptions.debug || window.location.search.includes("adhese_debug=true")) {
|
|
382
|
-
logger.setMinLogLevelThreshold("debug");
|
|
383
|
-
logger.debug("Debug logging enabled");
|
|
384
|
-
}
|
|
385
|
-
logger.debug("Created Adhese SDK instance", {
|
|
386
|
-
mergedOptions
|
|
387
|
-
});
|
|
388
|
-
}
|
|
389
|
-
function isPreviewMode() {
|
|
390
|
-
return window.location.search.includes("adhesePreviewCreativeId");
|
|
391
|
-
}
|
|
392
|
-
function createHook({
|
|
281
|
+
function createHook(name, {
|
|
393
282
|
onRun,
|
|
394
283
|
onAdd
|
|
395
|
-
}) {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
284
|
+
} = {}) {
|
|
285
|
+
hookMap.set(name, /* @__PURE__ */ new Set());
|
|
286
|
+
const run = async (arg) => {
|
|
287
|
+
let latestResult = arg;
|
|
288
|
+
for (const callback of hookMap.get(name) ?? [])
|
|
289
|
+
latestResult = await callback(latestResult) ?? latestResult;
|
|
290
|
+
onRun == null ? void 0 : onRun(hookMap.get(name));
|
|
291
|
+
return latestResult;
|
|
292
|
+
};
|
|
402
293
|
function add(callback) {
|
|
403
|
-
|
|
404
|
-
|
|
294
|
+
const hookSet = hookMap.get(name);
|
|
295
|
+
if (hookSet)
|
|
296
|
+
hookSet.add(callback);
|
|
297
|
+
else
|
|
298
|
+
hookMap.set(name, /* @__PURE__ */ new Set([callback]));
|
|
299
|
+
onAdd == null ? void 0 : onAdd(hookSet);
|
|
300
|
+
return () => {
|
|
301
|
+
var _a;
|
|
302
|
+
(_a = hookMap.get(name)) == null ? void 0 : _a.delete(callback);
|
|
303
|
+
};
|
|
405
304
|
}
|
|
406
305
|
return [run, add];
|
|
407
306
|
}
|
|
@@ -411,229 +310,313 @@ let isInit = false;
|
|
|
411
310
|
const waitOnInit = new Promise((resolve) => {
|
|
412
311
|
resolveOnInitPromise = resolve;
|
|
413
312
|
});
|
|
414
|
-
const [runOnInit, onInit] = createHook({
|
|
313
|
+
const [runOnInit, onInit] = createHook("onInit", {
|
|
415
314
|
onRun(callbacks) {
|
|
416
315
|
isInit = true;
|
|
417
316
|
resolveOnInitPromise();
|
|
418
317
|
logger.debug("Initialization completed");
|
|
419
|
-
callbacks.clear();
|
|
318
|
+
callbacks == null ? void 0 : callbacks.clear();
|
|
420
319
|
},
|
|
421
320
|
onAdd() {
|
|
422
321
|
if (isInit)
|
|
423
|
-
runOnInit();
|
|
322
|
+
runOnInit().catch(logger.error);
|
|
424
323
|
}
|
|
425
324
|
});
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
325
|
+
const [runOnRequest, onRequest] = createHook("onRequest");
|
|
326
|
+
const [runOnResponse, onResponse] = createHook("onResponse");
|
|
327
|
+
const numberLike = zod.union([zod.coerce.string().regex(/^\d+$/), zod.literal("")]).transform((value) => value === "" ? void 0 : Number(value));
|
|
328
|
+
const booleanLike = zod.union([zod.coerce.boolean(), zod.literal("")]);
|
|
329
|
+
const urlLike = zod.union([zod.coerce.string(), zod.literal("")]).transform((value) => {
|
|
330
|
+
try {
|
|
331
|
+
return new URL(value);
|
|
332
|
+
} catch {
|
|
333
|
+
return void 0;
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
const dateLike = zod.union([zod.coerce.string(), zod.literal("")]).transform((value) => {
|
|
337
|
+
if (value === "")
|
|
338
|
+
return void 0;
|
|
339
|
+
const date = new Date(numberLike.safeParse(value).success ? Number(value) : value);
|
|
340
|
+
if (Number.isNaN(date.getTime()))
|
|
341
|
+
return void 0;
|
|
342
|
+
return date;
|
|
343
|
+
});
|
|
344
|
+
const cssValueLike = zod.union([zod.coerce.string(), zod.literal(""), zod.number()]).transform((value) => {
|
|
345
|
+
if (value === "" || value === 0 || value === "0")
|
|
346
|
+
return void 0;
|
|
347
|
+
if (numberLike.parse(value))
|
|
348
|
+
return `${numberLike.parse(value)}px`;
|
|
349
|
+
return String(value);
|
|
350
|
+
});
|
|
351
|
+
const isJson = zod.string().transform((value, { addIssue }) => {
|
|
352
|
+
try {
|
|
353
|
+
return JSON.parse(value.replaceAll("'", '"'));
|
|
354
|
+
} catch (error) {
|
|
355
|
+
addIssue({
|
|
356
|
+
code: zod.ZodIssueCode.custom,
|
|
357
|
+
message: `Invalid JSON: ${error.message}`
|
|
454
358
|
});
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
queries: mergedOptions.queries
|
|
359
|
+
return zod.NEVER;
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
const isHtmlString = zod.string().transform((value, { addIssue }) => {
|
|
363
|
+
var _a;
|
|
364
|
+
const htmlParser = new DOMParser();
|
|
365
|
+
try {
|
|
366
|
+
const html = htmlParser.parseFromString(value, "text/html");
|
|
367
|
+
if (((_a = html.body) == null ? void 0 : _a.children.length) === 0)
|
|
368
|
+
throw new Error("Invalid HTML");
|
|
369
|
+
return value;
|
|
370
|
+
} catch (error) {
|
|
371
|
+
addIssue({
|
|
372
|
+
code: zod.ZodIssueCode.custom,
|
|
373
|
+
message: error.message
|
|
471
374
|
});
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
375
|
+
return zod.NEVER;
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
const isJsonOrHtmlString = zod.union([isJson, isHtmlString]);
|
|
379
|
+
const isJsonOrHtmlOptionalString = zod.union([zod.coerce.string(), isJsonOrHtmlString]).transform((value) => {
|
|
380
|
+
if (value === "")
|
|
381
|
+
return void 0;
|
|
382
|
+
return value;
|
|
383
|
+
}).optional();
|
|
384
|
+
const baseSchema = zod.object({
|
|
385
|
+
adDuration: numberLike.optional(),
|
|
386
|
+
adFormat: zod.string().optional(),
|
|
387
|
+
adType: zod.string(),
|
|
388
|
+
additionalCreativeTracker: urlLike.optional(),
|
|
389
|
+
additionalViewableTracker: zod.string().optional(),
|
|
390
|
+
adspaceEnd: dateLike.optional(),
|
|
391
|
+
adspaceId: zod.string().optional(),
|
|
392
|
+
adspaceKey: zod.string().optional(),
|
|
393
|
+
adspaceStart: dateLike.optional(),
|
|
394
|
+
advertiserId: zod.string().optional(),
|
|
395
|
+
altText: zod.string().optional(),
|
|
396
|
+
auctionable: booleanLike.optional(),
|
|
397
|
+
body: isJsonOrHtmlOptionalString,
|
|
398
|
+
clickTag: urlLike.optional(),
|
|
399
|
+
comment: zod.string().optional(),
|
|
400
|
+
creativeName: zod.string().optional(),
|
|
401
|
+
deliveryGroupId: zod.string().optional(),
|
|
402
|
+
deliveryMultiples: zod.string().optional(),
|
|
403
|
+
ext: zod.string().optional(),
|
|
404
|
+
extension: zod.object({
|
|
405
|
+
mediaType: zod.string(),
|
|
406
|
+
prebid: zod.unknown().optional()
|
|
407
|
+
}).optional(),
|
|
408
|
+
height: numberLike.optional(),
|
|
409
|
+
id: zod.string(),
|
|
410
|
+
impressionCounter: urlLike.optional(),
|
|
411
|
+
libId: zod.string().optional(),
|
|
412
|
+
orderId: zod.string().optional(),
|
|
413
|
+
orderName: zod.string().optional(),
|
|
414
|
+
orderProperty: zod.string().optional(),
|
|
415
|
+
origin: zod.union([zod.literal("JERLICIA"), zod.literal("DALE")]),
|
|
416
|
+
originData: zod.unknown().optional(),
|
|
417
|
+
originInstance: zod.string().optional(),
|
|
418
|
+
poolPath: urlLike.optional(),
|
|
419
|
+
preview: booleanLike.optional(),
|
|
420
|
+
priority: numberLike.optional(),
|
|
421
|
+
sfSrc: urlLike.optional(),
|
|
422
|
+
share: zod.string().optional(),
|
|
423
|
+
// eslint-disable-next-line ts/naming-convention
|
|
424
|
+
slotID: zod.string(),
|
|
425
|
+
slotName: zod.string(),
|
|
426
|
+
swfSrc: urlLike.optional(),
|
|
427
|
+
tag: isJsonOrHtmlOptionalString,
|
|
428
|
+
tagUrl: urlLike.optional(),
|
|
429
|
+
timeStamp: dateLike.optional(),
|
|
430
|
+
trackedImpressionCounter: urlLike.optional(),
|
|
431
|
+
tracker: urlLike.optional(),
|
|
432
|
+
trackingUrl: urlLike.optional(),
|
|
433
|
+
url: urlLike.optional(),
|
|
434
|
+
viewableImpressionCounter: urlLike.optional(),
|
|
435
|
+
width: numberLike.optional(),
|
|
436
|
+
widthLarge: cssValueLike.optional()
|
|
437
|
+
});
|
|
438
|
+
const jerliciaSchema = zod.object({
|
|
439
|
+
origin: zod.literal("JERLICIA"),
|
|
440
|
+
tag: isJsonOrHtmlString
|
|
441
|
+
}).passthrough();
|
|
442
|
+
const daleSchema = zod.object({
|
|
443
|
+
origin: zod.literal("DALE"),
|
|
444
|
+
body: isJsonOrHtmlString
|
|
445
|
+
}).passthrough().transform(({ body, ...data }) => ({
|
|
446
|
+
...data,
|
|
447
|
+
tag: body
|
|
448
|
+
}));
|
|
449
|
+
const adResponseSchema = baseSchema.extend({
|
|
450
|
+
additionalCreatives: zod.lazy(() => zod.union([adResponseSchema.array(), zod.string()]).optional())
|
|
451
|
+
});
|
|
452
|
+
const adSchema = adResponseSchema.transform(({
|
|
453
|
+
additionalCreatives,
|
|
454
|
+
...data
|
|
455
|
+
}) => {
|
|
456
|
+
const filteredValue = Object.fromEntries(
|
|
457
|
+
Object.entries(data).filter(([, value]) => Boolean(value) && JSON.stringify(value) !== "{}" && JSON.stringify(value) !== "[]")
|
|
458
|
+
);
|
|
459
|
+
return {
|
|
460
|
+
...filteredValue,
|
|
461
|
+
additionalCreatives: Array.isArray(additionalCreatives) ? additionalCreatives.map((creative) => adSchema.parse(creative)) : additionalCreatives
|
|
462
|
+
};
|
|
463
|
+
});
|
|
464
|
+
function parseResponse(response) {
|
|
465
|
+
const schemaMap = {
|
|
466
|
+
/* eslint-disable ts/naming-convention */
|
|
467
|
+
JERLICIA: jerliciaSchema,
|
|
468
|
+
DALE: daleSchema
|
|
469
|
+
/* eslint-enable ts/naming-convention */
|
|
470
|
+
};
|
|
471
|
+
const preParsed = adResponseSchema.array().parse(response);
|
|
472
|
+
return preParsed.map((item) => {
|
|
473
|
+
const schema = schemaMap[item.origin];
|
|
474
|
+
if (!schema)
|
|
475
|
+
return adSchema.parse(item);
|
|
476
|
+
return schema.parse(item);
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
async function requestPreviews(account) {
|
|
480
|
+
const previewObjects = getPreviewObjects();
|
|
481
|
+
const list = (await Promise.allSettled(previewObjects.filter((previewObject) => "adhesePreviewCreativeId" in previewObject).map(async (previewObject) => {
|
|
482
|
+
const endpoint = new URL(`https://${account}-preview.adhese.org/creatives/preview/json/tag.do`);
|
|
483
|
+
endpoint.searchParams.set(
|
|
484
|
+
"id",
|
|
485
|
+
previewObject.adhesePreviewCreativeId
|
|
486
|
+
);
|
|
487
|
+
const response = await fetch(endpoint.href, {
|
|
488
|
+
method: "GET",
|
|
489
|
+
headers: {
|
|
490
|
+
accept: "application/json"
|
|
521
491
|
}
|
|
522
|
-
|
|
492
|
+
});
|
|
493
|
+
if (!response.ok)
|
|
494
|
+
return Promise.reject(new Error(`Failed to request preview ad with ID: ${previewObject.adhesePreviewCreativeId}`));
|
|
495
|
+
return await response.json();
|
|
496
|
+
}))).filter((response) => {
|
|
497
|
+
if (response.status === "rejected") {
|
|
498
|
+
logger.error(response.reason);
|
|
499
|
+
return false;
|
|
523
500
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
501
|
+
return response.status === "fulfilled";
|
|
502
|
+
}).map((response) => response.value.map((item) => ({
|
|
503
|
+
...item,
|
|
504
|
+
preview: true
|
|
505
|
+
})));
|
|
506
|
+
return adSchema.array().parse(list.flat());
|
|
507
|
+
}
|
|
508
|
+
function getPreviewObjects() {
|
|
509
|
+
const currentUrl = new URL(window.location.href);
|
|
510
|
+
const previewObjects = [];
|
|
511
|
+
let currentObject = {};
|
|
512
|
+
for (const [key, value] of currentUrl.searchParams.entries()) {
|
|
513
|
+
if (key === "adhesePreviewCreativeId" && Object.keys(currentObject).length > 0) {
|
|
514
|
+
previewObjects.push(currentObject);
|
|
515
|
+
currentObject = {};
|
|
538
516
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
517
|
+
currentObject[key] = value;
|
|
518
|
+
}
|
|
519
|
+
if (Object.keys(currentObject).length > 0)
|
|
520
|
+
previewObjects.push(currentObject);
|
|
521
|
+
return previewObjects;
|
|
522
|
+
}
|
|
523
|
+
function requestWithPost({
|
|
524
|
+
context: { options: { host }, parameters },
|
|
525
|
+
...options
|
|
526
|
+
}) {
|
|
527
|
+
const payload = {
|
|
528
|
+
...options,
|
|
529
|
+
slots: options.slots.map((slot) => ({
|
|
530
|
+
slotname: runtimeCore.toValue(slot.name),
|
|
531
|
+
parameters: parseParameters(slot.parameters)
|
|
532
|
+
})),
|
|
533
|
+
parameters: parameters && parseParameters(parameters)
|
|
534
|
+
};
|
|
535
|
+
return fetch(`${new URL(host).href}json`, {
|
|
536
|
+
method: "POST",
|
|
537
|
+
body: JSON.stringify(payload),
|
|
538
|
+
headers: {
|
|
539
|
+
// eslint-disable-next-line ts/naming-convention
|
|
540
|
+
"Content-Type": "application/json"
|
|
556
541
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
for (const ad of ads) {
|
|
566
|
-
const slot = slotManager.get(ad.slotName);
|
|
567
|
-
if (slot)
|
|
568
|
-
slot.ad.value = ad;
|
|
569
|
-
}
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
async function requestWithGet({ context, slots }) {
|
|
545
|
+
return fetch(new URL(`${context.options.host}/json/sl${slots.map((slot) => runtimeCore.toValue(slot.name)).join("/sl")}`), {
|
|
546
|
+
method: "GET",
|
|
547
|
+
headers: {
|
|
548
|
+
// eslint-disable-next-line ts/naming-convention
|
|
549
|
+
"Content-Type": "application/json"
|
|
570
550
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
function parseParameters(parameters) {
|
|
554
|
+
return Object.fromEntries(Array.from(parameters.entries()).filter(([key]) => {
|
|
555
|
+
if (key.length === 2)
|
|
556
|
+
return true;
|
|
557
|
+
logger.warn(`Invalid parameter key: ${key}. Key should be exactly 2 characters long. Key will be ignored.`);
|
|
558
|
+
return false;
|
|
559
|
+
}).map(([key, value]) => {
|
|
560
|
+
if (typeof value === "string")
|
|
561
|
+
return [key, filterSpecialChars(value)];
|
|
562
|
+
return [key, value.map(filterSpecialChars)];
|
|
563
|
+
}));
|
|
564
|
+
}
|
|
565
|
+
function filterSpecialChars(value) {
|
|
566
|
+
const specialRegex = /[^\p{L}\p{N}_]/gu;
|
|
567
|
+
return value.replaceAll(specialRegex, "_");
|
|
568
|
+
}
|
|
569
|
+
async function requestAds(requestOptions) {
|
|
570
|
+
var _a, _b, _c, _d, _e;
|
|
571
|
+
const options = await runOnRequest(requestOptions);
|
|
572
|
+
const { context } = options;
|
|
573
|
+
try {
|
|
574
|
+
(_a = context.events) == null ? void 0 : _a.requestAd.dispatch({
|
|
575
|
+
...options,
|
|
576
|
+
context
|
|
581
577
|
});
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
(
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
var _a;
|
|
597
|
-
if ((slotManager.getAll().length ?? 0) > 0)
|
|
598
|
-
await fetchAndRenderAllSlots().catch(logger.error);
|
|
599
|
-
if (mergedOptions.findDomSlotsOnLoad)
|
|
600
|
-
await findDomSlots2();
|
|
601
|
-
if (mergedOptions.debug || window.location.search.includes("adhese_debug=true") || isPreviewMode()) {
|
|
602
|
-
unmountDevtools = await sdkDevtools.createDevtools(context);
|
|
603
|
-
(_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
|
|
604
|
-
}
|
|
605
|
-
if (!scope.active)
|
|
606
|
-
dispose();
|
|
578
|
+
const [response, previews] = await Promise.all([((_b = context.options.requestType) == null ? void 0 : _b.toUpperCase()) === "POST" ? requestWithPost(options) : requestWithGet(options), requestPreviews(context.options.account)]);
|
|
579
|
+
logger.debug("Received response", response);
|
|
580
|
+
if (!response.ok)
|
|
581
|
+
throw new Error(`Failed to request ad: ${response.status} ${response.statusText}`);
|
|
582
|
+
const result = parseResponse(await response.json());
|
|
583
|
+
logger.debug("Parsed ad", result);
|
|
584
|
+
if (previews.length > 0)
|
|
585
|
+
logger.info(`Found ${previews.length} ${previews.length === 1 ? "preview" : "previews"}. Replacing ads in response with preview items`, previews);
|
|
586
|
+
const matchedPreviews = previews.map(({ slotName, ...preview }) => {
|
|
587
|
+
const partnerAd = result.find((ad) => ad.libId === preview.libId);
|
|
588
|
+
return {
|
|
589
|
+
slotName: `${(partnerAd == null ? void 0 : partnerAd.slotName) ?? slotName}`,
|
|
590
|
+
...preview
|
|
591
|
+
};
|
|
607
592
|
});
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
...
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
};
|
|
624
|
-
});
|
|
593
|
+
if (matchedPreviews.length > 0)
|
|
594
|
+
(_c = context.events) == null ? void 0 : _c.previewReceived.dispatch(matchedPreviews);
|
|
595
|
+
const mergedResult = await runOnResponse([
|
|
596
|
+
...result.filter((ad) => !previews.some((preview) => preview.libId === ad.libId)),
|
|
597
|
+
...matchedPreviews
|
|
598
|
+
]);
|
|
599
|
+
if (mergedResult.length === 0)
|
|
600
|
+
throw new Error("No ads found");
|
|
601
|
+
(_d = context.events) == null ? void 0 : _d.responseReceived.dispatch(mergedResult);
|
|
602
|
+
return mergedResult;
|
|
603
|
+
} catch (error) {
|
|
604
|
+
logger.error(String(error));
|
|
605
|
+
(_e = context.events) == null ? void 0 : _e.requestError.dispatch(error);
|
|
606
|
+
throw error;
|
|
607
|
+
}
|
|
625
608
|
}
|
|
626
|
-
function
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
return document.body.appendChild(img);
|
|
609
|
+
async function requestAd({
|
|
610
|
+
slot,
|
|
611
|
+
...options
|
|
612
|
+
}) {
|
|
613
|
+
const [ad] = await requestAds({
|
|
614
|
+
slots: [slot],
|
|
615
|
+
...options
|
|
616
|
+
});
|
|
617
|
+
return ad;
|
|
636
618
|
}
|
|
619
|
+
const [runOnRender, onRender] = createHook("onRender");
|
|
637
620
|
function useViewabilityObserver({ context, ad, name, element }) {
|
|
638
621
|
let timeoutId = null;
|
|
639
622
|
const {
|
|
@@ -650,7 +633,7 @@ function useViewabilityObserver({ context, ad, name, element }) {
|
|
|
650
633
|
const isTracked = runtimeCore.computed(() => Boolean(trackingPixel.value));
|
|
651
634
|
const viewabilityObserver = new IntersectionObserver(([entry]) => {
|
|
652
635
|
if (context.options.viewabilityTracking && !trackingPixel.value && ad) {
|
|
653
|
-
const ratio = round(entry.intersectionRatio, 1);
|
|
636
|
+
const ratio = remeda.round(entry.intersectionRatio, 1);
|
|
654
637
|
if (ratio >= threshold && !timeoutId) {
|
|
655
638
|
timeoutId = setTimeout(() => {
|
|
656
639
|
var _a, _b, _c;
|
|
@@ -782,7 +765,7 @@ function createSlot(options) {
|
|
|
782
765
|
});
|
|
783
766
|
runtimeCore.watch([ad, isInViewport], async ([newAd, newIsInViewport], [oldAd]) => {
|
|
784
767
|
var _a, _b;
|
|
785
|
-
if (!newAd ||
|
|
768
|
+
if (!newAd || oldAd && remeda.isDeepEqual(newAd, oldAd))
|
|
786
769
|
return;
|
|
787
770
|
if (newIsInViewport || context.options.eagerRendering)
|
|
788
771
|
await render(newAd);
|
|
@@ -814,10 +797,10 @@ function createSlot(options) {
|
|
|
814
797
|
var _a, _b;
|
|
815
798
|
await waitForDomLoad();
|
|
816
799
|
await waitOnInit;
|
|
817
|
-
|
|
818
|
-
if (
|
|
819
|
-
|
|
820
|
-
|
|
800
|
+
let renderAd = adToRender ?? ad.value ?? originalAd.value ?? await requestAd$1();
|
|
801
|
+
if (renderAd)
|
|
802
|
+
renderAd = ((_a = options.onBeforeRender) == null ? void 0 : _a.call(options, renderAd)) ?? renderAd;
|
|
803
|
+
renderAd = await runOnRender(renderAd);
|
|
821
804
|
if (!element.value) {
|
|
822
805
|
const error = `Could not create slot for format ${format.value}. No element found.`;
|
|
823
806
|
logger.error(error, options);
|
|
@@ -825,8 +808,8 @@ function createSlot(options) {
|
|
|
825
808
|
}
|
|
826
809
|
if (context.debug)
|
|
827
810
|
element.value.style.position = "relative";
|
|
828
|
-
if (context.safeFrame &&
|
|
829
|
-
const position = context.safeFrame.addPosition(
|
|
811
|
+
if (context.safeFrame && renderAd && renderMode === "iframe") {
|
|
812
|
+
const position = context.safeFrame.addPosition(renderAd, element.value);
|
|
830
813
|
await context.safeFrame.render(position);
|
|
831
814
|
} else {
|
|
832
815
|
renderFunctions[renderMode](renderAd, element.value);
|
|
@@ -854,322 +837,387 @@ function createSlot(options) {
|
|
|
854
837
|
element.value.style.height = "";
|
|
855
838
|
}
|
|
856
839
|
function dispose() {
|
|
857
|
-
var _a, _b;
|
|
858
|
-
cleanElement();
|
|
859
|
-
(_a = impressionTrackingPixelElement.value) == null ? void 0 : _a.remove();
|
|
860
|
-
ad.value = null;
|
|
861
|
-
disposeRenderIntersectionObserver();
|
|
862
|
-
disposeViewabilityObserver();
|
|
863
|
-
(_b = options.onDispose) == null ? void 0 : _b.call(options);
|
|
864
|
-
queryDetector == null ? void 0 : queryDetector.dispose();
|
|
840
|
+
var _a, _b;
|
|
841
|
+
cleanElement();
|
|
842
|
+
(_a = impressionTrackingPixelElement.value) == null ? void 0 : _a.remove();
|
|
843
|
+
ad.value = null;
|
|
844
|
+
disposeRenderIntersectionObserver();
|
|
845
|
+
disposeViewabilityObserver();
|
|
846
|
+
(_b = options.onDispose) == null ? void 0 : _b.call(options);
|
|
847
|
+
queryDetector == null ? void 0 : queryDetector.dispose();
|
|
848
|
+
scope.stop();
|
|
849
|
+
}
|
|
850
|
+
return {
|
|
851
|
+
location: context.location,
|
|
852
|
+
lazyLoading: options.lazyLoading ?? false,
|
|
853
|
+
slot,
|
|
854
|
+
parameters,
|
|
855
|
+
format,
|
|
856
|
+
name,
|
|
857
|
+
ad,
|
|
858
|
+
isViewabilityTracked,
|
|
859
|
+
isImpressionTracked,
|
|
860
|
+
render,
|
|
861
|
+
getElement,
|
|
862
|
+
dispose
|
|
863
|
+
};
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
function useDomLoaded() {
|
|
867
|
+
const isDomLoaded = runtimeCore.ref(false);
|
|
868
|
+
onInit(async () => {
|
|
869
|
+
await waitForDomLoad();
|
|
870
|
+
isDomLoaded.value = true;
|
|
871
|
+
});
|
|
872
|
+
return isDomLoaded;
|
|
873
|
+
}
|
|
874
|
+
async function findDomSlots(context) {
|
|
875
|
+
await waitForDomLoad();
|
|
876
|
+
return Array.from(document.querySelectorAll(".adunit")).filter((element) => {
|
|
877
|
+
var _a;
|
|
878
|
+
if (!element.dataset.format)
|
|
879
|
+
return false;
|
|
880
|
+
const name = generateName(
|
|
881
|
+
context.location,
|
|
882
|
+
element.dataset.format,
|
|
883
|
+
element.dataset.slot
|
|
884
|
+
);
|
|
885
|
+
return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === name));
|
|
886
|
+
}).map((element) => createSlot({
|
|
887
|
+
format: element.dataset.format,
|
|
888
|
+
containingElement: element,
|
|
889
|
+
slot: element.dataset.slot,
|
|
890
|
+
context
|
|
891
|
+
})).filter((slot) => {
|
|
892
|
+
var _a;
|
|
893
|
+
return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === slot.name.value));
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
function createSlotManager({
|
|
897
|
+
initialSlots = [],
|
|
898
|
+
context
|
|
899
|
+
}) {
|
|
900
|
+
const scope = runtimeCore.effectScope();
|
|
901
|
+
return scope.run(() => {
|
|
902
|
+
const slots = runtimeCore.shallowReactive(/* @__PURE__ */ new Map());
|
|
903
|
+
runtimeCore.watchEffect(() => {
|
|
904
|
+
var _a;
|
|
905
|
+
(_a = context.events) == null ? void 0 : _a.changeSlots.dispatch(Array.from(slots.values()));
|
|
906
|
+
});
|
|
907
|
+
function getAll() {
|
|
908
|
+
return Array.from(slots).map(([, slot]) => slot);
|
|
909
|
+
}
|
|
910
|
+
function add(options) {
|
|
911
|
+
var _a;
|
|
912
|
+
const slot = createSlot({
|
|
913
|
+
...options,
|
|
914
|
+
onDispose: onDispose2,
|
|
915
|
+
context
|
|
916
|
+
});
|
|
917
|
+
function onDispose2() {
|
|
918
|
+
var _a2;
|
|
919
|
+
slots.delete(slot.name.value);
|
|
920
|
+
logger.debug("Slot removed", {
|
|
921
|
+
slot,
|
|
922
|
+
slots: Array.from(slots)
|
|
923
|
+
});
|
|
924
|
+
(_a2 = context.events) == null ? void 0 : _a2.removeSlot.dispatch(slot);
|
|
925
|
+
}
|
|
926
|
+
slots.set(slot.name.value, slot);
|
|
927
|
+
runtimeCore.watch(slot.name, (newName, previousName) => {
|
|
928
|
+
slots.set(newName, slot);
|
|
929
|
+
slots.delete(previousName);
|
|
930
|
+
});
|
|
931
|
+
logger.debug("Slot added", {
|
|
932
|
+
slot,
|
|
933
|
+
slots: Array.from(slots.values())
|
|
934
|
+
});
|
|
935
|
+
(_a = context.events) == null ? void 0 : _a.addSlot.dispatch(slot);
|
|
936
|
+
return slot;
|
|
937
|
+
}
|
|
938
|
+
async function findDomSlots$1() {
|
|
939
|
+
const domSlots = await findDomSlots(
|
|
940
|
+
context
|
|
941
|
+
);
|
|
942
|
+
for (const slot of domSlots)
|
|
943
|
+
slots.set(slot.name.value, slot);
|
|
944
|
+
return domSlots;
|
|
945
|
+
}
|
|
946
|
+
function get(name) {
|
|
947
|
+
return slots.get(name);
|
|
948
|
+
}
|
|
949
|
+
function dispose() {
|
|
950
|
+
for (const slot of slots.values())
|
|
951
|
+
slot.dispose();
|
|
952
|
+
slots.clear();
|
|
865
953
|
scope.stop();
|
|
866
954
|
}
|
|
955
|
+
for (const options of initialSlots) {
|
|
956
|
+
add({
|
|
957
|
+
...options,
|
|
958
|
+
lazyLoading: false
|
|
959
|
+
});
|
|
960
|
+
}
|
|
867
961
|
return {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
format,
|
|
873
|
-
name,
|
|
874
|
-
ad,
|
|
875
|
-
isViewabilityTracked,
|
|
876
|
-
isImpressionTracked,
|
|
877
|
-
render,
|
|
878
|
-
getElement,
|
|
962
|
+
getAll,
|
|
963
|
+
add,
|
|
964
|
+
findDomSlots: findDomSlots$1,
|
|
965
|
+
get,
|
|
879
966
|
dispose
|
|
880
967
|
};
|
|
881
968
|
});
|
|
882
969
|
}
|
|
883
|
-
function
|
|
884
|
-
const isDomLoaded = runtimeCore.ref(false);
|
|
885
|
-
onInit(async () => {
|
|
886
|
-
await waitForDomLoad();
|
|
887
|
-
isDomLoaded.value = true;
|
|
888
|
-
});
|
|
889
|
-
return isDomLoaded;
|
|
890
|
-
}
|
|
891
|
-
const numberLike = zod.union([zod.coerce.string().regex(/^\d+$/), zod.literal("")]).transform((value) => value === "" ? void 0 : Number(value));
|
|
892
|
-
const booleanLike = zod.union([zod.coerce.boolean(), zod.literal("")]);
|
|
893
|
-
const urlLike = zod.union([zod.coerce.string(), zod.literal("")]).transform((value) => {
|
|
894
|
-
try {
|
|
895
|
-
return new URL(value);
|
|
896
|
-
} catch {
|
|
897
|
-
return void 0;
|
|
898
|
-
}
|
|
899
|
-
});
|
|
900
|
-
const dateLike = zod.union([zod.coerce.string(), zod.literal("")]).transform((value) => {
|
|
901
|
-
if (value === "")
|
|
902
|
-
return void 0;
|
|
903
|
-
const date = new Date(numberLike.safeParse(value).success ? Number(value) : value);
|
|
904
|
-
if (Number.isNaN(date.getTime()))
|
|
905
|
-
return void 0;
|
|
906
|
-
return date;
|
|
907
|
-
});
|
|
908
|
-
const cssValueLike = zod.union([zod.coerce.string(), zod.literal(""), zod.number()]).transform((value) => {
|
|
909
|
-
if (value === "" || value === 0 || value === "0")
|
|
910
|
-
return void 0;
|
|
911
|
-
if (numberLike.parse(value))
|
|
912
|
-
return `${numberLike.parse(value)}px`;
|
|
913
|
-
return String(value);
|
|
914
|
-
});
|
|
915
|
-
const isJson = zod.string().transform((value, { addIssue }) => {
|
|
916
|
-
try {
|
|
917
|
-
return JSON.parse(value.replaceAll("'", '"'));
|
|
918
|
-
} catch (error) {
|
|
919
|
-
addIssue({
|
|
920
|
-
code: zod.ZodIssueCode.custom,
|
|
921
|
-
message: `Invalid JSON: ${error.message}`
|
|
922
|
-
});
|
|
923
|
-
return zod.NEVER;
|
|
924
|
-
}
|
|
925
|
-
});
|
|
926
|
-
const isHtmlString = zod.string().transform((value, { addIssue }) => {
|
|
970
|
+
function onTcfConsentChange(callback) {
|
|
927
971
|
var _a;
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
throw new Error("Invalid HTML");
|
|
933
|
-
return value;
|
|
934
|
-
} catch (error) {
|
|
935
|
-
addIssue({
|
|
936
|
-
code: zod.ZodIssueCode.custom,
|
|
937
|
-
message: error.message
|
|
938
|
-
});
|
|
939
|
-
return zod.NEVER;
|
|
940
|
-
}
|
|
941
|
-
});
|
|
942
|
-
const isJsonOrHtmlString = zod.union([isJson, isHtmlString]);
|
|
943
|
-
const isJsonOrHtmlOptionalString = zod.union([zod.coerce.string(), isJsonOrHtmlString]).transform((value) => {
|
|
944
|
-
if (value === "")
|
|
945
|
-
return void 0;
|
|
946
|
-
return value;
|
|
947
|
-
}).optional();
|
|
948
|
-
const baseSchema = zod.object({
|
|
949
|
-
adDuration: numberLike.optional(),
|
|
950
|
-
adFormat: zod.string().optional(),
|
|
951
|
-
adType: zod.string(),
|
|
952
|
-
additionalCreativeTracker: urlLike.optional(),
|
|
953
|
-
additionalViewableTracker: zod.string().optional(),
|
|
954
|
-
adspaceEnd: dateLike.optional(),
|
|
955
|
-
adspaceId: zod.string().optional(),
|
|
956
|
-
adspaceKey: zod.string().optional(),
|
|
957
|
-
adspaceStart: dateLike.optional(),
|
|
958
|
-
advertiserId: zod.string().optional(),
|
|
959
|
-
altText: zod.string().optional(),
|
|
960
|
-
auctionable: booleanLike.optional(),
|
|
961
|
-
body: isJsonOrHtmlOptionalString,
|
|
962
|
-
clickTag: urlLike.optional(),
|
|
963
|
-
comment: zod.string().optional(),
|
|
964
|
-
creativeName: zod.string().optional(),
|
|
965
|
-
deliveryGroupId: zod.string().optional(),
|
|
966
|
-
deliveryMultiples: zod.string().optional(),
|
|
967
|
-
ext: zod.string().optional(),
|
|
968
|
-
extension: zod.object({
|
|
969
|
-
mediaType: zod.string(),
|
|
970
|
-
prebid: zod.unknown().optional()
|
|
971
|
-
}).optional(),
|
|
972
|
-
height: numberLike.optional(),
|
|
973
|
-
id: zod.string(),
|
|
974
|
-
impressionCounter: urlLike.optional(),
|
|
975
|
-
libId: zod.string().optional(),
|
|
976
|
-
orderId: zod.string().optional(),
|
|
977
|
-
orderName: zod.string().optional(),
|
|
978
|
-
orderProperty: zod.string().optional(),
|
|
979
|
-
origin: zod.union([zod.literal("JERLICIA"), zod.literal("DALE")]),
|
|
980
|
-
originData: zod.unknown().optional(),
|
|
981
|
-
originInstance: zod.string().optional(),
|
|
982
|
-
poolPath: urlLike.optional(),
|
|
983
|
-
preview: booleanLike.optional(),
|
|
984
|
-
priority: numberLike.optional(),
|
|
985
|
-
sfSrc: urlLike.optional(),
|
|
986
|
-
share: zod.string().optional(),
|
|
987
|
-
// eslint-disable-next-line ts/naming-convention
|
|
988
|
-
slotID: zod.string(),
|
|
989
|
-
slotName: zod.string(),
|
|
990
|
-
swfSrc: urlLike.optional(),
|
|
991
|
-
tag: isJsonOrHtmlOptionalString,
|
|
992
|
-
tagUrl: urlLike.optional(),
|
|
993
|
-
timeStamp: dateLike.optional(),
|
|
994
|
-
trackedImpressionCounter: urlLike.optional(),
|
|
995
|
-
tracker: urlLike.optional(),
|
|
996
|
-
trackingUrl: urlLike.optional(),
|
|
997
|
-
url: urlLike.optional(),
|
|
998
|
-
viewableImpressionCounter: urlLike.optional(),
|
|
999
|
-
width: numberLike.optional(),
|
|
1000
|
-
widthLarge: cssValueLike.optional()
|
|
1001
|
-
});
|
|
1002
|
-
const jerliciaSchema = zod.object({
|
|
1003
|
-
origin: zod.literal("JERLICIA"),
|
|
1004
|
-
tag: isJsonOrHtmlString
|
|
1005
|
-
}).passthrough();
|
|
1006
|
-
const daleSchema = zod.object({
|
|
1007
|
-
origin: zod.literal("DALE"),
|
|
1008
|
-
body: isJsonOrHtmlString
|
|
1009
|
-
}).passthrough().transform(({ body, ...data }) => ({
|
|
1010
|
-
...data,
|
|
1011
|
-
tag: body
|
|
1012
|
-
}));
|
|
1013
|
-
const adResponseSchema = baseSchema.extend({
|
|
1014
|
-
additionalCreatives: zod.lazy(() => zod.union([adResponseSchema.array(), zod.string()]).optional())
|
|
1015
|
-
});
|
|
1016
|
-
const adSchema = adResponseSchema.transform(({
|
|
1017
|
-
additionalCreatives,
|
|
1018
|
-
...data
|
|
1019
|
-
}) => {
|
|
1020
|
-
const filteredValue = Object.fromEntries(
|
|
1021
|
-
Object.entries(data).filter(([, value]) => Boolean(value) && JSON.stringify(value) !== "{}" && JSON.stringify(value) !== "[]")
|
|
1022
|
-
);
|
|
1023
|
-
return {
|
|
1024
|
-
...filteredValue,
|
|
1025
|
-
additionalCreatives: Array.isArray(additionalCreatives) ? additionalCreatives.map((creative) => adSchema.parse(creative)) : additionalCreatives
|
|
1026
|
-
};
|
|
1027
|
-
});
|
|
1028
|
-
function parseResponse(response) {
|
|
1029
|
-
const schemaMap = {
|
|
1030
|
-
/* eslint-disable ts/naming-convention */
|
|
1031
|
-
JERLICIA: jerliciaSchema,
|
|
1032
|
-
DALE: daleSchema
|
|
1033
|
-
/* eslint-enable ts/naming-convention */
|
|
972
|
+
(_a = window.__tcfapi) == null ? void 0 : _a.call(window, "addEventListener", 2, callback);
|
|
973
|
+
return () => {
|
|
974
|
+
var _a2;
|
|
975
|
+
return (_a2 = window.__tcfapi) == null ? void 0 : _a2.call(window, "removeEventListener", 2, callback);
|
|
1034
976
|
};
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
977
|
+
}
|
|
978
|
+
function createParameters(options, queryDetector) {
|
|
979
|
+
const parameters = /* @__PURE__ */ new Map();
|
|
980
|
+
if (options.logReferrer)
|
|
981
|
+
parameters.set("re", btoa(document.referrer));
|
|
982
|
+
if (options.logUrl)
|
|
983
|
+
parameters.set("ur", btoa(window.location.href));
|
|
984
|
+
for (const [key, value] of Object.entries({
|
|
985
|
+
...options.parameters ?? {},
|
|
986
|
+
tl: options.consent ? "all" : "none",
|
|
987
|
+
dt: queryDetector.getQuery(),
|
|
988
|
+
br: queryDetector.getQuery(),
|
|
989
|
+
rn: Math.round(Math.random() * 1e4).toString()
|
|
990
|
+
}))
|
|
991
|
+
parameters.set(key, value);
|
|
992
|
+
return parameters;
|
|
993
|
+
}
|
|
994
|
+
function setupLogging(mergedOptions) {
|
|
995
|
+
if (mergedOptions.debug || window.location.search.includes("adhese_debug=true")) {
|
|
996
|
+
logger.setMinLogLevelThreshold("debug");
|
|
997
|
+
logger.debug("Debug logging enabled");
|
|
998
|
+
}
|
|
999
|
+
logger.debug("Created Adhese SDK instance", {
|
|
1000
|
+
mergedOptions
|
|
1041
1001
|
});
|
|
1042
1002
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
);
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1003
|
+
function isPreviewMode() {
|
|
1004
|
+
return window.location.search.includes("adhesePreviewCreativeId");
|
|
1005
|
+
}
|
|
1006
|
+
let isDisposed = false;
|
|
1007
|
+
const [runOnDispose, onDispose] = createHook("onDispose", {
|
|
1008
|
+
onRun(callbacks) {
|
|
1009
|
+
isDisposed = true;
|
|
1010
|
+
logger.debug("Disposal completed");
|
|
1011
|
+
callbacks == null ? void 0 : callbacks.clear();
|
|
1012
|
+
},
|
|
1013
|
+
onAdd() {
|
|
1014
|
+
if (isDisposed)
|
|
1015
|
+
runOnDispose().catch(logger.error);
|
|
1016
|
+
}
|
|
1017
|
+
});
|
|
1018
|
+
function createAdhese(options) {
|
|
1019
|
+
const scope = runtimeCore.effectScope();
|
|
1020
|
+
return scope.run(() => {
|
|
1021
|
+
const mergedOptions = {
|
|
1022
|
+
host: `https://ads-${options.account}.adhese.com`,
|
|
1023
|
+
poolHost: `https://pool-${options.account}.adhese.com`,
|
|
1024
|
+
location: "homepage",
|
|
1025
|
+
requestType: "POST",
|
|
1026
|
+
debug: false,
|
|
1027
|
+
initialSlots: [],
|
|
1028
|
+
findDomSlotsOnLoad: false,
|
|
1029
|
+
consent: false,
|
|
1030
|
+
logReferrer: true,
|
|
1031
|
+
logUrl: true,
|
|
1032
|
+
safeFrame: false,
|
|
1033
|
+
eagerRendering: false,
|
|
1034
|
+
viewabilityTracking: true,
|
|
1035
|
+
plugins: [],
|
|
1036
|
+
...options
|
|
1037
|
+
};
|
|
1038
|
+
setupLogging(mergedOptions);
|
|
1039
|
+
const context = runtimeCore.reactive({
|
|
1040
|
+
location: mergedOptions.location,
|
|
1041
|
+
consent: mergedOptions.consent,
|
|
1042
|
+
debug: mergedOptions.debug,
|
|
1043
|
+
getAll,
|
|
1044
|
+
get,
|
|
1045
|
+
options: mergedOptions,
|
|
1046
|
+
logger,
|
|
1047
|
+
addSlot
|
|
1056
1048
|
});
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
if (response.status === "rejected") {
|
|
1062
|
-
logger.error(response.reason);
|
|
1063
|
-
return false;
|
|
1049
|
+
for (const [index, plugin] of mergedOptions.plugins.entries()) {
|
|
1050
|
+
plugin(context, {
|
|
1051
|
+
index
|
|
1052
|
+
});
|
|
1064
1053
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
function getPreviewObjects() {
|
|
1073
|
-
const currentUrl = new URL(window.location.href);
|
|
1074
|
-
const previewObjects = [];
|
|
1075
|
-
let currentObject = {};
|
|
1076
|
-
for (const [key, value] of currentUrl.searchParams.entries()) {
|
|
1077
|
-
if (key === "adhesePreviewCreativeId" && Object.keys(currentObject).length > 0) {
|
|
1078
|
-
previewObjects.push(currentObject);
|
|
1079
|
-
currentObject = {};
|
|
1054
|
+
context.events = createEventManager();
|
|
1055
|
+
context.safeFrame = options.safeFrame ? createSafeFrame({
|
|
1056
|
+
renderFile: `${mergedOptions.poolHost}/sf/r.html`,
|
|
1057
|
+
context
|
|
1058
|
+
}) : void 0;
|
|
1059
|
+
function getLocation() {
|
|
1060
|
+
return context.location;
|
|
1080
1061
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
return previewObjects;
|
|
1086
|
-
}
|
|
1087
|
-
function requestWithPost({
|
|
1088
|
-
context: { options: { host }, parameters },
|
|
1089
|
-
...options
|
|
1090
|
-
}) {
|
|
1091
|
-
const payload = {
|
|
1092
|
-
...options,
|
|
1093
|
-
slots: options.slots.map((slot) => ({
|
|
1094
|
-
slotname: runtimeCore.toValue(slot.name),
|
|
1095
|
-
parameters: parseParameters(slot.parameters)
|
|
1096
|
-
})),
|
|
1097
|
-
parameters: parameters && parseParameters(parameters)
|
|
1098
|
-
};
|
|
1099
|
-
return fetch(`${new URL(host).href}json`, {
|
|
1100
|
-
method: "POST",
|
|
1101
|
-
body: JSON.stringify(payload),
|
|
1102
|
-
headers: {
|
|
1103
|
-
// eslint-disable-next-line ts/naming-convention
|
|
1104
|
-
"Content-Type": "application/json"
|
|
1062
|
+
function setLocation(newLocation) {
|
|
1063
|
+
var _a;
|
|
1064
|
+
context.location = newLocation;
|
|
1065
|
+
(_a = context.events) == null ? void 0 : _a.locationChange.dispatch(newLocation);
|
|
1105
1066
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1067
|
+
const queryDetector = createQueryDetector({
|
|
1068
|
+
onChange: onQueryChange,
|
|
1069
|
+
queries: mergedOptions.queries
|
|
1070
|
+
});
|
|
1071
|
+
context.parameters = createParameters(mergedOptions, queryDetector);
|
|
1072
|
+
runtimeCore.watch(
|
|
1073
|
+
context.parameters,
|
|
1074
|
+
onParametersChange,
|
|
1075
|
+
{
|
|
1076
|
+
deep: true,
|
|
1077
|
+
immediate: true
|
|
1078
|
+
}
|
|
1079
|
+
);
|
|
1080
|
+
function onParametersChange() {
|
|
1081
|
+
var _a;
|
|
1082
|
+
if (context.parameters)
|
|
1083
|
+
(_a = context.events) == null ? void 0 : _a.parametersChange.dispatch(context.parameters);
|
|
1114
1084
|
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1085
|
+
async function onQueryChange() {
|
|
1086
|
+
var _a, _b;
|
|
1087
|
+
const query = queryDetector.getQuery();
|
|
1088
|
+
(_a = context.parameters) == null ? void 0 : _a.set("dt", query);
|
|
1089
|
+
(_b = context.parameters) == null ? void 0 : _b.set("br", query);
|
|
1090
|
+
await fetchAndRenderAllSlots();
|
|
1091
|
+
}
|
|
1092
|
+
function getConsent() {
|
|
1093
|
+
return context.consent;
|
|
1094
|
+
}
|
|
1095
|
+
function setConsent(newConsent) {
|
|
1096
|
+
var _a, _b;
|
|
1097
|
+
(_a = context.parameters) == null ? void 0 : _a.set("tl", newConsent ? "all" : "none");
|
|
1098
|
+
context.consent = newConsent;
|
|
1099
|
+
(_b = context.events) == null ? void 0 : _b.consentChange.dispatch(newConsent);
|
|
1100
|
+
}
|
|
1101
|
+
const slotManager = createSlotManager({
|
|
1102
|
+
initialSlots: mergedOptions.initialSlots,
|
|
1131
1103
|
context
|
|
1132
1104
|
});
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1105
|
+
function getAll() {
|
|
1106
|
+
return slotManager.getAll() ?? [];
|
|
1107
|
+
}
|
|
1108
|
+
function get(name) {
|
|
1109
|
+
return slotManager.get(name);
|
|
1110
|
+
}
|
|
1111
|
+
function addSlot(slotOptions) {
|
|
1112
|
+
if (!slotManager)
|
|
1113
|
+
throw new Error("Slot manager not initialized");
|
|
1114
|
+
return slotManager.add(slotOptions);
|
|
1115
|
+
}
|
|
1116
|
+
async function findDomSlots2() {
|
|
1117
|
+
const domSlots = (await slotManager.findDomSlots() ?? []).filter((slot) => !slot.lazyLoading);
|
|
1118
|
+
if (domSlots.length <= 0)
|
|
1119
|
+
return [];
|
|
1120
|
+
const ads = await requestAds({
|
|
1121
|
+
slots: domSlots,
|
|
1122
|
+
context
|
|
1123
|
+
});
|
|
1124
|
+
for (const ad of ads) {
|
|
1125
|
+
const slot = slotManager.get(ad.slotName);
|
|
1126
|
+
if (slot)
|
|
1127
|
+
slot.ad.value = ad;
|
|
1128
|
+
}
|
|
1129
|
+
return domSlots;
|
|
1130
|
+
}
|
|
1131
|
+
async function toggleDebug() {
|
|
1132
|
+
var _a, _b;
|
|
1133
|
+
context.debug = !context.debug;
|
|
1134
|
+
if (context.debug) {
|
|
1135
|
+
logger.setMinLogLevelThreshold("debug");
|
|
1136
|
+
logger.debug("Debug mode enabled");
|
|
1137
|
+
(_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
|
|
1138
|
+
} else {
|
|
1139
|
+
logger.debug("Debug mode disabled");
|
|
1140
|
+
logger.setMinLogLevelThreshold("info");
|
|
1141
|
+
(_b = context.events) == null ? void 0 : _b.debugChange.dispatch(false);
|
|
1142
|
+
}
|
|
1143
|
+
return context.debug;
|
|
1144
|
+
}
|
|
1145
|
+
async function fetchAndRenderAllSlots() {
|
|
1146
|
+
const slots = (slotManager.getAll() ?? []).filter((slot) => !slot.lazyLoading);
|
|
1147
|
+
if (slots.length === 0)
|
|
1148
|
+
return;
|
|
1149
|
+
const ads = await requestAds({
|
|
1150
|
+
slots,
|
|
1151
|
+
context
|
|
1152
|
+
});
|
|
1153
|
+
for (const ad of ads) {
|
|
1154
|
+
const slot = slotManager.get(ad.slotName);
|
|
1155
|
+
if (slot)
|
|
1156
|
+
slot.ad.value = ad;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
const disposeOnTcfConsentChange = onTcfConsentChange(async (data) => {
|
|
1160
|
+
var _a, _b;
|
|
1161
|
+
if (!data.tcString)
|
|
1162
|
+
return;
|
|
1163
|
+
logger.debug("TCF v2 consent data received", {
|
|
1164
|
+
data
|
|
1165
|
+
});
|
|
1166
|
+
(_a = context.parameters) == null ? void 0 : _a.set("xt", data.tcString);
|
|
1167
|
+
(_b = context.parameters) == null ? void 0 : _b.delete("tl");
|
|
1168
|
+
await fetchAndRenderAllSlots();
|
|
1147
1169
|
});
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1170
|
+
function dispose() {
|
|
1171
|
+
var _a, _b;
|
|
1172
|
+
queryDetector.dispose();
|
|
1173
|
+
slotManager.dispose();
|
|
1174
|
+
queryDetector.dispose();
|
|
1175
|
+
disposeOnTcfConsentChange();
|
|
1176
|
+
(_a = context.parameters) == null ? void 0 : _a.clear();
|
|
1177
|
+
logger.resetLogs();
|
|
1178
|
+
(_b = context.events) == null ? void 0 : _b.dispose();
|
|
1179
|
+
logger.info("Adhese instance disposed");
|
|
1180
|
+
runOnDispose().catch(logger.error);
|
|
1181
|
+
clearAllHooks();
|
|
1182
|
+
scope.stop();
|
|
1183
|
+
}
|
|
1184
|
+
onInit(async () => {
|
|
1185
|
+
var _a;
|
|
1186
|
+
if ((slotManager.getAll().length ?? 0) > 0)
|
|
1187
|
+
await fetchAndRenderAllSlots().catch(logger.error);
|
|
1188
|
+
if (mergedOptions.findDomSlotsOnLoad)
|
|
1189
|
+
await findDomSlots2();
|
|
1190
|
+
if (mergedOptions.debug || window.location.search.includes("adhese_debug=true") || isPreviewMode())
|
|
1191
|
+
(_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
|
|
1192
|
+
if (!scope.active)
|
|
1193
|
+
dispose();
|
|
1194
|
+
});
|
|
1195
|
+
runOnInit().catch(logger.error);
|
|
1196
|
+
return {
|
|
1197
|
+
parameters: context.parameters,
|
|
1198
|
+
events: context.events,
|
|
1199
|
+
getLocation,
|
|
1200
|
+
setLocation,
|
|
1201
|
+
getConsent,
|
|
1202
|
+
setConsent,
|
|
1203
|
+
addSlot,
|
|
1204
|
+
findDomSlots: findDomSlots2,
|
|
1205
|
+
dispose,
|
|
1206
|
+
toggleDebug,
|
|
1207
|
+
get: slotManager.get,
|
|
1208
|
+
getAll: slotManager.getAll,
|
|
1209
|
+
context,
|
|
1210
|
+
options: mergedOptions
|
|
1211
|
+
};
|
|
1171
1212
|
});
|
|
1172
|
-
return ad;
|
|
1173
1213
|
}
|
|
1174
1214
|
exports.createAdhese = createAdhese;
|
|
1215
|
+
exports.logger = logger;
|
|
1216
|
+
exports.onDispose = onDispose;
|
|
1217
|
+
exports.onInit = onInit;
|
|
1218
|
+
exports.onRender = onRender;
|
|
1219
|
+
exports.onRequest = onRequest;
|
|
1220
|
+
exports.onResponse = onResponse;
|
|
1221
|
+
exports.requestAd = requestAd;
|
|
1222
|
+
exports.requestAds = requestAds;
|
|
1175
1223
|
//# sourceMappingURL=index.cjs.map
|