@particle-academy/fancy-pixel 0.1.0 → 0.2.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 +73 -8
- package/dist/fancy-pixel.global.min.js +9 -9
- package/dist/fancy-pixel.global.min.js.map +1 -1
- package/dist/index.cjs +483 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +56 -4
- package/dist/index.d.ts +56 -4
- package/dist/index.js +482 -2
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,463 @@ function sendPixelBeacon(endpoint, payload) {
|
|
|
31
31
|
return false;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// node_modules/@particle-academy/fancy-heuristics-js/dist/chunk-3XXNC3HT.js
|
|
35
|
+
function base(kind, actor, path, ts) {
|
|
36
|
+
return { kind, actor, path, ts };
|
|
37
|
+
}
|
|
38
|
+
function buildPageview(path, ts, actor = "human") {
|
|
39
|
+
return base("pageview", actor, path, ts);
|
|
40
|
+
}
|
|
41
|
+
function buildClick(args) {
|
|
42
|
+
const e = base("click", args.actor ?? "human", args.path, args.ts);
|
|
43
|
+
e.x = args.x;
|
|
44
|
+
e.y = args.y;
|
|
45
|
+
e.vw = args.vw;
|
|
46
|
+
e.vh = args.vh;
|
|
47
|
+
if (args.targetId !== void 0) e.targetId = args.targetId;
|
|
48
|
+
if (args.label !== void 0) e.label = args.label;
|
|
49
|
+
if (args.meta !== void 0) e.meta = args.meta;
|
|
50
|
+
return e;
|
|
51
|
+
}
|
|
52
|
+
function buildScroll(args) {
|
|
53
|
+
const e = base("scroll", args.actor ?? "human", args.path, args.ts);
|
|
54
|
+
e.scrollPct = args.scrollPct;
|
|
55
|
+
return e;
|
|
56
|
+
}
|
|
57
|
+
function buildPointer(args) {
|
|
58
|
+
const e = base("pointer", args.actor ?? "human", args.path, args.ts);
|
|
59
|
+
e.x = args.x;
|
|
60
|
+
e.y = args.y;
|
|
61
|
+
e.vw = args.vw;
|
|
62
|
+
e.vh = args.vh;
|
|
63
|
+
return e;
|
|
64
|
+
}
|
|
65
|
+
function buildDwell(args) {
|
|
66
|
+
const e = base("dwell", args.actor ?? "human", args.path, args.ts);
|
|
67
|
+
e.dwellMs = args.dwellMs;
|
|
68
|
+
return e;
|
|
69
|
+
}
|
|
70
|
+
function scrollPercent(scrollTop, scrollable) {
|
|
71
|
+
if (scrollable <= 0) return 100;
|
|
72
|
+
const pct = scrollTop / scrollable * 100;
|
|
73
|
+
if (pct <= 0) return 0;
|
|
74
|
+
if (pct >= 100) return 100;
|
|
75
|
+
return Math.round(pct);
|
|
76
|
+
}
|
|
77
|
+
function mapActivityToEvent(e, path) {
|
|
78
|
+
const source = e.source ?? "agent";
|
|
79
|
+
if (source !== "agent" && source !== "flow") return void 0;
|
|
80
|
+
const targetId = e.target?.elementId;
|
|
81
|
+
const label = e.target?.label;
|
|
82
|
+
const dwellMs = numericMeta(e.meta, "dwellMs");
|
|
83
|
+
if (dwellMs !== void 0) {
|
|
84
|
+
const ev2 = buildDwell({ path, ts: e.timestamp, dwellMs, actor: "agent" });
|
|
85
|
+
if (targetId !== void 0) ev2.targetId = targetId;
|
|
86
|
+
if (label !== void 0) ev2.label = label;
|
|
87
|
+
ev2.meta = { action: e.action, agentId: e.agentId, source };
|
|
88
|
+
return ev2;
|
|
89
|
+
}
|
|
90
|
+
const ev = buildClick({
|
|
91
|
+
path,
|
|
92
|
+
ts: e.timestamp,
|
|
93
|
+
x: numericMeta(e.meta, "x") ?? 0,
|
|
94
|
+
y: numericMeta(e.meta, "y") ?? 0,
|
|
95
|
+
vw: numericMeta(e.meta, "vw") ?? 0,
|
|
96
|
+
vh: numericMeta(e.meta, "vh") ?? 0,
|
|
97
|
+
actor: "agent",
|
|
98
|
+
targetId,
|
|
99
|
+
label,
|
|
100
|
+
meta: { action: e.action, agentId: e.agentId, source }
|
|
101
|
+
});
|
|
102
|
+
return ev;
|
|
103
|
+
}
|
|
104
|
+
function numericMeta(meta, key) {
|
|
105
|
+
const v = meta?.[key];
|
|
106
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
107
|
+
}
|
|
108
|
+
async function tapAgentActivity(opts) {
|
|
109
|
+
const load = opts.loadModule ?? defaultLoad;
|
|
110
|
+
let mod;
|
|
111
|
+
try {
|
|
112
|
+
mod = await load();
|
|
113
|
+
} catch {
|
|
114
|
+
mod = void 0;
|
|
115
|
+
}
|
|
116
|
+
if (!mod || typeof mod.onActivity !== "function") return () => {
|
|
117
|
+
};
|
|
118
|
+
try {
|
|
119
|
+
return mod.onActivity((e) => {
|
|
120
|
+
const ev = mapActivityToEvent(e, opts.path());
|
|
121
|
+
if (ev) opts.emit(ev);
|
|
122
|
+
});
|
|
123
|
+
} catch {
|
|
124
|
+
return () => {
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function defaultLoad() {
|
|
129
|
+
const spec = "@particle-academy/fancy-auto-common";
|
|
130
|
+
try {
|
|
131
|
+
const mod = await import(
|
|
132
|
+
/* @vite-ignore */
|
|
133
|
+
spec
|
|
134
|
+
);
|
|
135
|
+
if (mod && typeof mod.onActivity === "function") {
|
|
136
|
+
return mod;
|
|
137
|
+
}
|
|
138
|
+
return void 0;
|
|
139
|
+
} catch {
|
|
140
|
+
return void 0;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
var EventBuffer = class {
|
|
144
|
+
constructor(opts) {
|
|
145
|
+
this.events = [];
|
|
146
|
+
this.siteKey = opts.siteKey;
|
|
147
|
+
this.url = joinCollect(opts.endpoint);
|
|
148
|
+
this.sessionId = opts.sessionId;
|
|
149
|
+
this.send = opts.send ?? defaultSend;
|
|
150
|
+
}
|
|
151
|
+
/** Queue one event for the next flush. */
|
|
152
|
+
add(event) {
|
|
153
|
+
this.events.push(event);
|
|
154
|
+
}
|
|
155
|
+
/** Number of buffered (un-flushed) events. */
|
|
156
|
+
get size() {
|
|
157
|
+
return this.events.length;
|
|
158
|
+
}
|
|
159
|
+
/** The collect URL this buffer ships to. */
|
|
160
|
+
get collectUrl() {
|
|
161
|
+
return this.url;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Ship the buffered events as one batch. No-op when empty. On a failed
|
|
165
|
+
* handoff the events are kept so the next flush retries them.
|
|
166
|
+
*/
|
|
167
|
+
flush() {
|
|
168
|
+
if (this.events.length === 0) return;
|
|
169
|
+
const batch = {
|
|
170
|
+
siteKey: this.siteKey,
|
|
171
|
+
sessionId: this.sessionId,
|
|
172
|
+
events: this.events
|
|
173
|
+
};
|
|
174
|
+
const body = JSON.stringify(batch);
|
|
175
|
+
const ok = this.send(this.url, body);
|
|
176
|
+
if (ok) this.events = [];
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
function joinCollect(endpoint) {
|
|
180
|
+
return endpoint.replace(/\/+$/, "") + "/collect";
|
|
181
|
+
}
|
|
182
|
+
var defaultSend = (url, body) => {
|
|
183
|
+
const nav = typeof navigator !== "undefined" ? navigator : void 0;
|
|
184
|
+
if (nav && typeof nav.sendBeacon === "function") {
|
|
185
|
+
try {
|
|
186
|
+
const blob = typeof Blob !== "undefined" ? new Blob([body], { type: "application/json" }) : body;
|
|
187
|
+
if (nav.sendBeacon(url, blob)) return true;
|
|
188
|
+
} catch {
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (typeof fetch === "function") {
|
|
192
|
+
try {
|
|
193
|
+
void fetch(url, {
|
|
194
|
+
method: "POST",
|
|
195
|
+
body,
|
|
196
|
+
headers: { "Content-Type": "application/json" },
|
|
197
|
+
keepalive: true,
|
|
198
|
+
// Cross-origin ingestion: the PHP routes are CSRF-exempt; we don't read
|
|
199
|
+
// the response, so an opaque mode is fine.
|
|
200
|
+
mode: "cors",
|
|
201
|
+
credentials: "omit"
|
|
202
|
+
}).catch(() => {
|
|
203
|
+
});
|
|
204
|
+
return true;
|
|
205
|
+
} catch {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return false;
|
|
210
|
+
};
|
|
211
|
+
var SESSION_KEY = "fancy-heuristics:sid";
|
|
212
|
+
var fallbackCounter = 0;
|
|
213
|
+
function generateSessionId() {
|
|
214
|
+
const c = typeof globalThis !== "undefined" ? globalThis.crypto : void 0;
|
|
215
|
+
if (c && typeof c.randomUUID === "function") {
|
|
216
|
+
return c.randomUUID();
|
|
217
|
+
}
|
|
218
|
+
if (c && typeof c.getRandomValues === "function") {
|
|
219
|
+
const bytes = new Uint8Array(16);
|
|
220
|
+
c.getRandomValues(bytes);
|
|
221
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
222
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
223
|
+
const hex = [];
|
|
224
|
+
for (let i = 0; i < 16; i++) hex.push(bytes[i].toString(16).padStart(2, "0"));
|
|
225
|
+
return hex.slice(0, 4).join("") + "-" + hex.slice(4, 6).join("") + "-" + hex.slice(6, 8).join("") + "-" + hex.slice(8, 10).join("") + "-" + hex.slice(10, 16).join("");
|
|
226
|
+
}
|
|
227
|
+
fallbackCounter = fallbackCounter + 1 >>> 0;
|
|
228
|
+
return `fh-${Date.now().toString(36)}-${fallbackCounter.toString(36)}`;
|
|
229
|
+
}
|
|
230
|
+
function resolveSessionId(store) {
|
|
231
|
+
const s = safeSessionStorage();
|
|
232
|
+
if (!s) return generateSessionId();
|
|
233
|
+
try {
|
|
234
|
+
const existing = s.getItem(SESSION_KEY);
|
|
235
|
+
if (existing) return existing;
|
|
236
|
+
const fresh = generateSessionId();
|
|
237
|
+
s.setItem(SESSION_KEY, fresh);
|
|
238
|
+
return fresh;
|
|
239
|
+
} catch {
|
|
240
|
+
return generateSessionId();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function safeSessionStorage() {
|
|
244
|
+
try {
|
|
245
|
+
const ss = globalThis.sessionStorage;
|
|
246
|
+
if (!ss) return void 0;
|
|
247
|
+
ss.getItem(SESSION_KEY);
|
|
248
|
+
return ss;
|
|
249
|
+
} catch {
|
|
250
|
+
return void 0;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
var DEFAULT_FLUSH_MS = 1500;
|
|
254
|
+
var DEFAULT_POINTER_THROTTLE_MS = 120;
|
|
255
|
+
var DEFAULT_SCROLL_THROTTLE_MS = 200;
|
|
256
|
+
function resolveTrack(track) {
|
|
257
|
+
return {
|
|
258
|
+
pageview: track?.pageview ?? true,
|
|
259
|
+
dwell: track?.dwell ?? true,
|
|
260
|
+
click: track?.click ?? true,
|
|
261
|
+
scroll: track?.scroll ?? true,
|
|
262
|
+
pointer: track?.pointer ?? true,
|
|
263
|
+
agent: track?.agent ?? true
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function createCollector(opts) {
|
|
267
|
+
if (!opts || !opts.siteKey || !opts.endpoint) {
|
|
268
|
+
throw new Error("createCollector: { siteKey, endpoint } are required");
|
|
269
|
+
}
|
|
270
|
+
const track = resolveTrack(opts.track);
|
|
271
|
+
const flushMs = opts.flushMs ?? DEFAULT_FLUSH_MS;
|
|
272
|
+
const pointerThrottleMs = opts.pointerThrottleMs ?? DEFAULT_POINTER_THROTTLE_MS;
|
|
273
|
+
const scrollThrottleMs = opts.scrollThrottleMs ?? DEFAULT_SCROLL_THROTTLE_MS;
|
|
274
|
+
const sessionId = resolveSessionId();
|
|
275
|
+
const buffer = new EventBuffer({
|
|
276
|
+
siteKey: opts.siteKey,
|
|
277
|
+
endpoint: opts.endpoint,
|
|
278
|
+
sessionId
|
|
279
|
+
});
|
|
280
|
+
let started = false;
|
|
281
|
+
let flushTimer;
|
|
282
|
+
let agentUnsub;
|
|
283
|
+
const teardown = [];
|
|
284
|
+
let visibleSince = 0;
|
|
285
|
+
let accumulatedDwell = 0;
|
|
286
|
+
let maxScrollPct = 0;
|
|
287
|
+
let lastScrollAt = 0;
|
|
288
|
+
let lastPointerAt = 0;
|
|
289
|
+
const path = () => typeof location !== "undefined" && location ? location.pathname : "/";
|
|
290
|
+
const now = opts.now ?? (() => Date.now());
|
|
291
|
+
const vw = () => typeof window !== "undefined" ? window.innerWidth || 0 : 0;
|
|
292
|
+
const vh = () => typeof window !== "undefined" ? window.innerHeight || 0 : 0;
|
|
293
|
+
const emit = (e) => buffer.add(e);
|
|
294
|
+
const onClick = (ev) => {
|
|
295
|
+
const me = ev;
|
|
296
|
+
const targetEl = ev.target;
|
|
297
|
+
const { id, label } = describeTarget(targetEl);
|
|
298
|
+
emit(
|
|
299
|
+
buildClick({
|
|
300
|
+
path: path(),
|
|
301
|
+
ts: now(),
|
|
302
|
+
x: Math.round(me.clientX ?? 0),
|
|
303
|
+
y: Math.round(me.clientY ?? 0),
|
|
304
|
+
vw: vw(),
|
|
305
|
+
vh: vh(),
|
|
306
|
+
targetId: id,
|
|
307
|
+
label
|
|
308
|
+
})
|
|
309
|
+
);
|
|
310
|
+
};
|
|
311
|
+
const onScroll = () => {
|
|
312
|
+
const t = now();
|
|
313
|
+
if (t - lastScrollAt < scrollThrottleMs) return;
|
|
314
|
+
lastScrollAt = t;
|
|
315
|
+
const doc = typeof document !== "undefined" ? document.documentElement : void 0;
|
|
316
|
+
if (!doc) return;
|
|
317
|
+
const scrollTop = (typeof window !== "undefined" ? window.scrollY : 0) || doc.scrollTop || 0;
|
|
318
|
+
const scrollable = doc.scrollHeight - doc.clientHeight;
|
|
319
|
+
const pct = scrollPercent(scrollTop, scrollable);
|
|
320
|
+
if (pct > maxScrollPct) {
|
|
321
|
+
maxScrollPct = pct;
|
|
322
|
+
emit(buildScroll({ path: path(), ts: t, scrollPct: maxScrollPct }));
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
const onPointerMove = (ev) => {
|
|
326
|
+
const t = now();
|
|
327
|
+
if (t - lastPointerAt < pointerThrottleMs) return;
|
|
328
|
+
lastPointerAt = t;
|
|
329
|
+
const pe = ev;
|
|
330
|
+
emit(
|
|
331
|
+
buildPointer({
|
|
332
|
+
path: path(),
|
|
333
|
+
ts: t,
|
|
334
|
+
x: Math.round(pe.clientX ?? 0),
|
|
335
|
+
y: Math.round(pe.clientY ?? 0),
|
|
336
|
+
vw: vw(),
|
|
337
|
+
vh: vh()
|
|
338
|
+
})
|
|
339
|
+
);
|
|
340
|
+
};
|
|
341
|
+
const isVisible = () => typeof document === "undefined" || document.visibilityState !== "hidden";
|
|
342
|
+
const openDwellWindow = () => {
|
|
343
|
+
if (visibleSince === 0) visibleSince = now();
|
|
344
|
+
};
|
|
345
|
+
const closeDwellWindow = () => {
|
|
346
|
+
if (visibleSince !== 0) {
|
|
347
|
+
accumulatedDwell += now() - visibleSince;
|
|
348
|
+
visibleSince = 0;
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
const onVisibilityChange = () => {
|
|
352
|
+
if (isVisible()) openDwellWindow();
|
|
353
|
+
else closeDwellWindow();
|
|
354
|
+
};
|
|
355
|
+
const emitDwell = () => {
|
|
356
|
+
closeDwellWindow();
|
|
357
|
+
if (accumulatedDwell > 0) {
|
|
358
|
+
emit(buildDwell({ path: path(), ts: now(), dwellMs: accumulatedDwell }));
|
|
359
|
+
accumulatedDwell = 0;
|
|
360
|
+
}
|
|
361
|
+
if (isVisible()) openDwellWindow();
|
|
362
|
+
};
|
|
363
|
+
const onPageHide = () => {
|
|
364
|
+
if (track.dwell) {
|
|
365
|
+
closeDwellWindow();
|
|
366
|
+
if (accumulatedDwell > 0) {
|
|
367
|
+
emit(buildDwell({ path: path(), ts: now(), dwellMs: accumulatedDwell }));
|
|
368
|
+
accumulatedDwell = 0;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
buffer.flush();
|
|
372
|
+
};
|
|
373
|
+
const addListener = (target, type, handler, options) => {
|
|
374
|
+
if (!target || typeof target.addEventListener !== "function") return;
|
|
375
|
+
target.addEventListener(type, handler, options);
|
|
376
|
+
teardown.push(() => target.removeEventListener(type, handler, options));
|
|
377
|
+
};
|
|
378
|
+
return {
|
|
379
|
+
start() {
|
|
380
|
+
if (started) return;
|
|
381
|
+
started = true;
|
|
382
|
+
const doc = typeof document !== "undefined" ? document : void 0;
|
|
383
|
+
const win = typeof window !== "undefined" ? window : void 0;
|
|
384
|
+
if (track.pageview) {
|
|
385
|
+
emit(buildPageview(path(), now()));
|
|
386
|
+
}
|
|
387
|
+
if (track.dwell) {
|
|
388
|
+
openDwellWindow();
|
|
389
|
+
addListener(doc, "visibilitychange", onVisibilityChange);
|
|
390
|
+
}
|
|
391
|
+
if (track.click) {
|
|
392
|
+
addListener(doc, "click", onClick, { capture: true, passive: true });
|
|
393
|
+
}
|
|
394
|
+
if (track.scroll) {
|
|
395
|
+
addListener(win, "scroll", onScroll, { passive: true });
|
|
396
|
+
}
|
|
397
|
+
if (track.pointer) {
|
|
398
|
+
addListener(win, "pointermove", onPointerMove, { passive: true });
|
|
399
|
+
}
|
|
400
|
+
addListener(win, "pagehide", onPageHide);
|
|
401
|
+
if (track.agent) {
|
|
402
|
+
void tapAgentActivity({ path, emit }).then((unsub) => {
|
|
403
|
+
if (started) agentUnsub = unsub;
|
|
404
|
+
else unsub();
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
if (typeof setInterval === "function") {
|
|
408
|
+
flushTimer = setInterval(() => {
|
|
409
|
+
if (track.dwell) emitDwell();
|
|
410
|
+
buffer.flush();
|
|
411
|
+
}, flushMs);
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
stop() {
|
|
415
|
+
if (!started) return;
|
|
416
|
+
started = false;
|
|
417
|
+
if (flushTimer !== void 0) {
|
|
418
|
+
clearInterval(flushTimer);
|
|
419
|
+
flushTimer = void 0;
|
|
420
|
+
}
|
|
421
|
+
for (const fn of teardown.splice(0)) {
|
|
422
|
+
try {
|
|
423
|
+
fn();
|
|
424
|
+
} catch {
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (agentUnsub) {
|
|
428
|
+
try {
|
|
429
|
+
agentUnsub();
|
|
430
|
+
} catch {
|
|
431
|
+
}
|
|
432
|
+
agentUnsub = void 0;
|
|
433
|
+
}
|
|
434
|
+
if (track.dwell) {
|
|
435
|
+
closeDwellWindow();
|
|
436
|
+
if (accumulatedDwell > 0) {
|
|
437
|
+
emit(buildDwell({ path: path(), ts: now(), dwellMs: accumulatedDwell }));
|
|
438
|
+
accumulatedDwell = 0;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
buffer.flush();
|
|
442
|
+
},
|
|
443
|
+
flush() {
|
|
444
|
+
buffer.flush();
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
function describeTarget(el) {
|
|
449
|
+
if (!el) return {};
|
|
450
|
+
let node = el;
|
|
451
|
+
let id;
|
|
452
|
+
for (let depth = 0; node && depth < 5; depth++) {
|
|
453
|
+
const candidate = node.getAttribute?.("data-fancy-id") ?? node.getAttribute?.("data-testid") ?? (node.id || void 0);
|
|
454
|
+
if (candidate) {
|
|
455
|
+
id = candidate;
|
|
456
|
+
break;
|
|
457
|
+
}
|
|
458
|
+
node = node.parentElement;
|
|
459
|
+
}
|
|
460
|
+
const labelSource = node ?? el;
|
|
461
|
+
const label = readLabel(labelSource);
|
|
462
|
+
const out = {};
|
|
463
|
+
if (id !== void 0) out.id = id;
|
|
464
|
+
if (label !== void 0) out.label = label;
|
|
465
|
+
return out;
|
|
466
|
+
}
|
|
467
|
+
function readLabel(el) {
|
|
468
|
+
const aria = el.getAttribute?.("aria-label");
|
|
469
|
+
if (aria) return trim(aria);
|
|
470
|
+
const text = el.textContent;
|
|
471
|
+
if (text) {
|
|
472
|
+
const t = trim(text);
|
|
473
|
+
if (t) return t;
|
|
474
|
+
}
|
|
475
|
+
const tag = el.tagName ? el.tagName.toLowerCase() : void 0;
|
|
476
|
+
return tag;
|
|
477
|
+
}
|
|
478
|
+
function trim(s) {
|
|
479
|
+
return s.replace(/\s+/g, " ").trim().slice(0, 120);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// src/collector.ts
|
|
483
|
+
var factory = (opts) => createCollector({ siteKey: opts.siteKey, endpoint: opts.endpoint });
|
|
484
|
+
function createPixelCollector(opts) {
|
|
485
|
+
return factory(opts);
|
|
486
|
+
}
|
|
487
|
+
function __setCollectorFactory(next) {
|
|
488
|
+
factory = next ?? ((opts) => createCollector({ siteKey: opts.siteKey, endpoint: opts.endpoint }));
|
|
489
|
+
}
|
|
490
|
+
|
|
34
491
|
// src/render.ts
|
|
35
492
|
function logoGlyph(size) {
|
|
36
493
|
return `<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false" style="display:block;flex:0 0 auto;">
|
|
@@ -191,6 +648,7 @@ function mountPixel(opts = {}) {
|
|
|
191
648
|
const mode = MODES.includes(opts.mode) ? opts.mode : "floating";
|
|
192
649
|
const siteKey = opts.siteKey ?? "";
|
|
193
650
|
const endpoint = opts.endpoint ?? "";
|
|
651
|
+
const collect = opts.collect !== false;
|
|
194
652
|
const href = opts.href ?? DEFAULT_HREF;
|
|
195
653
|
const target = opts.target ?? null;
|
|
196
654
|
const host = createPixelHost(style, mode, href);
|
|
@@ -244,11 +702,21 @@ function mountPixel(opts = {}) {
|
|
|
244
702
|
setVisible(true);
|
|
245
703
|
}
|
|
246
704
|
beacon();
|
|
705
|
+
let collector = null;
|
|
706
|
+
if (endpoint && collect) {
|
|
707
|
+
try {
|
|
708
|
+
collector = createPixelCollector({ siteKey, endpoint });
|
|
709
|
+
collector.start();
|
|
710
|
+
} catch {
|
|
711
|
+
collector = null;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
247
714
|
const resolved = {
|
|
248
715
|
style,
|
|
249
716
|
mode,
|
|
250
717
|
siteKey,
|
|
251
718
|
endpoint,
|
|
719
|
+
collect,
|
|
252
720
|
href,
|
|
253
721
|
target
|
|
254
722
|
};
|
|
@@ -257,12 +725,22 @@ function mountPixel(opts = {}) {
|
|
|
257
725
|
get visible() {
|
|
258
726
|
return visible;
|
|
259
727
|
},
|
|
728
|
+
get collector() {
|
|
729
|
+
return collector;
|
|
730
|
+
},
|
|
260
731
|
options: resolved,
|
|
261
732
|
destroy() {
|
|
262
733
|
if (destroyed) return;
|
|
263
734
|
destroyed = true;
|
|
264
735
|
observer?.disconnect();
|
|
265
736
|
observer = null;
|
|
737
|
+
if (collector) {
|
|
738
|
+
try {
|
|
739
|
+
collector.stop();
|
|
740
|
+
} catch {
|
|
741
|
+
}
|
|
742
|
+
collector = null;
|
|
743
|
+
}
|
|
266
744
|
host.remove();
|
|
267
745
|
}
|
|
268
746
|
};
|
|
@@ -280,14 +758,16 @@ function readScriptConfig() {
|
|
|
280
758
|
}
|
|
281
759
|
if (!el) return null;
|
|
282
760
|
const ds = el.dataset;
|
|
283
|
-
if (ds.style === void 0 && ds.mode === void 0 && ds.site === void 0 && ds.endpoint === void 0 && ds.fancyPixel === void 0) {
|
|
761
|
+
if (ds.style === void 0 && ds.mode === void 0 && ds.site === void 0 && ds.endpoint === void 0 && ds.collect === void 0 && ds.fancyPixel === void 0) {
|
|
284
762
|
return null;
|
|
285
763
|
}
|
|
764
|
+
const collect = ds.collect !== void 0 ? ds.collect !== "false" : void 0;
|
|
286
765
|
return {
|
|
287
766
|
style: ds.style,
|
|
288
767
|
mode: ds.mode,
|
|
289
768
|
siteKey: ds.site,
|
|
290
769
|
endpoint: ds.endpoint,
|
|
770
|
+
collect,
|
|
291
771
|
target: ds.target ?? null,
|
|
292
772
|
href: ds.href
|
|
293
773
|
};
|
|
@@ -310,7 +790,9 @@ function autoInit() {
|
|
|
310
790
|
return run();
|
|
311
791
|
}
|
|
312
792
|
|
|
793
|
+
exports.__setCollectorFactory = __setCollectorFactory;
|
|
313
794
|
exports.autoInit = autoInit;
|
|
795
|
+
exports.createPixelCollector = createPixelCollector;
|
|
314
796
|
exports.createPixelHost = createPixelHost;
|
|
315
797
|
exports.hostStyleFor = hostStyleFor;
|
|
316
798
|
exports.mountPixel = mountPixel;
|