@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,352 @@
|
|
|
1
|
+
import { ConsentModeSignals, ManagedTag, ManagedTagType, SlotFormat, PlanSlot, Manifest, PlanContext, RenderPlan, DynamicParams, ConsentConfig } from '@hientran0208/ads-manifest';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Consent gate contract consumed by the gate chain (the real implementation lands
|
|
5
|
+
* in Phase 4). ONE snapshot gates BOTH paths (render + tag). The engine depends on
|
|
6
|
+
* this interface only — never on `__tcfapi`/`gtag`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
type VendorConsentId = "gpt" | "ga4" | "meta-pixel" | (string & {});
|
|
10
|
+
interface ConsentSnapshot {
|
|
11
|
+
signals: ConsentModeSignals;
|
|
12
|
+
/** Per-vendor allow/deny derived from the TCF→signal→vendor matrix. */
|
|
13
|
+
allows(vendor: VendorConsentId): boolean;
|
|
14
|
+
/** True once a real CMP signal has been read (vs conservative defaults). */
|
|
15
|
+
resolved: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface ConsentGate {
|
|
18
|
+
/** Synchronous conservative defaults — never blocks the fast-path. */
|
|
19
|
+
snapshot(): ConsentSnapshot;
|
|
20
|
+
/** Subscribe to mid-session consent changes (grant/deny). */
|
|
21
|
+
onChange(cb: (snap: ConsentSnapshot) => void): () => void;
|
|
22
|
+
/** Begin async CMP read (idempotent). */
|
|
23
|
+
start(): void;
|
|
24
|
+
}
|
|
25
|
+
/** Pass-through gate (everything allowed) — DI default for engine unit tests. */
|
|
26
|
+
declare function createAllowAllConsentGate(signals?: ConsentModeSignals): ConsentGate;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Typed pub/sub — where the two paths (render + tag) meet without coupling.
|
|
30
|
+
* The telemetry sink and (later) CAPI forwarder subscribe here; vendors emit
|
|
31
|
+
* normalized events. Synchronous delivery; a throwing handler is isolated so one
|
|
32
|
+
* bad subscriber cannot break dispatch.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
type EngineEvent = {
|
|
36
|
+
type: "slot:registered";
|
|
37
|
+
slotId: string;
|
|
38
|
+
uid: string;
|
|
39
|
+
} | {
|
|
40
|
+
type: "slot:requested";
|
|
41
|
+
slotId: string;
|
|
42
|
+
uid: string;
|
|
43
|
+
} | {
|
|
44
|
+
type: "slot:rendered";
|
|
45
|
+
slotId: string;
|
|
46
|
+
uid: string;
|
|
47
|
+
isEmpty: boolean;
|
|
48
|
+
} | {
|
|
49
|
+
type: "slot:empty";
|
|
50
|
+
slotId: string;
|
|
51
|
+
uid: string;
|
|
52
|
+
} | {
|
|
53
|
+
type: "slot:destroyed";
|
|
54
|
+
slotId: string;
|
|
55
|
+
uid: string;
|
|
56
|
+
} | {
|
|
57
|
+
type: "consent:changed";
|
|
58
|
+
signals: ConsentModeSignals;
|
|
59
|
+
} | {
|
|
60
|
+
type: "tag:injected";
|
|
61
|
+
host: string;
|
|
62
|
+
key: string;
|
|
63
|
+
} | {
|
|
64
|
+
type: "vendor:event";
|
|
65
|
+
vendor: string;
|
|
66
|
+
name: string;
|
|
67
|
+
payload?: unknown;
|
|
68
|
+
} | {
|
|
69
|
+
type: "error";
|
|
70
|
+
scope: string;
|
|
71
|
+
message: string;
|
|
72
|
+
cause?: unknown;
|
|
73
|
+
} | {
|
|
74
|
+
type: "warning";
|
|
75
|
+
scope: string;
|
|
76
|
+
message: string;
|
|
77
|
+
};
|
|
78
|
+
type EngineEventType = EngineEvent["type"];
|
|
79
|
+
type Handler<T extends EngineEventType = EngineEventType> = (ev: Extract<EngineEvent, {
|
|
80
|
+
type: T;
|
|
81
|
+
}>) => void;
|
|
82
|
+
interface EventBus {
|
|
83
|
+
on<T extends EngineEventType>(type: T, handler: Handler<T>): () => void;
|
|
84
|
+
emit(ev: EngineEvent): void;
|
|
85
|
+
}
|
|
86
|
+
declare function createEventBus(onHandlerError?: (err: unknown) => void): EventBus;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The SINGLE choke point for every external script — vendors AND gpt.js. Enforces a
|
|
90
|
+
* server-driven host allowlist (`plan.allowedTagHosts`), dedupes by key, and injects
|
|
91
|
+
* async-by-default (defer override). Nothing else in the SDK appends a <script>.
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
interface InjectOptions {
|
|
95
|
+
/** Dedupe key; a repeated key is a no-op. Defaults to the src URL. */
|
|
96
|
+
key?: string;
|
|
97
|
+
/** `false` → async (default); `true` → defer. */
|
|
98
|
+
defer?: boolean;
|
|
99
|
+
attrs?: Record<string, string>;
|
|
100
|
+
}
|
|
101
|
+
interface TagInjector {
|
|
102
|
+
/**
|
|
103
|
+
* Inject a <script src>. Rejects (emits `error`, returns false) if the src host
|
|
104
|
+
* is not in `allowedHosts`. Idempotent per key.
|
|
105
|
+
*/
|
|
106
|
+
inject(src: string, allowedHosts: string[], opts?: InjectOptions): boolean;
|
|
107
|
+
/** True if a key was already injected. */
|
|
108
|
+
has(key: string): boolean;
|
|
109
|
+
}
|
|
110
|
+
declare function createTagInjector(bus: EventBus, doc?: Document): TagInjector;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Tag-path vendor interface — a self-contained third-party script the SDK injects
|
|
114
|
+
* then steps back from (GA4, Meta Pixel in v1). Shape: `{ kind, init, teardown? }`.
|
|
115
|
+
* All script loading goes through the single TagInjector; vendors never inject
|
|
116
|
+
* directly.
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
type VendorKind = "analytics" | "identity" | "fraud";
|
|
120
|
+
interface VendorContext {
|
|
121
|
+
injector: TagInjector;
|
|
122
|
+
bus: EventBus;
|
|
123
|
+
/** Allowlisted hosts from `plan.allowedTagHosts`. */
|
|
124
|
+
allowedHosts: string[];
|
|
125
|
+
}
|
|
126
|
+
interface TagVendor {
|
|
127
|
+
readonly id: string;
|
|
128
|
+
kind(): VendorKind;
|
|
129
|
+
/** Inject + initialize the vendor for its manifest tag. Idempotent. */
|
|
130
|
+
init(tag: ManagedTag, ctx: VendorContext): void;
|
|
131
|
+
teardown?(): void;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Tag-path vendor registry, keyed by manifest tag type. Maps `managedTags[].type`
|
|
136
|
+
* → the vendor that injects it.
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
interface AdapterSlotRegistry {
|
|
140
|
+
register(type: ManagedTagType, vendor: TagVendor): void;
|
|
141
|
+
resolve(type: ManagedTagType): TagVendor | null;
|
|
142
|
+
all(): TagVendor[];
|
|
143
|
+
}
|
|
144
|
+
declare function createAdapterSlotRegistry(): AdapterSlotRegistry;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* The load-bearing boot order (sdk-sample SDK.md §7/§8). Reordering breaks Single
|
|
148
|
+
* Request Architecture or fires ads early — high-risk, locked by test.
|
|
149
|
+
*
|
|
150
|
+
* The engine drives these abstract steps in order; the render provider (GPT in v1)
|
|
151
|
+
* maps each to its concrete call (`disableInitialLoad` → `googletag.pubads()
|
|
152
|
+
* .disableInitialLoad()`, etc.). A future provider may map or no-op them.
|
|
153
|
+
*/
|
|
154
|
+
declare const BOOT_SPINE: readonly ["disableInitialLoad", "enableSingleRequest", "collapseEmptyDivs", "enableServices"];
|
|
155
|
+
type BootStep = (typeof BOOT_SPINE)[number];
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Neutral render-path provider interface — NOT GAM-centric. Built now (v1 ships one
|
|
159
|
+
* provider, GPT) so a 2nd provider needs no engine rework (sdk-sample: neutralize
|
|
160
|
+
* before the 2nd provider, else rework). The engine knows this contract, never
|
|
161
|
+
* `googletag`.
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
/** Opaque per-slot handle a provider returns from `prepare`. Engine treats as a token. */
|
|
165
|
+
interface ProviderHandle {
|
|
166
|
+
uid: string;
|
|
167
|
+
slotId: string;
|
|
168
|
+
format: SlotFormat;
|
|
169
|
+
/** Provider-private payload (e.g. the googletag Slot). Engine never inspects it. */
|
|
170
|
+
native?: unknown;
|
|
171
|
+
}
|
|
172
|
+
interface RequestOptions {
|
|
173
|
+
/** SPA nav → true (new page view); in-page refresh → false. Never a blanket default. */
|
|
174
|
+
changeCorrelator: boolean;
|
|
175
|
+
}
|
|
176
|
+
type ProviderLifecycleEvent = {
|
|
177
|
+
type: "rendered";
|
|
178
|
+
uid: string;
|
|
179
|
+
isEmpty: boolean;
|
|
180
|
+
} | {
|
|
181
|
+
type: "error";
|
|
182
|
+
uid?: string;
|
|
183
|
+
message: string;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* A render provider resolves slots for a set of formats. Resolution is per
|
|
187
|
+
* (format, binding) via the registry — not one global provider.
|
|
188
|
+
*/
|
|
189
|
+
interface RenderProvider {
|
|
190
|
+
readonly id: string;
|
|
191
|
+
/** Formats this provider can serve (capability negotiation). */
|
|
192
|
+
capabilities(): readonly SlotFormat[];
|
|
193
|
+
/** One ordered boot-spine step. The engine drives BOOT_SPINE order. */
|
|
194
|
+
bootStep(step: BootStep): void;
|
|
195
|
+
/**
|
|
196
|
+
* Define a slot. May return `null` when the format/viewport is unservable
|
|
197
|
+
* (e.g. interstitial OOP returns null) — the engine null-guards.
|
|
198
|
+
*/
|
|
199
|
+
prepare(slot: PlanSlot): ProviderHandle | null;
|
|
200
|
+
/** Batched request (preserve Single Request Architecture). */
|
|
201
|
+
request(handles: ProviderHandle[], opts: RequestOptions): void;
|
|
202
|
+
/** On-demand single display (interstitial / autoShow=false). */
|
|
203
|
+
display(handle: ProviderHandle): void;
|
|
204
|
+
/** Re-request already-defined slots (in-page refresh / consent-grant re-arm). */
|
|
205
|
+
refresh(handles: ProviderHandle[], opts: RequestOptions): void;
|
|
206
|
+
destroy(handles: ProviderHandle[]): void;
|
|
207
|
+
/** Subscribe to normalized provider lifecycle events. */
|
|
208
|
+
onLifecycle(cb: (ev: ProviderLifecycleEvent) => void): void;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Resolves a render provider per (format) — not one global provider. v1 registers
|
|
213
|
+
* one provider (GPT) covering all formats; the registry exists so a 2nd provider
|
|
214
|
+
* slots in without engine changes.
|
|
215
|
+
*/
|
|
216
|
+
|
|
217
|
+
interface ProviderRegistry {
|
|
218
|
+
register(provider: RenderProvider): void;
|
|
219
|
+
/** Provider that can serve `format`, or null if none. */
|
|
220
|
+
resolve(format: SlotFormat): RenderProvider | null;
|
|
221
|
+
all(): RenderProvider[];
|
|
222
|
+
}
|
|
223
|
+
declare function createProviderRegistry(): ProviderRegistry;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* IntersectionObserver wrapper for lazy slots. Fires `onEnter` once when a slot's
|
|
227
|
+
* element nears the viewport (`rootMargin`). SSR/no-IO guarded: if
|
|
228
|
+
* IntersectionObserver is absent, treats the slot as immediately visible.
|
|
229
|
+
*/
|
|
230
|
+
interface LazyObserver {
|
|
231
|
+
observe(el: Element, rootMargin: string, onEnter: () => void): void;
|
|
232
|
+
disconnect(): void;
|
|
233
|
+
}
|
|
234
|
+
declare function createLazyObserver(win?: Window): LazyObserver;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* The framework-agnostic AdsEngine — the brain that consumes a RenderPlan, runs the
|
|
238
|
+
* gate chain, drives both paths (render registry/dispatch + tag injector), manages
|
|
239
|
+
* epoch-keyed slot lifecycle, and exposes the dynamic-params API.
|
|
240
|
+
*
|
|
241
|
+
* It does NOT re-implement planning — it imports `plan()` from @hientran0208/ads-manifest.
|
|
242
|
+
* The parity gate (P5) asserts generation == execution against that one planner.
|
|
243
|
+
*/
|
|
244
|
+
|
|
245
|
+
interface AdsEngineDeps {
|
|
246
|
+
providerRegistry?: ProviderRegistry;
|
|
247
|
+
adapterRegistry?: AdapterSlotRegistry;
|
|
248
|
+
consentGate?: ConsentGate;
|
|
249
|
+
injector?: TagInjector;
|
|
250
|
+
lazyObserver?: LazyObserver;
|
|
251
|
+
bus?: EventBus;
|
|
252
|
+
win?: Window;
|
|
253
|
+
doc?: Document;
|
|
254
|
+
}
|
|
255
|
+
interface RefreshOptions {
|
|
256
|
+
/** SPA nav → new page view (correlator true, epoch bump); else in-page (false). */
|
|
257
|
+
newPageView?: boolean;
|
|
258
|
+
}
|
|
259
|
+
interface AdsEngine {
|
|
260
|
+
init(manifest: Manifest, ctx: PlanContext): void;
|
|
261
|
+
/**
|
|
262
|
+
* Approach C: boot directly from a server-resolved RenderPlan (the public
|
|
263
|
+
* `/placement` response) — no manifest needed. Used by publisher pages that are
|
|
264
|
+
* not operator-authenticated. Kill-switch/domain gating is the server's job here;
|
|
265
|
+
* consent is still driven client-side by the injected ConsentGate.
|
|
266
|
+
*/
|
|
267
|
+
initFromPlan(rp: RenderPlan, ctx: PlanContext, opts?: {
|
|
268
|
+
autoShow?: boolean;
|
|
269
|
+
}): void;
|
|
270
|
+
isBooted(): boolean;
|
|
271
|
+
setPageParams(p: DynamicParams): void;
|
|
272
|
+
setSlotParams(id: string, p: DynamicParams): void;
|
|
273
|
+
refresh(ids: string[] | null, opts?: RefreshOptions): void;
|
|
274
|
+
display(id: string): void;
|
|
275
|
+
destroy(): void;
|
|
276
|
+
on(type: EngineEvent["type"], handler: (ev: EngineEvent) => void): () => void;
|
|
277
|
+
/** Dev-only debug hook: the plan the engine actually executed (parity capture). */
|
|
278
|
+
getExecutedPlan(): RenderPlan | null;
|
|
279
|
+
readonly providerRegistry: ProviderRegistry;
|
|
280
|
+
readonly adapterRegistry: AdapterSlotRegistry;
|
|
281
|
+
}
|
|
282
|
+
declare function createAdsEngine(deps?: AdsEngineDeps): AdsEngine;
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Single assembly point used by ALL three public surfaces (IIFE / imperative /
|
|
286
|
+
* React) so dual-load behavior and wiring are identical everywhere (DRY). Registers
|
|
287
|
+
* the GPT provider + GA4/Meta-Pixel vendors + real ConsentGate into one engine.
|
|
288
|
+
*
|
|
289
|
+
* Two entry points: from a manifest (static fast-path) or from just a consent config
|
|
290
|
+
* (Approach-C placement path, where the plan arrives later from `/placement`).
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
interface AssembledEngine {
|
|
294
|
+
engine: AdsEngine;
|
|
295
|
+
bus: EventBus;
|
|
296
|
+
}
|
|
297
|
+
interface WireOptions {
|
|
298
|
+
win?: Window;
|
|
299
|
+
doc?: Document;
|
|
300
|
+
bus?: EventBus;
|
|
301
|
+
}
|
|
302
|
+
/** Build a wired (not booted) engine for a manifest + context (static fast-path). */
|
|
303
|
+
declare function assembleEngine(manifest: Manifest, ctx: PlanContext, opts?: WireOptions): AssembledEngine;
|
|
304
|
+
/**
|
|
305
|
+
* Build a wired engine for the Approach-C placement path — no manifest. The plan
|
|
306
|
+
* (and its allowedTagHosts) arrives later from `/placement`; vendors read the
|
|
307
|
+
* allowlist from that plan at arm time, and gpt.js uses the provider's default host.
|
|
308
|
+
*/
|
|
309
|
+
declare function assembleEngineForPlacement(consent: ConsentConfig | undefined, opts?: WireOptions): AssembledEngine;
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Imperative public surface: `createAdsClient({...})` → `await ads.init()`. Thin,
|
|
313
|
+
* idempotent wrapper over the assembled engine. Double-init is safe.
|
|
314
|
+
*
|
|
315
|
+
* Two modes:
|
|
316
|
+
* - **manifest** (static fast-path): pass `{ manifest }`.
|
|
317
|
+
* - **placement** (Approach C, publisher pages — no auth): pass
|
|
318
|
+
* `{ placement: { endpoint?, siteUuid } }`; init() POSTs to the public
|
|
319
|
+
* `/placement` endpoint and boots from the returned plan. Drive consent with the
|
|
320
|
+
* optional `consent` config (or a CMP on the page).
|
|
321
|
+
*/
|
|
322
|
+
|
|
323
|
+
interface PlacementSource {
|
|
324
|
+
/** Public placement endpoint. Defaults to same-origin `/placement`. */
|
|
325
|
+
endpoint?: string;
|
|
326
|
+
siteUuid: string;
|
|
327
|
+
}
|
|
328
|
+
interface AdsClientConfig {
|
|
329
|
+
/** Static fast-path: the inlined manifest. */
|
|
330
|
+
manifest?: Manifest;
|
|
331
|
+
/** Approach-C path: fetch the plan from `/placement` for this site. */
|
|
332
|
+
placement?: PlacementSource;
|
|
333
|
+
/** Consent config for the placement path (manifest mode reads manifest.consent). */
|
|
334
|
+
consent?: ConsentConfig;
|
|
335
|
+
/** Page context; defaults to the live window URL + viewport. */
|
|
336
|
+
context?: Partial<PlanContext>;
|
|
337
|
+
wire?: WireOptions;
|
|
338
|
+
}
|
|
339
|
+
interface AdsClient {
|
|
340
|
+
init(): Promise<void>;
|
|
341
|
+
showAds(id?: string): void;
|
|
342
|
+
setPageParams(p: DynamicParams): void;
|
|
343
|
+
setSlotParams(id: string, p: DynamicParams): void;
|
|
344
|
+
refresh(ids: string[] | null, opts?: RefreshOptions): void;
|
|
345
|
+
display(id: string): void;
|
|
346
|
+
destroy(): void;
|
|
347
|
+
on(type: EngineEvent["type"], handler: (ev: EngineEvent) => void): () => void;
|
|
348
|
+
getExecutedPlan(): RenderPlan | null;
|
|
349
|
+
}
|
|
350
|
+
declare function createAdsClient(config: AdsClientConfig): AdsClient;
|
|
351
|
+
|
|
352
|
+
export { type AdsClient as A, BOOT_SPINE as B, type ConsentGate as C, createTagInjector as D, type EngineEvent as E, type InjectOptions as I, type LazyObserver as L, type ProviderHandle as P, type RenderProvider as R, type TagInjector as T, type VendorConsentId as V, type WireOptions as W, type EventBus as a, type TagVendor as b, type PlacementSource as c, type AdapterSlotRegistry as d, type AdsClientConfig as e, type AdsEngine as f, type AdsEngineDeps as g, type AssembledEngine as h, type BootStep as i, type ConsentSnapshot as j, type EngineEventType as k, type ProviderLifecycleEvent as l, type ProviderRegistry as m, type RefreshOptions as n, type RequestOptions as o, type VendorContext as p, type VendorKind as q, assembleEngine as r, assembleEngineForPlacement as s, createAdapterSlotRegistry as t, createAdsClient as u, createAdsEngine as v, createAllowAllConsentGate as w, createEventBus as x, createLazyObserver as y, createProviderRegistry as z };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var AdsSDK=(function(exports){'use strict';var h=["anchor","interstitial","side-rail","oop"],V="23174336345";var G={ad_storage:"denied",analytics_storage:"denied",ad_user_data:"denied",ad_personalization:"denied"};function be(e,t,n){let o=e.networkCode?.trim()||V,r=e.siteDomain?.trim();return r?`/${o}/${r}/${r}_${n}`:`/${o}/${t}/${n}`}function he(e){return {mode:"v2",assumed:e?.assumed??false,defaults:e?.defaults??G,cmpTimeoutMs:e?.cmpTimeoutMs??2e3}}function we(e,t,n){let o=h.includes(e.format),r=e.adUnitPath??be(t,n,e.id);return o?{id:e.id,format:e.format,adUnitPath:r,...e.position?{position:e.position}:{},...e.side?{side:e.side}:{},...e.minViewport?{minViewport:e.minViewport}:{},...e.availableOn?{availableOn:e.availableOn}:{}}:{...e,adUnitPath:r,loading:e.loading??"eager",collapse:e.collapse??true,refresh:e.refresh??{enabled:false},sizeMapping:e.sizeMapping??[]}}function j(e){let t=e.gam??{},n={networkCode:t.networkCode?.trim()||V,...t.siteDomain?{siteDomain:t.siteDomain.trim()}:{}};return {...e,version:e.version??1,injection:e.injection??"head",autoShow:e.autoShow??true,killed:e.killed??false,gam:n,consent:he(e.consent),allowDomains:e.allowDomains??[],managedTags:e.managedTags??[],video:e.video??[],placeholders:(e.placeholders??[]).map(o=>we(o,n,e.publisherId))}}var Pe=["securepubads.g.doubleclick.net","www.googletagservices.com"],Ce={ga4:["www.googletagmanager.com"],"meta-pixel":["connect.facebook.net"]};function Te(e,t){let n=`${e}|${t}`,o=5381;for(let r=0;r<n.length;r++)o=(o<<5)+o+n.charCodeAt(r)>>>0;return `u${o.toString(36)}`}function Ee(e,t){if(!e.minViewport)return false;let[n,o]=e.minViewport;return t.w<n||t.h<o}function Ae(e,t){if(!t)return;let n={};return t.targeting&&(n.targeting=t.targeting),t.ppid!==void 0&&(n.ppid=t.ppid),t.privacy&&(n.privacy=t.privacy),t.pageUrl!==void 0&&(n.pageUrl=t.pageUrl),t.changeCorrelator!==void 0&&(n.changeCorrelator=t.changeCorrelator),Object.keys(n).length>0?n:void 0}function _e(e,t){let n=e.adUnitPath,o=h.includes(e.format),r=Ae(e.id,t.dynamic),i={id:e.id,format:e.format,adUnitPath:n,__uid:Te(e.id,n)};return o?(e.position&&(i.position=e.position),e.side&&(i.side=e.side)):(e.sizeMapping&&(i.sizeMapping=e.sizeMapping),e.loading&&(i.loading=e.loading),e.rootMargin&&(i.rootMargin=e.rootMargin),e.contentPause!==void 0&&(i.contentPause=e.contentPause),e.collapse!==void 0&&(i.collapse=e.collapse),e.refresh&&(i.refresh=e.refresh)),r&&(i.dynamic=r),i}function xe(e){let t=new Set(Pe);for(let n of e)for(let o of Ce[n.type]??[])t.add(o);return [...t].sort()}function C(e,t){let n=j(e);return {slots:n.placeholders.filter(r=>!Ee(r,t.viewport)).map(r=>_e(r,t)),managedTags:n.managedTags,video:n.video,allowedTagHosts:xe(n.managedTags)}}var ke=[".trycloudflare.com",".pages.dev",".workers.dev",".ngrok.io",".ngrok-free.app",".loca.lt",".local"],Oe=["localhost","127.0.0.1"];function R(e){return e.trim().toLowerCase().replace(/\.$/,"")}function Me(e){let t=R(e);return Oe.includes(t)?true:ke.some(n=>t.endsWith(n))}function q(e,t){let n=R(e);return Me(n)||!t||t.length===0?true:t.some(o=>{let r=R(o);if(!r)return false;if(r.startsWith(".")){let i=r.slice(1);return n===i||n.endsWith(r)}return n===r})}var $=["disableInitialLoad","enableSingleRequest","collapseEmptyDivs","enableServices"];function U(e){let t={signals:{ad_storage:"granted",analytics_storage:"granted",ad_user_data:"granted",ad_personalization:"granted"},allows:()=>true,resolved:true};return {snapshot:()=>t,onChange:()=>()=>{},start:()=>{}}}function W(){let e={page:{},perSlot:new Map,setPage(t){e.page={...e.page,...t};},setSlot(t,n){e.perSlot.set(t,{...e.perSlot.get(t)??{},...n});},resolved(t){let n=t?e.perSlot.get(t):void 0;return {...e.page,...n??{}}}};return e}function E(e){let t=new Map;return {on(n,o){let r=t.get(n);return r||(r=new Set,t.set(n,r)),r.add(o),()=>r.delete(o)},emit(n){let o=t.get(n.type);if(o)for(let r of [...o])try{r(n);}catch(i){}}}}function D(e){let t=h.includes(e);return e==="interstitial"?{usesDiv:false,ridesEagerBatch:false,onDemandOnly:true,refreshable:false}:t?{usesDiv:false,ridesEagerBatch:true,onDemandOnly:false,refreshable:false}:{usesDiv:true,ridesEagerBatch:true,onDemandOnly:false,refreshable:true}}function N(e){let{manifest:t,bus:n,hostname:o}=e;return t.killed?(n.emit({type:"warning",scope:"gate:kill",message:"kill switch active"}),{ok:false,gate:"kill",reason:"killed"}):q(o,t.allowDomains)?{ok:true}:(n.emit({type:"error",scope:"gate:domain",message:`host not allowed: ${o}`}),{ok:false,gate:"domain",reason:"domain_not_allowed"})}function A(){let e=new Map;return {register(t,n){e.set(t,n);},resolve(t){return e.get(t)??null},all(){return [...e.values()]}}}function _(){let e=[];return {register(t){e.push(t);},resolve(t){return e.find(n=>n.capabilities().includes(t))??null},all(){return [...e]}}}var Re={registered:["gated","destroyed"],gated:["requested","destroyed"],requested:["rendered","destroyed"],rendered:["requested","destroyed"],destroyed:[]};function K(){let e=new Map;return {register(t,n){let o={slot:t,handle:null,state:"registered",epoch:n};return e.set(t.__uid,o),o},get(t){return e.get(t)},all(){return [...e.values()]},transition(t,n){let o=e.get(t);return !o||!Re[o.state].includes(n)?false:(o.state=n,true)},attachHandle(t,n){let o=e.get(t);o&&(o.handle=n);},isCurrent(t,n){let o=e.get(t);return !!o&&o.epoch===n&&o.state!=="destroyed"},destroyAll(){for(let t of e.values())t.state="destroyed";e.clear();}}}function Ge(e){try{return new URL(e,"https://invalid.local").hostname}catch{return null}}function x(e,t=document){let n=new Set;return {has(o){return n.has(o)},inject(o,r,i={}){let d=i.key??o;if(n.has(d))return true;let c=Ge(o);if(!c||!r.includes(c))return e.emit({type:"error",scope:"tag-injector",message:`blocked script from disallowed host: ${c??o}`}),false;let m=t.createElement("script");m.src=o,i.defer?m.defer=true:m.async=true;for(let[y,a]of Object.entries(i.attrs??{}))m.setAttribute(y,a);return (t.head??t.documentElement).appendChild(m),n.add(d),e.emit({type:"tag:injected",host:c,key:d}),true}}}function Y(e=window){let t=[],n=e.IntersectionObserver;return {observe(o,r,i){if(!n){i();return}let d=new n((c,m)=>{for(let y of c)y.isIntersecting&&(m.disconnect(),i());},{rootMargin:r});d.observe(o),t.push(d);},disconnect(){for(let o of t)o.disconnect();t.length=0;}}}var I="__adsEngine";function J(e={}){let t=e.win??(typeof window<"u"?window:void 0),n=e.doc??(typeof document<"u"?document:void 0),o=e.bus??E(),r=e.providerRegistry??_(),i=e.adapterRegistry??A(),d=e.consentGate??U(),c=e.injector??(n?x(o,n):void 0),m=e.lazyObserver??(t?Y(t):void 0),y=W(),a=K(),u=false,f=0,p=null,S=null;function T(s){let l=p.ctx,v={...y.resolved()};return s!==void 0&&(v.changeCorrelator=s),{url:v.pageUrl??l.url,viewport:l.viewport,...Object.keys(v).length?{dynamic:v}:{}}}function O(s){for(let l of s.slots){let g=r.resolve(l.format);if(!g){o.emit({type:"warning",scope:"dispatch",message:`no provider for format ${l.format}`});continue}a.register(l,f);o.emit({type:"slot:registered",slotId:l.id,uid:l.__uid});let P=g.prepare(l);a.attachHandle(l.__uid,P),a.transition(l.__uid,"gated");}}function H(){return a.all().filter(s=>s.handle&&D(s.slot.format).ridesEagerBatch&&s.slot.loading!=="lazy").map(s=>s.handle).filter(Boolean)}function M(s,l){if(s.length){for(let g of s){let v=a.get(g.uid);v&&a.transition(g.uid,"requested")&&o.emit({type:"slot:requested",slotId:v.slot.id,uid:g.uid});}r.all()[0]?.request(s,{changeCorrelator:l});}}function ve(){for(let s of a.all()){if(s.slot.loading!=="lazy"||!s.handle)continue;let l=n?.getElementById(s.slot.id)??void 0,g=()=>{d.snapshot().allows("gpt")&&M([s.handle],false);};m&&l?m.observe(l,s.slot.rootMargin??"0px",g):m&&!l&&m.observe(n.body,s.slot.rootMargin??"0px",g);}}function L(){if(!(!p||!c))for(let s of p.plan.managedTags){let l=i.resolve(s.type);l&&d.snapshot().allows(s.type)&&l.init(s,{injector:c,bus:o,allowedHosts:p.plan.allowedTagHosts});}}function B(s,l){for(let g of r.all())for(let v of $)g.bootStep(v);O(s),u=true,d.start(),S=d.onChange(()=>Se()),L(),l&&d.snapshot().allows("gpt")&&(M(H(),false),ve());}function F(){return t&&t[I]?(o.emit({type:"warning",scope:"dual-load",message:"an AdsEngine already booted on this page; ignoring second init"}),false):(t&&(t[I]=true),true)}function Se(){if(!(!u||!p)&&(L(),d.snapshot().allows("gpt"))){let s=H().filter(l=>{let g=a.get(l.uid);return g&&g.state!=="requested"});M(s,false);}}return {providerRegistry:r,adapterRegistry:i,isBooted:()=>u,getExecutedPlan:()=>p?.plan??null,on:(s,l)=>o.on(s,l),init(s,l){if(!F())return;let g=j(s),v=t?.location?.hostname??new URL(l.url).hostname;if(!N({manifest:g,bus:o,hostname:v}).ok){u=false;return}p={manifest:s,ctx:l,plan:{slots:[],managedTags:[],video:[],allowedTagHosts:[]}},p.plan=C(s,T()),B(p.plan,g.autoShow);},initFromPlan(s,l,g={}){F()&&(p={ctx:l,plan:s},B(s,g.autoShow??true));},setPageParams(s){y.setPage(s);},setSlotParams(s,l){y.setSlot(s,l);},refresh(s,l={}){if(!u||!p)return;let g=l.newPageView??false;g&&(f+=1),p.manifest&&(p={...p,plan:C(p.manifest,T(g))});let v=s&&s.length?a.all().filter(b=>s.includes(b.slot.id)&&b.handle):a.all().filter(b=>b.handle&&D(b.slot.format).refreshable),P=v.map(b=>b.handle).filter(Boolean);if(P.length){for(let b of v)a.transition(b.slot.__uid,"requested");r.all()[0]?.refresh(P,{changeCorrelator:g});}},display(s){if(!u)return;let l=a.all().find(g=>g.slot.id===s);l?.handle&&d.snapshot().allows("gpt")&&r.all()[0]?.display(l.handle);},destroy(){S?.(),m?.disconnect();for(let s of r.all()){let l=a.all().map(g=>g.handle).filter(Boolean);l.length&&s.destroy(l);}a.destroyAll(),u=false,p=null,t&&delete t[I];}}}function je(e){return (e.sizeMapping?.find(o=>o.viewport[0]===0&&o.viewport[1]===0)?.sizes??e.sizeMapping?.[0]?.sizes??[]).map(X)}function X(e){return e==="fluid"?"fluid":e}function De(e,t){let n=e.sizeMapping();for(let o of t)n.addSize(o.viewport,o.sizes.map(X));return n.build()}function Q(e,t){let n=e.defineSlot(t.adUnitPath,je(t),t.id);return n?(t.sizeMapping&&t.sizeMapping.length>0&&n.defineSizeMapping(De(e,t.sizeMapping)),n.addService(e.pubads()),n):null}function Ie(e,t){let n=e.enums?.OutOfPageFormat??{};switch(t.format){case "anchor":return t.position==="bottom"?n.BOTTOM_ANCHOR:n.TOP_ANCHOR;case "interstitial":return n.INTERSTITIAL;case "side-rail":return t.side==="right"?n.RIGHT_SIDE_RAIL:n.LEFT_SIDE_RAIL;default:return n.INTERSTITIAL}}function Z(e,t){let n=Ie(e,t),o=e.defineOutOfPageSlot(t.adUnitPath,n);return o?(o.addService(e.pubads()),o):null}function ee(e,t){if(!t)return;let n={};t.pageUrl&&(n.pageUrl=t.pageUrl),t.privacy&&(n.privacyTreatments=t.privacy),Object.keys(n).length&&e.setConfig(n);}function te(e,t){let n={},o=t.dynamic?.targeting;o&&Object.keys(o).length&&(n.targeting=o),t.contentPause&&(n.adsenseAttributes={content_pause:true}),Object.keys(n).length&&e.setConfig(n);}function ne(e,t){t&&e.pubads().setPublisherProvidedId(t);}var ze="https://securepubads.g.doubleclick.net/tag/js/gpt.js",He="securepubads.g.doubleclick.net",Le=["display","native","anchor","interstitial","side-rail","oop"];function oe(e){let t=e.win??window,n=new Map,o=[],r=false;function i(a){(t.googletag=t.googletag??{cmd:[]}).cmd.push(()=>{try{a(t.googletag);}catch(f){e.bus.emit({type:"error",scope:"gpt",message:String(f),cause:f});}});}function d(){if(r||!e.injector)return;let a=e.allowedHosts??[He];e.injector.inject(ze,a,{key:"gpt.js"})&&(r=true);}function c(){for(let{planSlot:a}of n.values())if(a.dynamic?.ppid)return a.dynamic.ppid}function m(){for(let{planSlot:a}of n.values())if(a.dynamic)return a.dynamic}return {id:"gpt",capabilities:()=>Le,bootStep(a){a==="disableInitialLoad"&&d(),i(u=>{let f=u.pubads();switch(a){case "disableInitialLoad":f.disableInitialLoad();break;case "enableSingleRequest":f.enableSingleRequest();break;case "collapseEmptyDivs":f.collapseEmptyDivs();break;case "enableServices":u.enableServices(),f.addEventListener("slotRenderEnded",p=>{let S=p,T=y(S.slot?.getSlotElementId?.());for(let O of o)O({type:"rendered",uid:T??"",isEmpty:!!S.isEmpty});});break}});},prepare(a){let u=null,f=h.includes(a.format);return i(p=>{u=f?Z(p,a):Q(p,a),u?(n.set(a.__uid,{planSlot:a,gptSlot:u}),te(u,a)):e.bus.emit({type:"warning",scope:"gpt",message:`slot ${a.id} returned null (${a.format})`});}),{uid:a.__uid,slotId:a.id,format:a.format,native:()=>n.get(a.__uid)?.gptSlot}},request(a,u){i(f=>{ne(f,c()),ee(f,m());let p=a.map(S=>n.get(S.uid)?.gptSlot).filter(S=>!!S);p.length&&f.pubads().refresh(p,{changeCorrelator:u.changeCorrelator});});},display(a){i(u=>{let f=n.get(a.uid);f&&u.display(f.gptSlot);});},refresh(a,u){i(f=>{let p=a.map(S=>n.get(S.uid)?.gptSlot).filter(S=>!!S);p.length&&f.pubads().refresh(p,{changeCorrelator:u.changeCorrelator});});},destroy(a){i(u=>{let f=a.map(p=>n.get(p.uid)?.gptSlot).filter(p=>!!p);f.length&&u.destroySlots&&u.destroySlots(f);for(let p of a)n.delete(p.uid);});},onLifecycle(a){o.push(a);}};function y(a){if(a){for(let[u,f]of n)if(f.planSlot.id===a)return u}}}var Be="www.googletagmanager.com";function re(e=window){let t=false;function n(){if(typeof e.gtag=="function")return e.gtag;e.dataLayer=e.dataLayer??[];let o=(...r)=>{e.dataLayer.push(r);};return e.gtag=o,o}return {id:"ga4",kind:()=>"analytics",init(o,r){if(t)return;let i=`https://${Be}/gtag/js?id=${encodeURIComponent(o.id)}`;if(!r.injector.inject(i,r.allowedHosts,{key:`ga4:${o.id}`}))return;let c=n();c("js",new Date),c("config",o.id),t=true,r.bus.emit({type:"vendor:event",vendor:"ga4",name:"config",payload:{id:o.id}});}}}var Fe="https://connect.facebook.net/en_US/fbevents.js";function ie(e=window){let t=false;function n(){if(typeof e.fbq=="function")return e.fbq;let r=function(...i){r.callMethod?r.callMethod(...i):r.queue.push(i);};return r.queue=[],r.loaded=true,r.version="2.0",e.fbq=r,e._fbq=e._fbq??r,r}return {id:"meta-pixel",kind:()=>"analytics",init(r,i){if(t||!i.injector.inject(Fe,i.allowedHosts,{key:`meta-pixel:${r.id}`}))return;let c=n();c("init",r.id),o(i,c,"PageView"),t=true;}};function o(r,i,d,c){i("track",d,c),r.bus.emit({type:"vendor:event",vendor:"meta-pixel",name:d,payload:c});}}function ae(e){if(typeof e.gtag=="function")return e.gtag;e.dataLayer=e.dataLayer??[];let t=(...n)=>{e.dataLayer.push(n);};return e.gtag=t,t}function se(e=window){let t=false;return {defaultsSet:()=>t,setDefaults(n){ae(e)("consent","default",{...n,wait_for_update:500}),t=true;},update(n){ae(e)("consent","update",{...n});}}}var Ve=new Set(["tcloaded","useractioncomplete"]);function de(e=window,t={}){let n=e.__tcfapi,o=t.setTimeoutFn??setTimeout;return {present:()=>typeof n=="function",onConsent(r){if(typeof n!="function"){t.onTimeout?.();return}let i=false,d=o(()=>{i||t.onTimeout?.();},t.timeoutMs??2e3);n("addEventListener",2,(c,m)=>{!m||!c||(!c.eventStatus||Ve.has(c.eventStatus))&&(i=true,clearTimeout(d),r(c.purpose?.consents??{},c.gdprApplies??true));});}}}function k(e){return e?"granted":"denied"}var w=(e,t)=>e[t]===true;function le(e){return {ad_storage:k(w(e,1)),analytics_storage:k(w(e,1)),ad_user_data:k(w(e,1)&&w(e,7)),ad_personalization:k(w(e,3)&&w(e,4))}}function ce(e,t){switch(e){case "gpt":return t.ad_storage==="granted";case "ga4":return t.analytics_storage==="granted";case "meta-pixel":return t.ad_storage==="granted";default:return t.ad_storage==="granted"}}function pe(e,t){return {signals:e,resolved:t,allows:n=>ce(n,e)}}function ue(e={}){let t=e.config??{},n=e.consentMode??se(),o=e.tcfBridge??de(void 0,{timeoutMs:t.cmpTimeoutMs??2e3}),r=t.defaults??G,i=pe(r,false),d=new Set,c=false;n.setDefaults(r);function m(y){i=pe(y,true),n.update(y),e.bus?.emit({type:"consent:changed",signals:y});for(let a of [...d])a(i);}return {snapshot:()=>i,onChange(y){return d.add(y),()=>d.delete(y)},start(){c||(c=true,o.onConsent(y=>{m(le(y));}));}}}function ge(e){let t=e.win??(typeof window<"u"?window:void 0),n=e.doc??(typeof document<"u"?document:void 0),o=e.bus??E(),r=n?x(o,n):void 0,i=_();r&&i.register(oe({bus:o,injector:r,...e.allowedHosts?{allowedHosts:e.allowedHosts}:{},win:t}));let d=A();t&&(d.register("ga4",re(t)),d.register("meta-pixel",ie(t)));let c=ue({...e.consent?{config:e.consent}:{},bus:o});return {engine:J({providerRegistry:i,adapterRegistry:d,consentGate:c,injector:r,bus:o,win:t,doc:n}),bus:o}}function fe(e,t,n={}){let o=C(e,t).allowedTagHosts;return ge({allowedHosts:o,...e.consent?{consent:e.consent}:{},...n})}function me(e,t={}){return ge({...e?{consent:e}:{},...t})}function qe(e,t){let n=t??(typeof window<"u"?window:void 0);return {url:e?.url??n?.location?.href??"",viewport:e?.viewport??{w:n?.innerWidth??1280,h:n?.innerHeight??800},...e?.dynamic?{dynamic:e.dynamic}:{}}}async function $e(e,t){let n=e.endpoint??"/placement",o=await fetch(n,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({siteUuid:e.siteUuid,context:t})});if(!o.ok)throw new Error(`placement ${o.status}`);return (await o.json()).plan}function ye(e){let t=qe(e.context,e.wire?.win),n=e.wire??{},{engine:o}=e.manifest!==void 0?fe(e.manifest,t,n):me(e.consent,n),r=false;return {async init(){if(!r){if(e.manifest!==void 0)o.init(e.manifest,t);else if(e.placement){let i=await $e(e.placement,t);o.initFromPlan(i,t);}else throw new Error("createAdsClient: provide `manifest` or `placement`");r=true;}},showAds(i){i&&o.display(i);},setPageParams:i=>o.setPageParams(i),setSlotParams:(i,d)=>o.setSlotParams(i,d),refresh:(i,d)=>o.refresh(i,d),display:i=>o.display(i),destroy:()=>{o.destroy(),r=false;},on:(i,d)=>o.on(i,d),getExecutedPlan:()=>o.getExecutedPlan()}}function Ue(e){let t={};if(!e)return {dynamic:t};let n=m=>e.getAttribute(m),o=n("data-targeting");if(o)try{t.targeting=JSON.parse(o);}catch{}let r=n("data-ppid");r&&(t.ppid=r);let i=n("data-page-url");i&&(t.pageUrl=i);let d=n("data-privacy");if(d)try{t.privacy=JSON.parse(d);}catch{}let c=n("data-change-correlator");return c!=null&&(t.changeCorrelator=c==="true"),{dynamic:t,...i?{pageUrl:i}:{}}}function z(e=window){let t=e.AdsSDK;if(t&&t.client)return t;let n=t?.cmd,o=Array.isArray(n)?[...n]:[],r={cmd:{push(i){r.client?i(r.client):o.push(i);}},async init(i){let d=e.document?.currentScript??e.document?.querySelector("script[data-ads-sdk]"),c=Ue(d),m={...i.context??{},dynamic:{...i.context?.dynamic??{},...c.dynamic}},y=ye({...i.manifest!==void 0?{manifest:i.manifest}:{},...i.placement?{placement:i.placement}:{},...i.consent?{consent:i.consent}:{},context:m,wire:{win:e}});await y.init(),r.client=y;for(let a of o.splice(0))a(y);}};return e.AdsSDK=r,r}typeof window<"u"&&z(window);
|
|
2
|
+
exports.installAdsSdk=z;return exports;})({});//# sourceMappingURL=ads-sa.global.js.map
|
|
3
|
+
//# sourceMappingURL=ads-sa.global.js.map
|