@hientran0208/ads-sdk 1.0.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 +53 -0
- package/dist/ads-client-BVlLFVQU.d.cts +352 -0
- package/dist/ads-client-BVlLFVQU.d.ts +352 -0
- package/dist/ads-sa.global.js +3 -0
- package/dist/ads-sa.global.js.map +1 -0
- package/dist/chunk-GA4VEFSM.js +900 -0
- package/dist/chunk-GA4VEFSM.js.map +1 -0
- package/dist/index.cjs +1012 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +256 -0
- package/dist/index.d.ts +256 -0
- package/dist/index.js +88 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +960 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +50 -0
- package/dist/react.d.ts +50 -0
- package/dist/react.js +63 -0
- package/dist/react.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,900 @@
|
|
|
1
|
+
import { OOP_FORMATS, plan, normalize, CONSERVATIVE_CONSENT_DEFAULTS, isDomainAllowed } from '@hientran0208/ads-manifest';
|
|
2
|
+
|
|
3
|
+
// src/core/boot-spine.ts
|
|
4
|
+
var BOOT_SPINE = [
|
|
5
|
+
"disableInitialLoad",
|
|
6
|
+
"enableSingleRequest",
|
|
7
|
+
"collapseEmptyDivs",
|
|
8
|
+
"enableServices"
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
// src/core/consent-gate-contract.ts
|
|
12
|
+
function createAllowAllConsentGate(signals) {
|
|
13
|
+
const snap = {
|
|
14
|
+
signals: signals ?? {
|
|
15
|
+
ad_storage: "granted",
|
|
16
|
+
analytics_storage: "granted",
|
|
17
|
+
ad_user_data: "granted",
|
|
18
|
+
ad_personalization: "granted"
|
|
19
|
+
},
|
|
20
|
+
allows: () => true,
|
|
21
|
+
resolved: true
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
snapshot: () => snap,
|
|
25
|
+
onChange: () => () => {
|
|
26
|
+
},
|
|
27
|
+
start: () => {
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/core/event-bus.ts
|
|
33
|
+
function createEventBus(onHandlerError) {
|
|
34
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
35
|
+
return {
|
|
36
|
+
on(type, handler) {
|
|
37
|
+
let set = handlers.get(type);
|
|
38
|
+
if (!set) {
|
|
39
|
+
set = /* @__PURE__ */ new Set();
|
|
40
|
+
handlers.set(type, set);
|
|
41
|
+
}
|
|
42
|
+
set.add(handler);
|
|
43
|
+
return () => set.delete(handler);
|
|
44
|
+
},
|
|
45
|
+
emit(ev) {
|
|
46
|
+
const set = handlers.get(ev.type);
|
|
47
|
+
if (!set) return;
|
|
48
|
+
for (const handler of [...set]) {
|
|
49
|
+
try {
|
|
50
|
+
handler(ev);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
onHandlerError?.(err);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function dispatchTraits(format) {
|
|
59
|
+
const isOop = OOP_FORMATS.includes(format);
|
|
60
|
+
if (format === "interstitial") {
|
|
61
|
+
return { usesDiv: false, ridesEagerBatch: false, onDemandOnly: true, refreshable: false };
|
|
62
|
+
}
|
|
63
|
+
if (isOop) {
|
|
64
|
+
return { usesDiv: false, ridesEagerBatch: true, onDemandOnly: false, refreshable: false };
|
|
65
|
+
}
|
|
66
|
+
return { usesDiv: true, ridesEagerBatch: true, onDemandOnly: false, refreshable: true };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/core/registries/adapter-slot-registry.ts
|
|
70
|
+
function createAdapterSlotRegistry() {
|
|
71
|
+
const byType = /* @__PURE__ */ new Map();
|
|
72
|
+
return {
|
|
73
|
+
register(type, vendor) {
|
|
74
|
+
byType.set(type, vendor);
|
|
75
|
+
},
|
|
76
|
+
resolve(type) {
|
|
77
|
+
return byType.get(type) ?? null;
|
|
78
|
+
},
|
|
79
|
+
all() {
|
|
80
|
+
return [...byType.values()];
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/core/registries/provider-registry.ts
|
|
86
|
+
function createProviderRegistry() {
|
|
87
|
+
const providers = [];
|
|
88
|
+
return {
|
|
89
|
+
register(provider) {
|
|
90
|
+
providers.push(provider);
|
|
91
|
+
},
|
|
92
|
+
resolve(format) {
|
|
93
|
+
return providers.find((p) => p.capabilities().includes(format)) ?? null;
|
|
94
|
+
},
|
|
95
|
+
all() {
|
|
96
|
+
return [...providers];
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/core/slot-lifecycle.ts
|
|
102
|
+
var LEGAL = {
|
|
103
|
+
registered: ["gated", "destroyed"],
|
|
104
|
+
gated: ["requested", "destroyed"],
|
|
105
|
+
requested: ["rendered", "destroyed"],
|
|
106
|
+
rendered: ["requested", "destroyed"],
|
|
107
|
+
// refresh re-enters requested
|
|
108
|
+
destroyed: []
|
|
109
|
+
};
|
|
110
|
+
function createSlotLifecycle() {
|
|
111
|
+
const records = /* @__PURE__ */ new Map();
|
|
112
|
+
return {
|
|
113
|
+
register(slot, epoch) {
|
|
114
|
+
const rec = { slot, handle: null, state: "registered", epoch };
|
|
115
|
+
records.set(slot.__uid, rec);
|
|
116
|
+
return rec;
|
|
117
|
+
},
|
|
118
|
+
get(uid) {
|
|
119
|
+
return records.get(uid);
|
|
120
|
+
},
|
|
121
|
+
all() {
|
|
122
|
+
return [...records.values()];
|
|
123
|
+
},
|
|
124
|
+
transition(uid, to) {
|
|
125
|
+
const rec = records.get(uid);
|
|
126
|
+
if (!rec) return false;
|
|
127
|
+
if (!LEGAL[rec.state].includes(to)) return false;
|
|
128
|
+
rec.state = to;
|
|
129
|
+
return true;
|
|
130
|
+
},
|
|
131
|
+
attachHandle(uid, handle) {
|
|
132
|
+
const rec = records.get(uid);
|
|
133
|
+
if (rec) rec.handle = handle;
|
|
134
|
+
},
|
|
135
|
+
isCurrent(uid, epoch) {
|
|
136
|
+
const rec = records.get(uid);
|
|
137
|
+
return !!rec && rec.epoch === epoch && rec.state !== "destroyed";
|
|
138
|
+
},
|
|
139
|
+
destroyAll() {
|
|
140
|
+
for (const rec of records.values()) rec.state = "destroyed";
|
|
141
|
+
records.clear();
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/inject/tag-injector.ts
|
|
147
|
+
function hostOf(src) {
|
|
148
|
+
try {
|
|
149
|
+
return new URL(src, "https://invalid.local").hostname;
|
|
150
|
+
} catch {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function createTagInjector(bus, doc = document) {
|
|
155
|
+
const injected = /* @__PURE__ */ new Set();
|
|
156
|
+
return {
|
|
157
|
+
has(key) {
|
|
158
|
+
return injected.has(key);
|
|
159
|
+
},
|
|
160
|
+
inject(src, allowedHosts, opts = {}) {
|
|
161
|
+
const key = opts.key ?? src;
|
|
162
|
+
if (injected.has(key)) return true;
|
|
163
|
+
const host = hostOf(src);
|
|
164
|
+
if (!host || !allowedHosts.includes(host)) {
|
|
165
|
+
bus.emit({
|
|
166
|
+
type: "error",
|
|
167
|
+
scope: "tag-injector",
|
|
168
|
+
message: `blocked script from disallowed host: ${host ?? src}`
|
|
169
|
+
});
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
const el = doc.createElement("script");
|
|
173
|
+
el.src = src;
|
|
174
|
+
if (opts.defer) el.defer = true;
|
|
175
|
+
else el.async = true;
|
|
176
|
+
for (const [k, v] of Object.entries(opts.attrs ?? {})) {
|
|
177
|
+
el.setAttribute(k, v);
|
|
178
|
+
}
|
|
179
|
+
(doc.head ?? doc.documentElement).appendChild(el);
|
|
180
|
+
injected.add(key);
|
|
181
|
+
bus.emit({ type: "tag:injected", host, key });
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/inject/lazy-observer.ts
|
|
188
|
+
function createLazyObserver(win = window) {
|
|
189
|
+
const observers = [];
|
|
190
|
+
const Ctor = win.IntersectionObserver;
|
|
191
|
+
return {
|
|
192
|
+
observe(el, rootMargin, onEnter) {
|
|
193
|
+
if (!Ctor) {
|
|
194
|
+
onEnter();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const io = new Ctor(
|
|
198
|
+
(entries, obs) => {
|
|
199
|
+
for (const entry of entries) {
|
|
200
|
+
if (entry.isIntersecting) {
|
|
201
|
+
obs.disconnect();
|
|
202
|
+
onEnter();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
{ rootMargin }
|
|
207
|
+
);
|
|
208
|
+
io.observe(el);
|
|
209
|
+
observers.push(io);
|
|
210
|
+
},
|
|
211
|
+
disconnect() {
|
|
212
|
+
for (const io of observers) io.disconnect();
|
|
213
|
+
observers.length = 0;
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// src/core/dynamic-params.ts
|
|
219
|
+
function createDynamicParamsStore() {
|
|
220
|
+
const store = {
|
|
221
|
+
page: {},
|
|
222
|
+
perSlot: /* @__PURE__ */ new Map(),
|
|
223
|
+
setPage(p) {
|
|
224
|
+
store.page = { ...store.page, ...p };
|
|
225
|
+
},
|
|
226
|
+
setSlot(id, p) {
|
|
227
|
+
store.perSlot.set(id, { ...store.perSlot.get(id) ?? {}, ...p });
|
|
228
|
+
},
|
|
229
|
+
resolved(slotId) {
|
|
230
|
+
const slot = slotId ? store.perSlot.get(slotId) : void 0;
|
|
231
|
+
return { ...store.page, ...slot ?? {} };
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
return store;
|
|
235
|
+
}
|
|
236
|
+
function runGateChain(deps) {
|
|
237
|
+
const { manifest, bus, hostname } = deps;
|
|
238
|
+
if (manifest.killed) {
|
|
239
|
+
bus.emit({ type: "warning", scope: "gate:kill", message: "kill switch active" });
|
|
240
|
+
return { ok: false, gate: "kill", reason: "killed" };
|
|
241
|
+
}
|
|
242
|
+
if (!isDomainAllowed(hostname, manifest.allowDomains)) {
|
|
243
|
+
bus.emit({
|
|
244
|
+
type: "error",
|
|
245
|
+
scope: "gate:domain",
|
|
246
|
+
message: `host not allowed: ${hostname}`
|
|
247
|
+
});
|
|
248
|
+
return { ok: false, gate: "domain", reason: "domain_not_allowed" };
|
|
249
|
+
}
|
|
250
|
+
return { ok: true };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/core/ads-engine.ts
|
|
254
|
+
var GUARD_KEY = "__adsEngine";
|
|
255
|
+
function createAdsEngine(deps = {}) {
|
|
256
|
+
const win = deps.win ?? (typeof window !== "undefined" ? window : void 0);
|
|
257
|
+
const doc = deps.doc ?? (typeof document !== "undefined" ? document : void 0);
|
|
258
|
+
const bus = deps.bus ?? createEventBus();
|
|
259
|
+
const providerRegistry = deps.providerRegistry ?? createProviderRegistry();
|
|
260
|
+
const adapterRegistry = deps.adapterRegistry ?? createAdapterSlotRegistry();
|
|
261
|
+
const consentGate = deps.consentGate ?? createAllowAllConsentGate();
|
|
262
|
+
const injector = deps.injector ?? (doc ? createTagInjector(bus, doc) : void 0);
|
|
263
|
+
const lazyObserver = deps.lazyObserver ?? (win ? createLazyObserver(win) : void 0);
|
|
264
|
+
const dynamicStore = createDynamicParamsStore();
|
|
265
|
+
const lifecycle = createSlotLifecycle();
|
|
266
|
+
let booted = false;
|
|
267
|
+
let epoch = 0;
|
|
268
|
+
let current = null;
|
|
269
|
+
let consentUnsub = null;
|
|
270
|
+
function planContext(overridePageView) {
|
|
271
|
+
const base = current.ctx;
|
|
272
|
+
const dyn = dynamicStore.resolved();
|
|
273
|
+
const merged = { ...dyn };
|
|
274
|
+
if (overridePageView !== void 0) merged.changeCorrelator = overridePageView;
|
|
275
|
+
return {
|
|
276
|
+
url: merged.pageUrl ?? base.url,
|
|
277
|
+
viewport: base.viewport,
|
|
278
|
+
...Object.keys(merged).length ? { dynamic: merged } : {}
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function defineSlots(rp) {
|
|
282
|
+
for (const slot of rp.slots) {
|
|
283
|
+
const provider = providerRegistry.resolve(slot.format);
|
|
284
|
+
if (!provider) {
|
|
285
|
+
bus.emit({ type: "warning", scope: "dispatch", message: `no provider for format ${slot.format}` });
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
lifecycle.register(slot, epoch);
|
|
289
|
+
bus.emit({ type: "slot:registered", slotId: slot.id, uid: slot.__uid });
|
|
290
|
+
const handle = provider.prepare(slot);
|
|
291
|
+
lifecycle.attachHandle(slot.__uid, handle);
|
|
292
|
+
lifecycle.transition(slot.__uid, "gated");
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function eagerHandles() {
|
|
296
|
+
return lifecycle.all().filter((r) => r.handle && dispatchTraits(r.slot.format).ridesEagerBatch && r.slot.loading !== "lazy").map((r) => r.handle).filter(Boolean);
|
|
297
|
+
}
|
|
298
|
+
function requestHandles(handles, changeCorrelator) {
|
|
299
|
+
if (!handles.length) return;
|
|
300
|
+
for (const h of handles) {
|
|
301
|
+
const rec = lifecycle.get(h.uid);
|
|
302
|
+
if (rec && lifecycle.transition(h.uid, "requested")) {
|
|
303
|
+
bus.emit({ type: "slot:requested", slotId: rec.slot.id, uid: h.uid });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
providerRegistry.all()[0]?.request(handles, { changeCorrelator });
|
|
307
|
+
}
|
|
308
|
+
function armLazy() {
|
|
309
|
+
for (const rec of lifecycle.all()) {
|
|
310
|
+
if (rec.slot.loading !== "lazy" || !rec.handle) continue;
|
|
311
|
+
const el = doc?.getElementById(rec.slot.id) ?? void 0;
|
|
312
|
+
const arm = () => {
|
|
313
|
+
if (!consentGate.snapshot().allows("gpt")) return;
|
|
314
|
+
requestHandles([rec.handle], false);
|
|
315
|
+
};
|
|
316
|
+
if (lazyObserver && el) lazyObserver.observe(el, rec.slot.rootMargin ?? "0px", arm);
|
|
317
|
+
else if (lazyObserver && !el) lazyObserver.observe(doc.body, rec.slot.rootMargin ?? "0px", arm);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
function armTagVendors() {
|
|
321
|
+
if (!current || !injector) return;
|
|
322
|
+
for (const tag of current.plan.managedTags) {
|
|
323
|
+
const vendor = adapterRegistry.resolve(tag.type);
|
|
324
|
+
if (!vendor) continue;
|
|
325
|
+
if (!consentGate.snapshot().allows(tag.type)) continue;
|
|
326
|
+
vendor.init(tag, { injector, bus, allowedHosts: current.plan.allowedTagHosts });
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function bootResolved(rp, autoShow) {
|
|
330
|
+
for (const provider of providerRegistry.all()) {
|
|
331
|
+
for (const step of BOOT_SPINE) provider.bootStep(step);
|
|
332
|
+
}
|
|
333
|
+
defineSlots(rp);
|
|
334
|
+
booted = true;
|
|
335
|
+
consentGate.start();
|
|
336
|
+
consentUnsub = consentGate.onChange(() => onConsentChange());
|
|
337
|
+
armTagVendors();
|
|
338
|
+
if (autoShow && consentGate.snapshot().allows("gpt")) {
|
|
339
|
+
requestHandles(eagerHandles(), false);
|
|
340
|
+
armLazy();
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
function claimPageGuard() {
|
|
344
|
+
if (win && win[GUARD_KEY]) {
|
|
345
|
+
bus.emit({ type: "warning", scope: "dual-load", message: "an AdsEngine already booted on this page; ignoring second init" });
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
if (win) win[GUARD_KEY] = true;
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
function onConsentChange() {
|
|
352
|
+
if (!booted || !current) return;
|
|
353
|
+
armTagVendors();
|
|
354
|
+
if (consentGate.snapshot().allows("gpt")) {
|
|
355
|
+
const handles = eagerHandles().filter((h) => {
|
|
356
|
+
const rec = lifecycle.get(h.uid);
|
|
357
|
+
return rec && rec.state !== "requested";
|
|
358
|
+
});
|
|
359
|
+
requestHandles(handles, false);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
providerRegistry,
|
|
364
|
+
adapterRegistry,
|
|
365
|
+
isBooted: () => booted,
|
|
366
|
+
getExecutedPlan: () => current?.plan ?? null,
|
|
367
|
+
on: (type, handler) => bus.on(type, handler),
|
|
368
|
+
init(manifest, ctx) {
|
|
369
|
+
if (!claimPageGuard()) return;
|
|
370
|
+
const normalized = normalize(manifest);
|
|
371
|
+
const hostname = win?.location?.hostname ?? new URL(ctx.url).hostname;
|
|
372
|
+
const gate = runGateChain({ manifest: normalized, bus, hostname });
|
|
373
|
+
if (!gate.ok) {
|
|
374
|
+
booted = false;
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
current = { manifest, ctx, plan: { slots: [], managedTags: [], video: [], allowedTagHosts: [] } };
|
|
378
|
+
current.plan = plan(manifest, planContext());
|
|
379
|
+
bootResolved(current.plan, normalized.autoShow);
|
|
380
|
+
},
|
|
381
|
+
initFromPlan(rp, ctx, opts = {}) {
|
|
382
|
+
if (!claimPageGuard()) return;
|
|
383
|
+
current = { ctx, plan: rp };
|
|
384
|
+
bootResolved(rp, opts.autoShow ?? true);
|
|
385
|
+
},
|
|
386
|
+
setPageParams(p) {
|
|
387
|
+
dynamicStore.setPage(p);
|
|
388
|
+
},
|
|
389
|
+
setSlotParams(id, p) {
|
|
390
|
+
dynamicStore.setSlot(id, p);
|
|
391
|
+
},
|
|
392
|
+
refresh(ids, opts = {}) {
|
|
393
|
+
if (!booted || !current) return;
|
|
394
|
+
const newPageView = opts.newPageView ?? false;
|
|
395
|
+
if (newPageView) epoch += 1;
|
|
396
|
+
if (current.manifest) {
|
|
397
|
+
current = { ...current, plan: plan(current.manifest, planContext(newPageView)) };
|
|
398
|
+
}
|
|
399
|
+
const targets = ids && ids.length ? lifecycle.all().filter((r) => ids.includes(r.slot.id) && r.handle) : lifecycle.all().filter((r) => r.handle && dispatchTraits(r.slot.format).refreshable);
|
|
400
|
+
const handles = targets.map((r) => r.handle).filter(Boolean);
|
|
401
|
+
if (!handles.length) return;
|
|
402
|
+
for (const r of targets) lifecycle.transition(r.slot.__uid, "requested");
|
|
403
|
+
providerRegistry.all()[0]?.refresh(handles, { changeCorrelator: newPageView });
|
|
404
|
+
},
|
|
405
|
+
display(id) {
|
|
406
|
+
if (!booted) return;
|
|
407
|
+
const rec = lifecycle.all().find((r) => r.slot.id === id);
|
|
408
|
+
if (!rec?.handle) return;
|
|
409
|
+
if (!consentGate.snapshot().allows("gpt")) return;
|
|
410
|
+
providerRegistry.all()[0]?.display(rec.handle);
|
|
411
|
+
},
|
|
412
|
+
destroy() {
|
|
413
|
+
consentUnsub?.();
|
|
414
|
+
lazyObserver?.disconnect();
|
|
415
|
+
for (const provider of providerRegistry.all()) {
|
|
416
|
+
const handles = lifecycle.all().map((r) => r.handle).filter(Boolean);
|
|
417
|
+
if (handles.length) provider.destroy(handles);
|
|
418
|
+
}
|
|
419
|
+
lifecycle.destroyAll();
|
|
420
|
+
booted = false;
|
|
421
|
+
current = null;
|
|
422
|
+
if (win) delete win[GUARD_KEY];
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// src/consent/consent-mode.ts
|
|
428
|
+
function ensureGtag(host) {
|
|
429
|
+
if (typeof host.gtag === "function") return host.gtag;
|
|
430
|
+
host.dataLayer = host.dataLayer ?? [];
|
|
431
|
+
const gtag = (...args) => {
|
|
432
|
+
host.dataLayer.push(args);
|
|
433
|
+
};
|
|
434
|
+
host.gtag = gtag;
|
|
435
|
+
return gtag;
|
|
436
|
+
}
|
|
437
|
+
function createConsentMode(host = window) {
|
|
438
|
+
let defaultsApplied = false;
|
|
439
|
+
return {
|
|
440
|
+
defaultsSet: () => defaultsApplied,
|
|
441
|
+
setDefaults(signals) {
|
|
442
|
+
const gtag = ensureGtag(host);
|
|
443
|
+
gtag("consent", "default", { ...signals, wait_for_update: 500 });
|
|
444
|
+
defaultsApplied = true;
|
|
445
|
+
},
|
|
446
|
+
update(signals) {
|
|
447
|
+
const gtag = ensureGtag(host);
|
|
448
|
+
gtag("consent", "update", { ...signals });
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// src/consent/tcf-bridge.ts
|
|
454
|
+
var READY_STATUSES = /* @__PURE__ */ new Set(["tcloaded", "useractioncomplete"]);
|
|
455
|
+
function createTcfBridge(host = window, opts = {}) {
|
|
456
|
+
const api = host.__tcfapi;
|
|
457
|
+
const setTimeoutFn = opts.setTimeoutFn ?? setTimeout;
|
|
458
|
+
return {
|
|
459
|
+
present: () => typeof api === "function",
|
|
460
|
+
onConsent(cb) {
|
|
461
|
+
if (typeof api !== "function") {
|
|
462
|
+
opts.onTimeout?.();
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
let fired = false;
|
|
466
|
+
const timer = setTimeoutFn(() => {
|
|
467
|
+
if (!fired) opts.onTimeout?.();
|
|
468
|
+
}, opts.timeoutMs ?? 2e3);
|
|
469
|
+
api("addEventListener", 2, (tcData, success) => {
|
|
470
|
+
if (!success || !tcData) return;
|
|
471
|
+
if (!tcData.eventStatus || READY_STATUSES.has(tcData.eventStatus)) {
|
|
472
|
+
fired = true;
|
|
473
|
+
clearTimeout(timer);
|
|
474
|
+
cb(tcData.purpose?.consents ?? {}, tcData.gdprApplies ?? true);
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// src/consent/tcf-purpose-signal-map.ts
|
|
482
|
+
function state(granted) {
|
|
483
|
+
return granted ? "granted" : "denied";
|
|
484
|
+
}
|
|
485
|
+
var g = (p, n) => p[n] === true;
|
|
486
|
+
function purposesToSignals(consents) {
|
|
487
|
+
return {
|
|
488
|
+
ad_storage: state(g(consents, 1)),
|
|
489
|
+
analytics_storage: state(g(consents, 1)),
|
|
490
|
+
ad_user_data: state(g(consents, 1) && g(consents, 7)),
|
|
491
|
+
ad_personalization: state(g(consents, 3) && g(consents, 4))
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// src/consent/vendor-map.ts
|
|
496
|
+
function vendorAllowed(vendor, signals) {
|
|
497
|
+
switch (vendor) {
|
|
498
|
+
case "gpt":
|
|
499
|
+
return signals.ad_storage === "granted";
|
|
500
|
+
case "ga4":
|
|
501
|
+
return signals.analytics_storage === "granted";
|
|
502
|
+
case "meta-pixel":
|
|
503
|
+
return signals.ad_storage === "granted";
|
|
504
|
+
default:
|
|
505
|
+
return signals.ad_storage === "granted";
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
function vendorDecisionMap(signals) {
|
|
509
|
+
return {
|
|
510
|
+
gpt: vendorAllowed("gpt", signals),
|
|
511
|
+
ga4: vendorAllowed("ga4", signals),
|
|
512
|
+
"meta-pixel": vendorAllowed("meta-pixel", signals)
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
function snapshotFor(signals, resolved) {
|
|
516
|
+
return {
|
|
517
|
+
signals,
|
|
518
|
+
resolved,
|
|
519
|
+
allows: (vendor) => vendorAllowed(vendor, signals)
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
function createConsentGate(deps = {}) {
|
|
523
|
+
const config = deps.config ?? {};
|
|
524
|
+
const consentMode = deps.consentMode ?? createConsentMode();
|
|
525
|
+
const tcfBridge = deps.tcfBridge ?? createTcfBridge(void 0, { timeoutMs: config.cmpTimeoutMs ?? 2e3 });
|
|
526
|
+
const defaults = config.defaults ?? CONSERVATIVE_CONSENT_DEFAULTS;
|
|
527
|
+
let current = snapshotFor(defaults, false);
|
|
528
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
529
|
+
let started = false;
|
|
530
|
+
consentMode.setDefaults(defaults);
|
|
531
|
+
function applySignals(signals) {
|
|
532
|
+
current = snapshotFor(signals, true);
|
|
533
|
+
consentMode.update(signals);
|
|
534
|
+
deps.bus?.emit({ type: "consent:changed", signals });
|
|
535
|
+
for (const l of [...listeners]) l(current);
|
|
536
|
+
}
|
|
537
|
+
return {
|
|
538
|
+
snapshot: () => current,
|
|
539
|
+
onChange(cb) {
|
|
540
|
+
listeners.add(cb);
|
|
541
|
+
return () => listeners.delete(cb);
|
|
542
|
+
},
|
|
543
|
+
start() {
|
|
544
|
+
if (started) return;
|
|
545
|
+
started = true;
|
|
546
|
+
tcfBridge.onConsent((consents) => {
|
|
547
|
+
applySignals(purposesToSignals(consents));
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// src/adapters/provider/gpt/define-slot.ts
|
|
554
|
+
function baseSizes(slot) {
|
|
555
|
+
const base = slot.sizeMapping?.find((m) => m.viewport[0] === 0 && m.viewport[1] === 0);
|
|
556
|
+
const sizes = base?.sizes ?? slot.sizeMapping?.[0]?.sizes ?? [];
|
|
557
|
+
return sizes.map(toGptSize);
|
|
558
|
+
}
|
|
559
|
+
function toGptSize(size) {
|
|
560
|
+
return size === "fluid" ? "fluid" : size;
|
|
561
|
+
}
|
|
562
|
+
function buildSizeMapping(gt, mapping) {
|
|
563
|
+
const builder = gt.sizeMapping();
|
|
564
|
+
for (const entry of mapping) {
|
|
565
|
+
builder.addSize(entry.viewport, entry.sizes.map(toGptSize));
|
|
566
|
+
}
|
|
567
|
+
return builder.build();
|
|
568
|
+
}
|
|
569
|
+
function defineDisplaySlot(gt, slot) {
|
|
570
|
+
const gptSlot = gt.defineSlot(slot.adUnitPath, baseSizes(slot), slot.id);
|
|
571
|
+
if (!gptSlot) return null;
|
|
572
|
+
if (slot.sizeMapping && slot.sizeMapping.length > 0) {
|
|
573
|
+
gptSlot.defineSizeMapping(buildSizeMapping(gt, slot.sizeMapping));
|
|
574
|
+
}
|
|
575
|
+
gptSlot.addService(gt.pubads());
|
|
576
|
+
return gptSlot;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// src/adapters/provider/gpt/oop-formats.ts
|
|
580
|
+
function oopFormatValue(gt, slot) {
|
|
581
|
+
const formats = gt.enums?.OutOfPageFormat ?? {};
|
|
582
|
+
switch (slot.format) {
|
|
583
|
+
case "anchor":
|
|
584
|
+
return slot.position === "bottom" ? formats["BOTTOM_ANCHOR"] : formats["TOP_ANCHOR"];
|
|
585
|
+
case "interstitial":
|
|
586
|
+
return formats["INTERSTITIAL"];
|
|
587
|
+
case "side-rail":
|
|
588
|
+
return slot.side === "right" ? formats["RIGHT_SIDE_RAIL"] : formats["LEFT_SIDE_RAIL"];
|
|
589
|
+
default:
|
|
590
|
+
return formats["INTERSTITIAL"];
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function defineOopSlot(gt, slot) {
|
|
594
|
+
const fmt = oopFormatValue(gt, slot);
|
|
595
|
+
const gptSlot = gt.defineOutOfPageSlot(slot.adUnitPath, fmt);
|
|
596
|
+
if (!gptSlot) return null;
|
|
597
|
+
gptSlot.addService(gt.pubads());
|
|
598
|
+
return gptSlot;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// src/adapters/provider/gpt/config-api.ts
|
|
602
|
+
function applyPageConfig(gt, dynamic) {
|
|
603
|
+
if (!dynamic) return;
|
|
604
|
+
const cfg = {};
|
|
605
|
+
if (dynamic.pageUrl) cfg["pageUrl"] = dynamic.pageUrl;
|
|
606
|
+
if (dynamic.privacy) cfg["privacyTreatments"] = dynamic.privacy;
|
|
607
|
+
if (Object.keys(cfg).length) gt.setConfig(cfg);
|
|
608
|
+
}
|
|
609
|
+
function applySlotConfig(slot, planSlot) {
|
|
610
|
+
const cfg = {};
|
|
611
|
+
const targeting = planSlot.dynamic?.targeting;
|
|
612
|
+
if (targeting && Object.keys(targeting).length) {
|
|
613
|
+
cfg["targeting"] = targeting;
|
|
614
|
+
}
|
|
615
|
+
if (planSlot.contentPause) {
|
|
616
|
+
cfg["adsenseAttributes"] = { content_pause: true };
|
|
617
|
+
}
|
|
618
|
+
if (Object.keys(cfg).length) slot.setConfig(cfg);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// src/adapters/provider/gpt/ppid.ts
|
|
622
|
+
function applyPpid(gt, ppid) {
|
|
623
|
+
if (!ppid) return;
|
|
624
|
+
gt.pubads().setPublisherProvidedId(ppid);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// src/adapters/provider/gpt/index.ts
|
|
628
|
+
var GPT_SRC = "https://securepubads.g.doubleclick.net/tag/js/gpt.js";
|
|
629
|
+
var GPT_HOST = "securepubads.g.doubleclick.net";
|
|
630
|
+
var V1_FORMATS = ["display", "native", "anchor", "interstitial", "side-rail", "oop"];
|
|
631
|
+
function createGptProvider(deps) {
|
|
632
|
+
const win = deps.win ?? window;
|
|
633
|
+
const entries = /* @__PURE__ */ new Map();
|
|
634
|
+
const lifecycleCbs = [];
|
|
635
|
+
let gptLoaded = false;
|
|
636
|
+
function gtCmd(fn) {
|
|
637
|
+
const gt = win.googletag = win.googletag ?? { cmd: [] };
|
|
638
|
+
gt.cmd.push(() => {
|
|
639
|
+
try {
|
|
640
|
+
fn(win.googletag);
|
|
641
|
+
} catch (err) {
|
|
642
|
+
deps.bus.emit({ type: "error", scope: "gpt", message: String(err), cause: err });
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
function loadGpt() {
|
|
647
|
+
if (gptLoaded || !deps.injector) return;
|
|
648
|
+
const hosts = deps.allowedHosts ?? [GPT_HOST];
|
|
649
|
+
const ok = deps.injector.inject(GPT_SRC, hosts, { key: "gpt.js" });
|
|
650
|
+
if (!ok) {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
gptLoaded = true;
|
|
654
|
+
}
|
|
655
|
+
function pagePpid() {
|
|
656
|
+
for (const { planSlot } of entries.values()) {
|
|
657
|
+
if (planSlot.dynamic?.ppid) return planSlot.dynamic.ppid;
|
|
658
|
+
}
|
|
659
|
+
return void 0;
|
|
660
|
+
}
|
|
661
|
+
function pageDynamic() {
|
|
662
|
+
for (const { planSlot } of entries.values()) {
|
|
663
|
+
if (planSlot.dynamic) return planSlot.dynamic;
|
|
664
|
+
}
|
|
665
|
+
return void 0;
|
|
666
|
+
}
|
|
667
|
+
return {
|
|
668
|
+
id: "gpt",
|
|
669
|
+
capabilities: () => V1_FORMATS,
|
|
670
|
+
bootStep(step) {
|
|
671
|
+
if (step === "disableInitialLoad") loadGpt();
|
|
672
|
+
gtCmd((gt) => {
|
|
673
|
+
const pubads = gt.pubads();
|
|
674
|
+
switch (step) {
|
|
675
|
+
case "disableInitialLoad":
|
|
676
|
+
pubads.disableInitialLoad();
|
|
677
|
+
break;
|
|
678
|
+
case "enableSingleRequest":
|
|
679
|
+
pubads.enableSingleRequest();
|
|
680
|
+
break;
|
|
681
|
+
case "collapseEmptyDivs":
|
|
682
|
+
pubads.collapseEmptyDivs();
|
|
683
|
+
break;
|
|
684
|
+
case "enableServices":
|
|
685
|
+
gt.enableServices();
|
|
686
|
+
pubads.addEventListener("slotRenderEnded", (e) => {
|
|
687
|
+
const ev = e;
|
|
688
|
+
const uid = findUidByElementId(ev.slot?.getSlotElementId?.());
|
|
689
|
+
for (const cb of lifecycleCbs) {
|
|
690
|
+
cb({ type: "rendered", uid: uid ?? "", isEmpty: !!ev.isEmpty });
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
break;
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
},
|
|
697
|
+
prepare(slot) {
|
|
698
|
+
let gptSlot = null;
|
|
699
|
+
const isOop = OOP_FORMATS.includes(slot.format);
|
|
700
|
+
gtCmd((gt) => {
|
|
701
|
+
gptSlot = isOop ? defineOopSlot(gt, slot) : defineDisplaySlot(gt, slot);
|
|
702
|
+
if (gptSlot) {
|
|
703
|
+
entries.set(slot.__uid, { planSlot: slot, gptSlot });
|
|
704
|
+
applySlotConfig(gptSlot, slot);
|
|
705
|
+
} else {
|
|
706
|
+
deps.bus.emit({ type: "warning", scope: "gpt", message: `slot ${slot.id} returned null (${slot.format})` });
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
return { uid: slot.__uid, slotId: slot.id, format: slot.format, native: () => entries.get(slot.__uid)?.gptSlot };
|
|
710
|
+
},
|
|
711
|
+
request(handles, opts) {
|
|
712
|
+
gtCmd((gt) => {
|
|
713
|
+
applyPpid(gt, pagePpid());
|
|
714
|
+
applyPageConfig(gt, pageDynamic());
|
|
715
|
+
const gptSlots = handles.map((h) => entries.get(h.uid)?.gptSlot).filter((s) => !!s);
|
|
716
|
+
if (gptSlots.length) gt.pubads().refresh(gptSlots, { changeCorrelator: opts.changeCorrelator });
|
|
717
|
+
});
|
|
718
|
+
},
|
|
719
|
+
display(handle) {
|
|
720
|
+
gtCmd((gt) => {
|
|
721
|
+
const entry = entries.get(handle.uid);
|
|
722
|
+
if (entry) gt.display(entry.gptSlot);
|
|
723
|
+
});
|
|
724
|
+
},
|
|
725
|
+
refresh(handles, opts) {
|
|
726
|
+
gtCmd((gt) => {
|
|
727
|
+
const gptSlots = handles.map((h) => entries.get(h.uid)?.gptSlot).filter((s) => !!s);
|
|
728
|
+
if (gptSlots.length) gt.pubads().refresh(gptSlots, { changeCorrelator: opts.changeCorrelator });
|
|
729
|
+
});
|
|
730
|
+
},
|
|
731
|
+
destroy(handles) {
|
|
732
|
+
gtCmd((gt) => {
|
|
733
|
+
const gptSlots = handles.map((h) => entries.get(h.uid)?.gptSlot).filter((s) => !!s);
|
|
734
|
+
if (gptSlots.length && gt.destroySlots) gt.destroySlots(gptSlots);
|
|
735
|
+
for (const h of handles) entries.delete(h.uid);
|
|
736
|
+
});
|
|
737
|
+
},
|
|
738
|
+
onLifecycle(cb) {
|
|
739
|
+
lifecycleCbs.push(cb);
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
function findUidByElementId(elementId) {
|
|
743
|
+
if (!elementId) return void 0;
|
|
744
|
+
for (const [uid, entry] of entries) {
|
|
745
|
+
if (entry.planSlot.id === elementId) return uid;
|
|
746
|
+
}
|
|
747
|
+
return void 0;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// src/adapters/tag-path/ga4.ts
|
|
752
|
+
var GTAG_HOST = "www.googletagmanager.com";
|
|
753
|
+
function createGa4Vendor(win = window) {
|
|
754
|
+
let initialized = false;
|
|
755
|
+
function ensureGtag2() {
|
|
756
|
+
if (typeof win.gtag === "function") return win.gtag;
|
|
757
|
+
win.dataLayer = win.dataLayer ?? [];
|
|
758
|
+
const gtag = (...args) => {
|
|
759
|
+
win.dataLayer.push(args);
|
|
760
|
+
};
|
|
761
|
+
win.gtag = gtag;
|
|
762
|
+
return gtag;
|
|
763
|
+
}
|
|
764
|
+
return {
|
|
765
|
+
id: "ga4",
|
|
766
|
+
kind: () => "analytics",
|
|
767
|
+
init(tag, ctx) {
|
|
768
|
+
if (initialized) return;
|
|
769
|
+
const src = `https://${GTAG_HOST}/gtag/js?id=${encodeURIComponent(tag.id)}`;
|
|
770
|
+
const ok = ctx.injector.inject(src, ctx.allowedHosts, { key: `ga4:${tag.id}` });
|
|
771
|
+
if (!ok) return;
|
|
772
|
+
const gtag = ensureGtag2();
|
|
773
|
+
gtag("js", /* @__PURE__ */ new Date());
|
|
774
|
+
gtag("config", tag.id);
|
|
775
|
+
initialized = true;
|
|
776
|
+
ctx.bus.emit({ type: "vendor:event", vendor: "ga4", name: "config", payload: { id: tag.id } });
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// src/adapters/tag-path/meta-pixel.ts
|
|
782
|
+
var FB_SRC = "https://connect.facebook.net/en_US/fbevents.js";
|
|
783
|
+
function createMetaPixelVendor(win = window) {
|
|
784
|
+
let initialized = false;
|
|
785
|
+
function ensureFbq() {
|
|
786
|
+
if (typeof win.fbq === "function") return win.fbq;
|
|
787
|
+
const fbq = function(...args) {
|
|
788
|
+
if (fbq.callMethod) fbq.callMethod(...args);
|
|
789
|
+
else fbq.queue.push(args);
|
|
790
|
+
};
|
|
791
|
+
fbq.queue = [];
|
|
792
|
+
fbq.loaded = true;
|
|
793
|
+
fbq.version = "2.0";
|
|
794
|
+
win.fbq = fbq;
|
|
795
|
+
win._fbq = win._fbq ?? fbq;
|
|
796
|
+
return fbq;
|
|
797
|
+
}
|
|
798
|
+
return {
|
|
799
|
+
id: "meta-pixel",
|
|
800
|
+
kind: () => "analytics",
|
|
801
|
+
init(tag, ctx) {
|
|
802
|
+
if (initialized) return;
|
|
803
|
+
const ok = ctx.injector.inject(FB_SRC, ctx.allowedHosts, { key: `meta-pixel:${tag.id}` });
|
|
804
|
+
if (!ok) return;
|
|
805
|
+
const fbq = ensureFbq();
|
|
806
|
+
fbq("init", tag.id);
|
|
807
|
+
track(ctx, fbq, "PageView");
|
|
808
|
+
initialized = true;
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
function track(ctx, fbq, event, payload) {
|
|
812
|
+
fbq("track", event, payload);
|
|
813
|
+
ctx.bus.emit({ type: "vendor:event", vendor: "meta-pixel", name: event, payload });
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
function buildEngine(args) {
|
|
817
|
+
const win = args.win ?? (typeof window !== "undefined" ? window : void 0);
|
|
818
|
+
const doc = args.doc ?? (typeof document !== "undefined" ? document : void 0);
|
|
819
|
+
const bus = args.bus ?? createEventBus();
|
|
820
|
+
const injector = doc ? createTagInjector(bus, doc) : void 0;
|
|
821
|
+
const providerRegistry = createProviderRegistry();
|
|
822
|
+
if (injector) {
|
|
823
|
+
providerRegistry.register(
|
|
824
|
+
createGptProvider({ bus, injector, ...args.allowedHosts ? { allowedHosts: args.allowedHosts } : {}, win })
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
const adapterRegistry = createAdapterSlotRegistry();
|
|
828
|
+
if (win) {
|
|
829
|
+
adapterRegistry.register("ga4", createGa4Vendor(win));
|
|
830
|
+
adapterRegistry.register("meta-pixel", createMetaPixelVendor(win));
|
|
831
|
+
}
|
|
832
|
+
const consentGate = createConsentGate({ ...args.consent ? { config: args.consent } : {}, bus });
|
|
833
|
+
const engine = createAdsEngine({ providerRegistry, adapterRegistry, consentGate, injector, bus, win, doc });
|
|
834
|
+
return { engine, bus };
|
|
835
|
+
}
|
|
836
|
+
function assembleEngine(manifest, ctx, opts = {}) {
|
|
837
|
+
const allowedHosts = plan(manifest, ctx).allowedTagHosts;
|
|
838
|
+
return buildEngine({ allowedHosts, ...manifest.consent ? { consent: manifest.consent } : {}, ...opts });
|
|
839
|
+
}
|
|
840
|
+
function assembleEngineForPlacement(consent, opts = {}) {
|
|
841
|
+
return buildEngine({ ...consent ? { consent } : {}, ...opts });
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// src/wrappers/ads-client.ts
|
|
845
|
+
function resolveContext(partial, win) {
|
|
846
|
+
const w = win ?? (typeof window !== "undefined" ? window : void 0);
|
|
847
|
+
return {
|
|
848
|
+
url: partial?.url ?? w?.location?.href ?? "",
|
|
849
|
+
viewport: partial?.viewport ?? { w: w?.innerWidth ?? 1280, h: w?.innerHeight ?? 800 },
|
|
850
|
+
...partial?.dynamic ? { dynamic: partial.dynamic } : {}
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
async function fetchPlacement(src, ctx) {
|
|
854
|
+
const endpoint = src.endpoint ?? "/placement";
|
|
855
|
+
const res = await fetch(endpoint, {
|
|
856
|
+
method: "POST",
|
|
857
|
+
headers: { "content-type": "application/json" },
|
|
858
|
+
body: JSON.stringify({ siteUuid: src.siteUuid, context: ctx })
|
|
859
|
+
});
|
|
860
|
+
if (!res.ok) throw new Error(`placement ${res.status}`);
|
|
861
|
+
const data = await res.json();
|
|
862
|
+
return data.plan;
|
|
863
|
+
}
|
|
864
|
+
function createAdsClient(config) {
|
|
865
|
+
const ctx = resolveContext(config.context, config.wire?.win);
|
|
866
|
+
const wire = config.wire ?? {};
|
|
867
|
+
const { engine } = config.manifest !== void 0 ? assembleEngine(config.manifest, ctx, wire) : assembleEngineForPlacement(config.consent, wire);
|
|
868
|
+
let booted = false;
|
|
869
|
+
return {
|
|
870
|
+
async init() {
|
|
871
|
+
if (booted) return;
|
|
872
|
+
if (config.manifest !== void 0) {
|
|
873
|
+
engine.init(config.manifest, ctx);
|
|
874
|
+
} else if (config.placement) {
|
|
875
|
+
const plan3 = await fetchPlacement(config.placement, ctx);
|
|
876
|
+
engine.initFromPlan(plan3, ctx);
|
|
877
|
+
} else {
|
|
878
|
+
throw new Error("createAdsClient: provide `manifest` or `placement`");
|
|
879
|
+
}
|
|
880
|
+
booted = true;
|
|
881
|
+
},
|
|
882
|
+
showAds(id) {
|
|
883
|
+
if (id) engine.display(id);
|
|
884
|
+
},
|
|
885
|
+
setPageParams: (p) => engine.setPageParams(p),
|
|
886
|
+
setSlotParams: (id, p) => engine.setSlotParams(id, p),
|
|
887
|
+
refresh: (ids, opts) => engine.refresh(ids, opts),
|
|
888
|
+
display: (id) => engine.display(id),
|
|
889
|
+
destroy: () => {
|
|
890
|
+
engine.destroy();
|
|
891
|
+
booted = false;
|
|
892
|
+
},
|
|
893
|
+
on: (type, handler) => engine.on(type, handler),
|
|
894
|
+
getExecutedPlan: () => engine.getExecutedPlan()
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
export { BOOT_SPINE, assembleEngine, assembleEngineForPlacement, createAdapterSlotRegistry, createAdsClient, createAdsEngine, createAllowAllConsentGate, createConsentGate, createConsentMode, createEventBus, createGa4Vendor, createGptProvider, createLazyObserver, createMetaPixelVendor, createProviderRegistry, createSlotLifecycle, createTagInjector, createTcfBridge, dispatchTraits, purposesToSignals, vendorAllowed, vendorDecisionMap };
|
|
899
|
+
//# sourceMappingURL=chunk-GA4VEFSM.js.map
|
|
900
|
+
//# sourceMappingURL=chunk-GA4VEFSM.js.map
|