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