@adhese/sdk 0.7.0 → 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 +676 -666
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +79 -40
- package/dist/index.js +678 -668
- package/dist/index.js.map +1 -1
- package/package.json +12 -6
package/dist/index.cjs
CHANGED
|
@@ -152,109 +152,16 @@ function renderInline(ad, element) {
|
|
|
152
152
|
function generateName(location, format, slot) {
|
|
153
153
|
return `${location}${slot ? `${slot}` : ""}-${format}`;
|
|
154
154
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
);
|
|
166
|
-
return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === name));
|
|
167
|
-
}).map((element) => createSlot({
|
|
168
|
-
format: element.dataset.format,
|
|
169
|
-
containingElement: element,
|
|
170
|
-
slot: element.dataset.slot,
|
|
171
|
-
context
|
|
172
|
-
})).filter((slot) => {
|
|
173
|
-
var _a;
|
|
174
|
-
return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === slot.name.value));
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
function createSlotManager({
|
|
178
|
-
initialSlots = [],
|
|
179
|
-
context
|
|
180
|
-
}) {
|
|
181
|
-
const scope = runtimeCore.effectScope();
|
|
182
|
-
return scope.run(() => {
|
|
183
|
-
const slots = runtimeCore.shallowReactive(/* @__PURE__ */ new Map());
|
|
184
|
-
runtimeCore.watchEffect(() => {
|
|
185
|
-
var _a;
|
|
186
|
-
(_a = context.events) == null ? void 0 : _a.changeSlots.dispatch(Array.from(slots.values()));
|
|
187
|
-
});
|
|
188
|
-
function getAll() {
|
|
189
|
-
return Array.from(slots).map(([, slot]) => slot);
|
|
190
|
-
}
|
|
191
|
-
function add(options) {
|
|
192
|
-
var _a;
|
|
193
|
-
const slot = createSlot({
|
|
194
|
-
...options,
|
|
195
|
-
onDispose: onDispose2,
|
|
196
|
-
context
|
|
197
|
-
});
|
|
198
|
-
function onDispose2() {
|
|
199
|
-
var _a2;
|
|
200
|
-
slots.delete(slot.name.value);
|
|
201
|
-
logger.debug("Slot removed", {
|
|
202
|
-
slot,
|
|
203
|
-
slots: Array.from(slots)
|
|
204
|
-
});
|
|
205
|
-
(_a2 = context.events) == null ? void 0 : _a2.removeSlot.dispatch(slot);
|
|
206
|
-
}
|
|
207
|
-
slots.set(slot.name.value, slot);
|
|
208
|
-
runtimeCore.watch(slot.name, (newName, previousName) => {
|
|
209
|
-
slots.set(newName, slot);
|
|
210
|
-
slots.delete(previousName);
|
|
211
|
-
});
|
|
212
|
-
logger.debug("Slot added", {
|
|
213
|
-
slot,
|
|
214
|
-
slots: Array.from(slots.values())
|
|
215
|
-
});
|
|
216
|
-
(_a = context.events) == null ? void 0 : _a.addSlot.dispatch(slot);
|
|
217
|
-
return slot;
|
|
218
|
-
}
|
|
219
|
-
async function findDomSlots$1() {
|
|
220
|
-
const domSlots = await findDomSlots(
|
|
221
|
-
context
|
|
222
|
-
);
|
|
223
|
-
for (const slot of domSlots)
|
|
224
|
-
slots.set(slot.name.value, slot);
|
|
225
|
-
return domSlots;
|
|
226
|
-
}
|
|
227
|
-
function get(name) {
|
|
228
|
-
return slots.get(name);
|
|
229
|
-
}
|
|
230
|
-
function dispose() {
|
|
231
|
-
for (const slot of slots.values())
|
|
232
|
-
slot.dispose();
|
|
233
|
-
slots.clear();
|
|
234
|
-
scope.stop();
|
|
235
|
-
}
|
|
236
|
-
for (const options of initialSlots) {
|
|
237
|
-
add({
|
|
238
|
-
...options,
|
|
239
|
-
lazyLoading: false
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
return {
|
|
243
|
-
getAll,
|
|
244
|
-
add,
|
|
245
|
-
findDomSlots: findDomSlots$1,
|
|
246
|
-
get,
|
|
247
|
-
dispose
|
|
248
|
-
};
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
function onTcfConsentChange(callback) {
|
|
252
|
-
var _a;
|
|
253
|
-
(_a = window.__tcfapi) == null ? void 0 : _a.call(window, "addEventListener", 2, callback);
|
|
254
|
-
return () => {
|
|
255
|
-
var _a2;
|
|
256
|
-
return (_a2 = window.__tcfapi) == null ? void 0 : _a2.call(window, "removeEventListener", 2, callback);
|
|
257
|
-
};
|
|
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);
|
|
258
165
|
}
|
|
259
166
|
function createQueryDetector({
|
|
260
167
|
onChange,
|
|
@@ -367,54 +274,35 @@ function createLogger({
|
|
|
367
274
|
const logger = createLogger({
|
|
368
275
|
scope: "Adhese SDK"
|
|
369
276
|
});
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
parameters.set("re", btoa(document.referrer));
|
|
374
|
-
if (options.logUrl)
|
|
375
|
-
parameters.set("ur", btoa(window.location.href));
|
|
376
|
-
for (const [key, value] of Object.entries({
|
|
377
|
-
...options.parameters ?? {},
|
|
378
|
-
tl: options.consent ? "all" : "none",
|
|
379
|
-
dt: queryDetector.getQuery(),
|
|
380
|
-
br: queryDetector.getQuery(),
|
|
381
|
-
rn: Math.round(Math.random() * 1e4).toString()
|
|
382
|
-
}))
|
|
383
|
-
parameters.set(key, value);
|
|
384
|
-
return parameters;
|
|
277
|
+
const hookMap = /* @__PURE__ */ new Map();
|
|
278
|
+
function clearAllHooks() {
|
|
279
|
+
hookMap.clear();
|
|
385
280
|
}
|
|
386
|
-
function
|
|
387
|
-
if (mergedOptions.debug || window.location.search.includes("adhese_debug=true")) {
|
|
388
|
-
logger.setMinLogLevelThreshold("debug");
|
|
389
|
-
logger.debug("Debug logging enabled");
|
|
390
|
-
}
|
|
391
|
-
logger.debug("Created Adhese SDK instance", {
|
|
392
|
-
mergedOptions
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
function isPreviewMode() {
|
|
396
|
-
return window.location.search.includes("adhesePreviewCreativeId");
|
|
397
|
-
}
|
|
398
|
-
function createHook({
|
|
281
|
+
function createHook(name, {
|
|
399
282
|
onRun,
|
|
400
|
-
onAdd
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
for (const callback of
|
|
406
|
-
callback();
|
|
407
|
-
onRun == null ? void 0 : onRun(
|
|
408
|
-
|
|
283
|
+
onAdd
|
|
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
|
+
};
|
|
409
293
|
function add(callback) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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
|
+
};
|
|
416
304
|
}
|
|
417
|
-
return [run, add
|
|
305
|
+
return [run, add];
|
|
418
306
|
}
|
|
419
307
|
let resolveOnInitPromise = () => {
|
|
420
308
|
};
|
|
@@ -422,246 +310,313 @@ let isInit = false;
|
|
|
422
310
|
const waitOnInit = new Promise((resolve) => {
|
|
423
311
|
resolveOnInitPromise = resolve;
|
|
424
312
|
});
|
|
425
|
-
const [runOnInit, onInit
|
|
313
|
+
const [runOnInit, onInit] = createHook("onInit", {
|
|
426
314
|
onRun(callbacks) {
|
|
427
315
|
isInit = true;
|
|
428
316
|
resolveOnInitPromise();
|
|
429
317
|
logger.debug("Initialization completed");
|
|
430
|
-
callbacks.clear();
|
|
318
|
+
callbacks == null ? void 0 : callbacks.clear();
|
|
431
319
|
},
|
|
432
320
|
onAdd() {
|
|
433
321
|
if (isInit)
|
|
434
|
-
runOnInit();
|
|
322
|
+
runOnInit().catch(logger.error);
|
|
435
323
|
}
|
|
436
324
|
});
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
resolveOnDisposePromise();
|
|
447
|
-
logger.debug("Disposal completed");
|
|
448
|
-
callbacks.clear();
|
|
449
|
-
},
|
|
450
|
-
onAdd() {
|
|
451
|
-
if (isDisposed)
|
|
452
|
-
runOnDispose();
|
|
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;
|
|
453
334
|
}
|
|
454
335
|
});
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
location: mergedOptions.location,
|
|
478
|
-
consent: mergedOptions.consent,
|
|
479
|
-
debug: mergedOptions.debug,
|
|
480
|
-
getAll,
|
|
481
|
-
get,
|
|
482
|
-
options: mergedOptions,
|
|
483
|
-
logger
|
|
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}`
|
|
484
358
|
});
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
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
|
|
501
374
|
});
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
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"
|
|
551
491
|
}
|
|
552
|
-
|
|
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;
|
|
553
500
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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 = {};
|
|
568
516
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
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"
|
|
582
541
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
for (const ad of ads) {
|
|
592
|
-
const slot = slotManager.get(ad.slotName);
|
|
593
|
-
if (slot)
|
|
594
|
-
slot.ad.value = ad;
|
|
595
|
-
}
|
|
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"
|
|
596
550
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
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
|
|
607
577
|
});
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
logger.
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
}
|
|
623
|
-
for (const plugin of mergedOptions.plugins)
|
|
624
|
-
plugin(context);
|
|
625
|
-
onInit(async () => {
|
|
626
|
-
var _a;
|
|
627
|
-
if ((slotManager.getAll().length ?? 0) > 0)
|
|
628
|
-
await fetchAndRenderAllSlots().catch(logger.error);
|
|
629
|
-
if (mergedOptions.findDomSlotsOnLoad)
|
|
630
|
-
await findDomSlots2();
|
|
631
|
-
if (mergedOptions.debug || window.location.search.includes("adhese_debug=true") || isPreviewMode())
|
|
632
|
-
(_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
|
|
633
|
-
if (!scope.active)
|
|
634
|
-
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
|
+
};
|
|
635
592
|
});
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
...
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
};
|
|
652
|
-
});
|
|
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
|
+
}
|
|
653
608
|
}
|
|
654
|
-
function
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
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;
|
|
664
618
|
}
|
|
619
|
+
const [runOnRender, onRender] = createHook("onRender");
|
|
665
620
|
function useViewabilityObserver({ context, ad, name, element }) {
|
|
666
621
|
let timeoutId = null;
|
|
667
622
|
const {
|
|
@@ -842,10 +797,10 @@ function createSlot(options) {
|
|
|
842
797
|
var _a, _b;
|
|
843
798
|
await waitForDomLoad();
|
|
844
799
|
await waitOnInit;
|
|
845
|
-
|
|
846
|
-
if (
|
|
847
|
-
|
|
848
|
-
|
|
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);
|
|
849
804
|
if (!element.value) {
|
|
850
805
|
const error = `Could not create slot for format ${format.value}. No element found.`;
|
|
851
806
|
logger.error(error, options);
|
|
@@ -853,8 +808,8 @@ function createSlot(options) {
|
|
|
853
808
|
}
|
|
854
809
|
if (context.debug)
|
|
855
810
|
element.value.style.position = "relative";
|
|
856
|
-
if (context.safeFrame &&
|
|
857
|
-
const position = context.safeFrame.addPosition(
|
|
811
|
+
if (context.safeFrame && renderAd && renderMode === "iframe") {
|
|
812
|
+
const position = context.safeFrame.addPosition(renderAd, element.value);
|
|
858
813
|
await context.safeFrame.render(position);
|
|
859
814
|
} else {
|
|
860
815
|
renderFunctions[renderMode](renderAd, element.value);
|
|
@@ -893,321 +848,376 @@ function createSlot(options) {
|
|
|
893
848
|
scope.stop();
|
|
894
849
|
}
|
|
895
850
|
return {
|
|
896
|
-
location: context.location,
|
|
897
|
-
lazyLoading: options.lazyLoading ?? false,
|
|
898
|
-
slot,
|
|
899
|
-
parameters,
|
|
900
|
-
format,
|
|
901
|
-
name,
|
|
902
|
-
ad,
|
|
903
|
-
isViewabilityTracked,
|
|
904
|
-
isImpressionTracked,
|
|
905
|
-
render,
|
|
906
|
-
getElement,
|
|
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();
|
|
953
|
+
scope.stop();
|
|
954
|
+
}
|
|
955
|
+
for (const options of initialSlots) {
|
|
956
|
+
add({
|
|
957
|
+
...options,
|
|
958
|
+
lazyLoading: false
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
return {
|
|
962
|
+
getAll,
|
|
963
|
+
add,
|
|
964
|
+
findDomSlots: findDomSlots$1,
|
|
965
|
+
get,
|
|
907
966
|
dispose
|
|
908
967
|
};
|
|
909
968
|
});
|
|
910
969
|
}
|
|
911
|
-
function
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
970
|
+
function onTcfConsentChange(callback) {
|
|
971
|
+
var _a;
|
|
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);
|
|
976
|
+
};
|
|
918
977
|
}
|
|
919
|
-
|
|
920
|
-
const
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
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");
|
|
926
998
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
try {
|
|
945
|
-
return JSON.parse(value.replaceAll("'", '"'));
|
|
946
|
-
} catch (error) {
|
|
947
|
-
addIssue({
|
|
948
|
-
code: zod.ZodIssueCode.custom,
|
|
949
|
-
message: `Invalid JSON: ${error.message}`
|
|
950
|
-
});
|
|
951
|
-
return zod.NEVER;
|
|
999
|
+
logger.debug("Created Adhese SDK instance", {
|
|
1000
|
+
mergedOptions
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
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);
|
|
952
1016
|
}
|
|
953
1017
|
});
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
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
|
|
966
1048
|
});
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
auctionable: booleanLike.optional(),
|
|
989
|
-
body: isJsonOrHtmlOptionalString,
|
|
990
|
-
clickTag: urlLike.optional(),
|
|
991
|
-
comment: zod.string().optional(),
|
|
992
|
-
creativeName: zod.string().optional(),
|
|
993
|
-
deliveryGroupId: zod.string().optional(),
|
|
994
|
-
deliveryMultiples: zod.string().optional(),
|
|
995
|
-
ext: zod.string().optional(),
|
|
996
|
-
extension: zod.object({
|
|
997
|
-
mediaType: zod.string(),
|
|
998
|
-
prebid: zod.unknown().optional()
|
|
999
|
-
}).optional(),
|
|
1000
|
-
height: numberLike.optional(),
|
|
1001
|
-
id: zod.string(),
|
|
1002
|
-
impressionCounter: urlLike.optional(),
|
|
1003
|
-
libId: zod.string().optional(),
|
|
1004
|
-
orderId: zod.string().optional(),
|
|
1005
|
-
orderName: zod.string().optional(),
|
|
1006
|
-
orderProperty: zod.string().optional(),
|
|
1007
|
-
origin: zod.union([zod.literal("JERLICIA"), zod.literal("DALE")]),
|
|
1008
|
-
originData: zod.unknown().optional(),
|
|
1009
|
-
originInstance: zod.string().optional(),
|
|
1010
|
-
poolPath: urlLike.optional(),
|
|
1011
|
-
preview: booleanLike.optional(),
|
|
1012
|
-
priority: numberLike.optional(),
|
|
1013
|
-
sfSrc: urlLike.optional(),
|
|
1014
|
-
share: zod.string().optional(),
|
|
1015
|
-
// eslint-disable-next-line ts/naming-convention
|
|
1016
|
-
slotID: zod.string(),
|
|
1017
|
-
slotName: zod.string(),
|
|
1018
|
-
swfSrc: urlLike.optional(),
|
|
1019
|
-
tag: isJsonOrHtmlOptionalString,
|
|
1020
|
-
tagUrl: urlLike.optional(),
|
|
1021
|
-
timeStamp: dateLike.optional(),
|
|
1022
|
-
trackedImpressionCounter: urlLike.optional(),
|
|
1023
|
-
tracker: urlLike.optional(),
|
|
1024
|
-
trackingUrl: urlLike.optional(),
|
|
1025
|
-
url: urlLike.optional(),
|
|
1026
|
-
viewableImpressionCounter: urlLike.optional(),
|
|
1027
|
-
width: numberLike.optional(),
|
|
1028
|
-
widthLarge: cssValueLike.optional()
|
|
1029
|
-
});
|
|
1030
|
-
const jerliciaSchema = zod.object({
|
|
1031
|
-
origin: zod.literal("JERLICIA"),
|
|
1032
|
-
tag: isJsonOrHtmlString
|
|
1033
|
-
}).passthrough();
|
|
1034
|
-
const daleSchema = zod.object({
|
|
1035
|
-
origin: zod.literal("DALE"),
|
|
1036
|
-
body: isJsonOrHtmlString
|
|
1037
|
-
}).passthrough().transform(({ body, ...data }) => ({
|
|
1038
|
-
...data,
|
|
1039
|
-
tag: body
|
|
1040
|
-
}));
|
|
1041
|
-
const adResponseSchema = baseSchema.extend({
|
|
1042
|
-
additionalCreatives: zod.lazy(() => zod.union([adResponseSchema.array(), zod.string()]).optional())
|
|
1043
|
-
});
|
|
1044
|
-
const adSchema = adResponseSchema.transform(({
|
|
1045
|
-
additionalCreatives,
|
|
1046
|
-
...data
|
|
1047
|
-
}) => {
|
|
1048
|
-
const filteredValue = Object.fromEntries(
|
|
1049
|
-
Object.entries(data).filter(([, value]) => Boolean(value) && JSON.stringify(value) !== "{}" && JSON.stringify(value) !== "[]")
|
|
1050
|
-
);
|
|
1051
|
-
return {
|
|
1052
|
-
...filteredValue,
|
|
1053
|
-
additionalCreatives: Array.isArray(additionalCreatives) ? additionalCreatives.map((creative) => adSchema.parse(creative)) : additionalCreatives
|
|
1054
|
-
};
|
|
1055
|
-
});
|
|
1056
|
-
function parseResponse(response) {
|
|
1057
|
-
const schemaMap = {
|
|
1058
|
-
/* eslint-disable ts/naming-convention */
|
|
1059
|
-
JERLICIA: jerliciaSchema,
|
|
1060
|
-
DALE: daleSchema
|
|
1061
|
-
/* eslint-enable ts/naming-convention */
|
|
1062
|
-
};
|
|
1063
|
-
const preParsed = adResponseSchema.array().parse(response);
|
|
1064
|
-
return preParsed.map((item) => {
|
|
1065
|
-
const schema = schemaMap[item.origin];
|
|
1066
|
-
if (!schema)
|
|
1067
|
-
return adSchema.parse(item);
|
|
1068
|
-
return schema.parse(item);
|
|
1069
|
-
});
|
|
1070
|
-
}
|
|
1071
|
-
async function requestPreviews(account) {
|
|
1072
|
-
const previewObjects = getPreviewObjects();
|
|
1073
|
-
const list = (await Promise.allSettled(previewObjects.filter((previewObject) => "adhesePreviewCreativeId" in previewObject).map(async (previewObject) => {
|
|
1074
|
-
const endpoint = new URL(`https://${account}-preview.adhese.org/creatives/preview/json/tag.do`);
|
|
1075
|
-
endpoint.searchParams.set(
|
|
1076
|
-
"id",
|
|
1077
|
-
previewObject.adhesePreviewCreativeId
|
|
1078
|
-
);
|
|
1079
|
-
const response = await fetch(endpoint.href, {
|
|
1080
|
-
method: "GET",
|
|
1081
|
-
headers: {
|
|
1082
|
-
accept: "application/json"
|
|
1083
|
-
}
|
|
1049
|
+
for (const [index, plugin] of mergedOptions.plugins.entries()) {
|
|
1050
|
+
plugin(context, {
|
|
1051
|
+
index
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
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;
|
|
1061
|
+
}
|
|
1062
|
+
function setLocation(newLocation) {
|
|
1063
|
+
var _a;
|
|
1064
|
+
context.location = newLocation;
|
|
1065
|
+
(_a = context.events) == null ? void 0 : _a.locationChange.dispatch(newLocation);
|
|
1066
|
+
}
|
|
1067
|
+
const queryDetector = createQueryDetector({
|
|
1068
|
+
onChange: onQueryChange,
|
|
1069
|
+
queries: mergedOptions.queries
|
|
1084
1070
|
});
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
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);
|
|
1092
1084
|
}
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
}
|
|
1100
|
-
function getPreviewObjects() {
|
|
1101
|
-
const currentUrl = new URL(window.location.href);
|
|
1102
|
-
const previewObjects = [];
|
|
1103
|
-
let currentObject = {};
|
|
1104
|
-
for (const [key, value] of currentUrl.searchParams.entries()) {
|
|
1105
|
-
if (key === "adhesePreviewCreativeId" && Object.keys(currentObject).length > 0) {
|
|
1106
|
-
previewObjects.push(currentObject);
|
|
1107
|
-
currentObject = {};
|
|
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();
|
|
1108
1091
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
if (Object.keys(currentObject).length > 0)
|
|
1112
|
-
previewObjects.push(currentObject);
|
|
1113
|
-
return previewObjects;
|
|
1114
|
-
}
|
|
1115
|
-
function requestWithPost({
|
|
1116
|
-
context: { options: { host }, parameters },
|
|
1117
|
-
...options
|
|
1118
|
-
}) {
|
|
1119
|
-
const payload = {
|
|
1120
|
-
...options,
|
|
1121
|
-
slots: options.slots.map((slot) => ({
|
|
1122
|
-
slotname: runtimeCore.toValue(slot.name),
|
|
1123
|
-
parameters: parseParameters(slot.parameters)
|
|
1124
|
-
})),
|
|
1125
|
-
parameters: parameters && parseParameters(parameters)
|
|
1126
|
-
};
|
|
1127
|
-
return fetch(`${new URL(host).href}json`, {
|
|
1128
|
-
method: "POST",
|
|
1129
|
-
body: JSON.stringify(payload),
|
|
1130
|
-
headers: {
|
|
1131
|
-
// eslint-disable-next-line ts/naming-convention
|
|
1132
|
-
"Content-Type": "application/json"
|
|
1092
|
+
function getConsent() {
|
|
1093
|
+
return context.consent;
|
|
1133
1094
|
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
headers: {
|
|
1140
|
-
// eslint-disable-next-line ts/naming-convention
|
|
1141
|
-
"Content-Type": "application/json"
|
|
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);
|
|
1142
1100
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
function parseParameters(parameters) {
|
|
1146
|
-
return Object.fromEntries(Array.from(parameters.entries()).filter(([key]) => {
|
|
1147
|
-
if (key.length === 2)
|
|
1148
|
-
return true;
|
|
1149
|
-
logger.warn(`Invalid parameter key: ${key}. Key should be exactly 2 characters long. Key will be ignored.`);
|
|
1150
|
-
return false;
|
|
1151
|
-
}).map(([key, value]) => {
|
|
1152
|
-
if (typeof value === "string")
|
|
1153
|
-
return [key, filterSpecialChars(value)];
|
|
1154
|
-
return [key, value.map(filterSpecialChars)];
|
|
1155
|
-
}));
|
|
1156
|
-
}
|
|
1157
|
-
function filterSpecialChars(value) {
|
|
1158
|
-
const specialRegex = /[^\p{L}\p{N}_]/gu;
|
|
1159
|
-
return value.replaceAll(specialRegex, "_");
|
|
1160
|
-
}
|
|
1161
|
-
async function requestAds(options) {
|
|
1162
|
-
var _a, _b, _c, _d, _e;
|
|
1163
|
-
const { context } = options;
|
|
1164
|
-
try {
|
|
1165
|
-
(_a = context.events) == null ? void 0 : _a.requestAd.dispatch({
|
|
1166
|
-
...options,
|
|
1101
|
+
const slotManager = createSlotManager({
|
|
1102
|
+
initialSlots: mergedOptions.initialSlots,
|
|
1167
1103
|
context
|
|
1168
1104
|
});
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
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();
|
|
1183
1169
|
});
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
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
|
+
};
|
|
1207
1212
|
});
|
|
1208
|
-
return ad;
|
|
1209
1213
|
}
|
|
1210
1214
|
exports.createAdhese = createAdhese;
|
|
1215
|
+
exports.logger = logger;
|
|
1211
1216
|
exports.onDispose = onDispose;
|
|
1212
1217
|
exports.onInit = onInit;
|
|
1218
|
+
exports.onRender = onRender;
|
|
1219
|
+
exports.onRequest = onRequest;
|
|
1220
|
+
exports.onResponse = onResponse;
|
|
1221
|
+
exports.requestAd = requestAd;
|
|
1222
|
+
exports.requestAds = requestAds;
|
|
1213
1223
|
//# sourceMappingURL=index.cjs.map
|