@nexly/core 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-meta.d.ts +20 -3
- package/dist/browser-meta.d.ts.map +1 -1
- package/dist/browser-meta.js +41 -23
- package/dist/collect.d.ts +4 -1
- package/dist/collect.d.ts.map +1 -1
- package/dist/collect.js +5 -0
- package/dist/events/engagement.d.ts +5 -1
- package/dist/events/engagement.d.ts.map +1 -1
- package/dist/events/engagement.js +37 -34
- package/dist/events/pageview.d.ts +2 -1
- package/dist/events/pageview.d.ts.map +1 -1
- package/dist/events/pageview.js +5 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/nexly.d.ts +5 -2
- package/dist/nexly.d.ts.map +1 -1
- package/dist/nexly.js +5 -3
- package/package.json +1 -1
package/dist/browser-meta.d.ts
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Browser metadata collection, split into session-stable and per-event fields.
|
|
3
|
+
*
|
|
4
|
+
* - `collectSessionMeta()` — stable within a session (UA, screen, language, etc.), sent once.
|
|
5
|
+
* - `collectEventMeta()` — per-event volatile fields (url, pathname, referrer), sent with every event.
|
|
6
|
+
* - `collectBrowserMeta()` — legacy: merges both for backward compatibility.
|
|
5
7
|
*
|
|
6
8
|
* Does not include geo (country/region/city) — that requires server-side IP lookup.
|
|
7
9
|
*/
|
|
10
|
+
/**
|
|
11
|
+
* Session-stable metadata: user agent, screen, language, timezone, etc.
|
|
12
|
+
* Collected once per session and sent as `session_context` on the wire.
|
|
13
|
+
*/
|
|
14
|
+
export declare function collectSessionMeta(): Record<string, unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* Per-event volatile metadata: only fields that actually change between events.
|
|
17
|
+
* Includes `visitor_id` and `session_id` for server-side extraction,
|
|
18
|
+
* plus `url` and `pathname` to track SPA navigation.
|
|
19
|
+
*/
|
|
20
|
+
export declare function collectEventMeta(): Record<string, unknown>;
|
|
21
|
+
/**
|
|
22
|
+
* Legacy: full browser metadata (session + event fields merged).
|
|
23
|
+
* Kept for backward compatibility with `Nexly.event()` and custom events.
|
|
24
|
+
*/
|
|
8
25
|
export declare function collectBrowserMeta(): Record<string, unknown>;
|
|
9
26
|
//# sourceMappingURL=browser-meta.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-meta.d.ts","sourceRoot":"","sources":["../src/browser-meta.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"browser-meta.d.ts","sourceRoot":"","sources":["../src/browser-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkBH;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiF5D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAc1D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE5D"}
|
package/dist/browser-meta.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Browser metadata collection, split into session-stable and per-event fields.
|
|
3
|
+
*
|
|
4
|
+
* - `collectSessionMeta()` — stable within a session (UA, screen, language, etc.), sent once.
|
|
5
|
+
* - `collectEventMeta()` — per-event volatile fields (url, pathname, referrer), sent with every event.
|
|
6
|
+
* - `collectBrowserMeta()` — legacy: merges both for backward compatibility.
|
|
5
7
|
*
|
|
6
8
|
* Does not include geo (country/region/city) — that requires server-side IP lookup.
|
|
7
9
|
*/
|
|
@@ -14,19 +16,18 @@ function safe(fn) {
|
|
|
14
16
|
return undefined;
|
|
15
17
|
}
|
|
16
18
|
}
|
|
17
|
-
|
|
19
|
+
function filterEmpty(obj) {
|
|
20
|
+
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined && v !== '' && !(Array.isArray(v) && v.length === 0)));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Session-stable metadata: user agent, screen, language, timezone, etc.
|
|
24
|
+
* Collected once per session and sent as `session_context` on the wire.
|
|
25
|
+
*/
|
|
26
|
+
export function collectSessionMeta() {
|
|
18
27
|
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
|
|
19
28
|
return {};
|
|
20
29
|
}
|
|
21
30
|
const out = {};
|
|
22
|
-
out.visitor_id = safe(() => getVisitorId());
|
|
23
|
-
out.session_id = safe(() => getSessionId());
|
|
24
|
-
out.url = safe(() => window.location.href);
|
|
25
|
-
out.pathname = safe(() => window.location.pathname);
|
|
26
|
-
const ref = safe(() => document.referrer);
|
|
27
|
-
if (ref) {
|
|
28
|
-
out.referrer = ref;
|
|
29
|
-
}
|
|
30
31
|
out.language = safe(() => navigator.language);
|
|
31
32
|
const langs = safe(() => navigator.languages);
|
|
32
33
|
if (langs?.length) {
|
|
@@ -41,10 +42,14 @@ export function collectBrowserMeta() {
|
|
|
41
42
|
out.viewport_width = safe(() => window.innerWidth);
|
|
42
43
|
out.viewport_height = safe(() => window.innerHeight);
|
|
43
44
|
out.device_pixel_ratio = safe(() => window.devicePixelRatio);
|
|
45
|
+
const ref = safe(() => document.referrer);
|
|
46
|
+
if (ref) {
|
|
47
|
+
out.referrer = ref;
|
|
48
|
+
}
|
|
49
|
+
out.online = safe(() => navigator.onLine);
|
|
44
50
|
out.user_agent = safe(() => navigator.userAgent);
|
|
45
51
|
out.navigator_platform = safe(() => navigator.platform);
|
|
46
52
|
out.cookie_enabled = safe(() => navigator.cookieEnabled);
|
|
47
|
-
out.online = safe(() => navigator.onLine);
|
|
48
53
|
out.hardware_concurrency = safe(() => navigator.hardwareConcurrency);
|
|
49
54
|
out.max_touch_points = safe(() => navigator.maxTouchPoints);
|
|
50
55
|
const conn = safe(() => navigator.connection);
|
|
@@ -87,15 +92,28 @@ export function collectBrowserMeta() {
|
|
|
87
92
|
out.prefers_reduced_motion = reduced;
|
|
88
93
|
}
|
|
89
94
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
return filterEmpty(out);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Per-event volatile metadata: only fields that actually change between events.
|
|
99
|
+
* Includes `visitor_id` and `session_id` for server-side extraction,
|
|
100
|
+
* plus `url` and `pathname` to track SPA navigation.
|
|
101
|
+
*/
|
|
102
|
+
export function collectEventMeta() {
|
|
103
|
+
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
|
|
104
|
+
return {};
|
|
99
105
|
}
|
|
100
|
-
|
|
106
|
+
const out = {};
|
|
107
|
+
out.visitor_id = safe(() => getVisitorId());
|
|
108
|
+
out.session_id = safe(() => getSessionId());
|
|
109
|
+
out.url = safe(() => window.location.href);
|
|
110
|
+
out.pathname = safe(() => window.location.pathname);
|
|
111
|
+
return filterEmpty(out);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Legacy: full browser metadata (session + event fields merged).
|
|
115
|
+
* Kept for backward compatibility with `Nexly.event()` and custom events.
|
|
116
|
+
*/
|
|
117
|
+
export function collectBrowserMeta() {
|
|
118
|
+
return { ...collectSessionMeta(), ...collectEventMeta() };
|
|
101
119
|
}
|
package/dist/collect.d.ts
CHANGED
|
@@ -5,8 +5,9 @@ export type IngestCredentials = {
|
|
|
5
5
|
};
|
|
6
6
|
/**
|
|
7
7
|
* Event envelope:
|
|
8
|
-
* - `context` —
|
|
8
|
+
* - `context` — per-event volatile metadata (url, pathname, viewport, etc.).
|
|
9
9
|
* - `data` — owner-defined custom properties (later: only keys registered for the app).
|
|
10
|
+
* - `session_context` — session-stable metadata (UA, screen, language), sent once per session.
|
|
10
11
|
*/
|
|
11
12
|
export type TrackEventInput = {
|
|
12
13
|
credentials: IngestCredentials;
|
|
@@ -14,6 +15,7 @@ export type TrackEventInput = {
|
|
|
14
15
|
eventType: string;
|
|
15
16
|
context?: Record<string, unknown>;
|
|
16
17
|
data?: Record<string, unknown>;
|
|
18
|
+
sessionContext?: Record<string, unknown>;
|
|
17
19
|
};
|
|
18
20
|
/** Full send: transport URL + event envelope. */
|
|
19
21
|
export type SendBeaconCollectInput = TrackEventInput & {
|
|
@@ -26,6 +28,7 @@ export type CollectCredentials = {
|
|
|
26
28
|
/**
|
|
27
29
|
* Builds the JSON body for POST /v1/collect (snake_case wire format).
|
|
28
30
|
* Duplicates `context.path` to top-level `path` when present.
|
|
31
|
+
* Includes `session_context` when provided (first event of a session).
|
|
29
32
|
*/
|
|
30
33
|
export declare function buildCollectPayload(input: TrackEventInput): Record<string, unknown>;
|
|
31
34
|
/**
|
package/dist/collect.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../src/collect.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../src/collect.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,iBAAiB,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACzC,CAAA;AAED,iDAAiD;AACjD,MAAM,MAAM,sBAAsB,GAAG,eAAe,GAAG;IACrD,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,6GAA6G;AAC7G,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAA;CACnB,GAAG,iBAAiB,CAAA;AAMrB;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAqBnF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CASxE"}
|
package/dist/collect.js
CHANGED
|
@@ -4,6 +4,7 @@ function isPlainObject(v) {
|
|
|
4
4
|
/**
|
|
5
5
|
* Builds the JSON body for POST /v1/collect (snake_case wire format).
|
|
6
6
|
* Duplicates `context.path` to top-level `path` when present.
|
|
7
|
+
* Includes `session_context` when provided (first event of a session).
|
|
7
8
|
*/
|
|
8
9
|
export function buildCollectPayload(input) {
|
|
9
10
|
const context = isPlainObject(input.context) ? input.context : {};
|
|
@@ -21,6 +22,10 @@ export function buildCollectPayload(input) {
|
|
|
21
22
|
if (path) {
|
|
22
23
|
body.path = path;
|
|
23
24
|
}
|
|
25
|
+
const sc = isPlainObject(input.sessionContext) ? input.sessionContext : null;
|
|
26
|
+
if (sc && Object.keys(sc).length > 0) {
|
|
27
|
+
body.session_context = sc;
|
|
28
|
+
}
|
|
24
29
|
return body;
|
|
25
30
|
}
|
|
26
31
|
/**
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { type CollectCredentials } from '../collect.js';
|
|
2
2
|
type StopFn = () => void;
|
|
3
3
|
/**
|
|
4
|
-
* Attaches engagement listeners (scroll, click, input focus, visibility, heartbeat).
|
|
4
|
+
* Attaches engagement listeners (scroll, click, input focus, visibility, keepalive heartbeat).
|
|
5
5
|
* Returns a cleanup function that removes all listeners and timers.
|
|
6
|
+
*
|
|
7
|
+
* Duration is tracked client-side: a 1s tick increments `activeSeconds` only while visible.
|
|
8
|
+
* A lightweight keepalive heartbeat fires every 60s for the realtime dashboard.
|
|
9
|
+
* Summary events are sent on visibility hidden and beforeunload.
|
|
6
10
|
*/
|
|
7
11
|
export declare function startEngagementTracking(creds: CollectCredentials): StopFn;
|
|
8
12
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engagement.d.ts","sourceRoot":"","sources":["../../src/events/engagement.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"engagement.d.ts","sourceRoot":"","sources":["../../src/events/engagement.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAyB1E,KAAK,MAAM,GAAG,MAAM,IAAI,CAAA;AAExB;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAmIzE"}
|
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { collectEventMeta, collectSessionMeta } from '../browser-meta.js';
|
|
2
2
|
import { sendBeaconCollect } from '../collect.js';
|
|
3
3
|
const CLICK_THROTTLE_MS = 500;
|
|
4
|
-
const
|
|
4
|
+
const KEEPALIVE_INTERVAL_MS = 60_000;
|
|
5
5
|
const SCROLL_DEBOUNCE_MS = 300;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
function sendEngagement(creds, eventName, eventType, data) {
|
|
6
|
+
const ACTIVE_TICK_MS = 1_000;
|
|
7
|
+
function sendEngagement(creds, eventName, eventType, data, sessionContext) {
|
|
10
8
|
sendBeaconCollect({
|
|
11
9
|
collectUrl: creds.collectUrl,
|
|
12
10
|
credentials: { appId: creds.appId, apiToken: creds.apiToken },
|
|
13
11
|
eventName,
|
|
14
12
|
eventType,
|
|
15
|
-
context:
|
|
13
|
+
context: collectEventMeta(),
|
|
16
14
|
data,
|
|
15
|
+
sessionContext,
|
|
17
16
|
});
|
|
18
17
|
}
|
|
19
18
|
/**
|
|
20
|
-
* Attaches engagement listeners (scroll, click, input focus, visibility, heartbeat).
|
|
19
|
+
* Attaches engagement listeners (scroll, click, input focus, visibility, keepalive heartbeat).
|
|
21
20
|
* Returns a cleanup function that removes all listeners and timers.
|
|
21
|
+
*
|
|
22
|
+
* Duration is tracked client-side: a 1s tick increments `activeSeconds` only while visible.
|
|
23
|
+
* A lightweight keepalive heartbeat fires every 60s for the realtime dashboard.
|
|
24
|
+
* Summary events are sent on visibility hidden and beforeunload.
|
|
22
25
|
*/
|
|
23
26
|
export function startEngagementTracking(creds) {
|
|
24
27
|
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
@@ -26,6 +29,20 @@ export function startEngagementTracking(creds) {
|
|
|
26
29
|
}
|
|
27
30
|
const ac = new AbortController();
|
|
28
31
|
const { signal } = ac;
|
|
32
|
+
let sessionContextSent = false;
|
|
33
|
+
function getSessionContextOnce() {
|
|
34
|
+
if (sessionContextSent)
|
|
35
|
+
return undefined;
|
|
36
|
+
sessionContextSent = true;
|
|
37
|
+
return collectSessionMeta();
|
|
38
|
+
}
|
|
39
|
+
// ---- client-side active duration tracking ----
|
|
40
|
+
let activeSeconds = 0;
|
|
41
|
+
const activeTickId = setInterval(() => {
|
|
42
|
+
if (document.visibilityState === 'visible') {
|
|
43
|
+
activeSeconds++;
|
|
44
|
+
}
|
|
45
|
+
}, ACTIVE_TICK_MS);
|
|
29
46
|
// ---- scroll depth ----
|
|
30
47
|
let maxScrollPercent = 0;
|
|
31
48
|
let scrollTimer = null;
|
|
@@ -91,50 +108,36 @@ export function startEngagementTracking(creds) {
|
|
|
91
108
|
});
|
|
92
109
|
}
|
|
93
110
|
document.addEventListener('focusin', onFocusIn, { signal });
|
|
94
|
-
// ---- visibility /
|
|
95
|
-
let visibleSince = document.visibilityState === 'visible' ? Date.now() : 0;
|
|
96
|
-
let accumulatedVisibleMs = 0;
|
|
111
|
+
// ---- visibility / session summary ----
|
|
97
112
|
function onVisibilityChange() {
|
|
98
113
|
if (document.visibilityState === 'hidden') {
|
|
99
|
-
if (visibleSince > 0) {
|
|
100
|
-
accumulatedVisibleMs += Date.now() - visibleSince;
|
|
101
|
-
visibleSince = 0;
|
|
102
|
-
}
|
|
103
114
|
flushScrollDepth();
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
sendEngagement(creds, 'visibility_change', 'lifecycle', { visible_seconds: secs, state: 'hidden' });
|
|
115
|
+
if (activeSeconds > 0) {
|
|
116
|
+
sendEngagement(creds, 'session_ping', 'lifecycle', { active_seconds: activeSeconds });
|
|
107
117
|
}
|
|
108
118
|
}
|
|
109
|
-
else {
|
|
110
|
-
visibleSince = Date.now();
|
|
111
|
-
}
|
|
112
119
|
}
|
|
113
120
|
document.addEventListener('visibilitychange', onVisibilityChange, { signal });
|
|
114
121
|
function onBeforeUnload() {
|
|
115
|
-
if (visibleSince > 0) {
|
|
116
|
-
accumulatedVisibleMs += Date.now() - visibleSince;
|
|
117
|
-
visibleSince = 0;
|
|
118
|
-
}
|
|
119
122
|
flushScrollDepth();
|
|
120
|
-
|
|
121
|
-
sendEngagement(creds, 'visibility_change', 'lifecycle', { visible_seconds: secs, state: 'unload' });
|
|
123
|
+
sendEngagement(creds, 'session_end', 'lifecycle', { active_seconds: activeSeconds });
|
|
122
124
|
}
|
|
123
125
|
window.addEventListener('beforeunload', onBeforeUnload, { signal });
|
|
124
|
-
// ---- heartbeat ----
|
|
125
|
-
|
|
126
|
-
function sendHeartbeat() {
|
|
126
|
+
// ---- keepalive heartbeat (60s, lightweight, for realtime dashboard) ----
|
|
127
|
+
function sendKeepalive() {
|
|
127
128
|
if (document.visibilityState !== 'visible')
|
|
128
129
|
return;
|
|
129
|
-
|
|
130
|
-
sendEngagement(creds, 'heartbeat', 'lifecycle', { elapsed_seconds: elapsed });
|
|
130
|
+
sendEngagement(creds, 'heartbeat', 'lifecycle', { active_seconds: activeSeconds }, getSessionContextOnce());
|
|
131
131
|
}
|
|
132
|
-
|
|
132
|
+
// Send first heartbeat immediately to register the session context
|
|
133
|
+
sendKeepalive();
|
|
134
|
+
const keepaliveId = setInterval(sendKeepalive, KEEPALIVE_INTERVAL_MS);
|
|
133
135
|
// ---- cleanup ----
|
|
134
136
|
return () => {
|
|
135
137
|
ac.abort();
|
|
136
138
|
if (scrollTimer)
|
|
137
139
|
clearTimeout(scrollTimer);
|
|
138
|
-
clearInterval(
|
|
140
|
+
clearInterval(activeTickId);
|
|
141
|
+
clearInterval(keepaliveId);
|
|
139
142
|
};
|
|
140
143
|
}
|
|
@@ -2,7 +2,8 @@ import { type CollectCredentials } from '../collect.js';
|
|
|
2
2
|
/** Current document path, or `/` outside a browser. */
|
|
3
3
|
export declare function getDefaultPathname(): string;
|
|
4
4
|
/**
|
|
5
|
-
* Page view:
|
|
5
|
+
* Page view: sends slim `context` (per-event meta) plus `session_context` (session-stable meta).
|
|
6
|
+
* The backend upserts the session row from `session_context` on every pageview.
|
|
6
7
|
*/
|
|
7
8
|
export declare function sendPageViewBeacon(creds: CollectCredentials, path?: string): boolean;
|
|
8
9
|
//# sourceMappingURL=pageview.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pageview.d.ts","sourceRoot":"","sources":["../../src/events/pageview.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAE1E,uDAAuD;AACvD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED
|
|
1
|
+
{"version":3,"file":"pageview.d.ts","sourceRoot":"","sources":["../../src/events/pageview.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAE1E,uDAAuD;AACvD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,EAAE,IAAI,GAAE,MAA6B,GAAG,OAAO,CAa1G"}
|
package/dist/events/pageview.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { collectEventMeta, collectSessionMeta } from '../browser-meta.js';
|
|
2
2
|
import { sendBeaconCollect } from '../collect.js';
|
|
3
3
|
/** Current document path, or `/` outside a browser. */
|
|
4
4
|
export function getDefaultPathname() {
|
|
5
5
|
return typeof window !== 'undefined' ? window.location.pathname : '/';
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* Page view:
|
|
8
|
+
* Page view: sends slim `context` (per-event meta) plus `session_context` (session-stable meta).
|
|
9
|
+
* The backend upserts the session row from `session_context` on every pageview.
|
|
9
10
|
*/
|
|
10
11
|
export function sendPageViewBeacon(creds, path = getDefaultPathname()) {
|
|
11
12
|
return sendBeaconCollect({
|
|
@@ -14,9 +15,10 @@ export function sendPageViewBeacon(creds, path = getDefaultPathname()) {
|
|
|
14
15
|
eventName: 'pageview',
|
|
15
16
|
eventType: 'pageview',
|
|
16
17
|
context: {
|
|
17
|
-
...
|
|
18
|
+
...collectEventMeta(),
|
|
18
19
|
path,
|
|
19
20
|
},
|
|
20
21
|
data: {},
|
|
22
|
+
sessionContext: collectSessionMeta(),
|
|
21
23
|
});
|
|
22
24
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Browser event ingest client (public API).
|
|
3
3
|
*/
|
|
4
|
-
export { Nexly, type NexlyEventInput, type NexlyInit } from './nexly.js';
|
|
5
|
-
export { collectBrowserMeta } from './browser-meta.js';
|
|
4
|
+
export { Nexly, type NexlyEventInput, type NexlyEventType, type NexlyInit } from './nexly.js';
|
|
5
|
+
export { collectBrowserMeta, collectSessionMeta, collectEventMeta } from './browser-meta.js';
|
|
6
6
|
export { getSessionId, getVisitorId } from './session.js';
|
|
7
7
|
export { buildCollectPayload, sendBeaconCollect, type CollectCredentials, type IngestCredentials, type SendBeaconCollectInput, type TrackEventInput, } from './collect.js';
|
|
8
8
|
export { getDefaultPathname, sendPageViewBeacon, startEngagementTracking } from './events/index.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAC7F,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAC5F,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,eAAe,GACrB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Browser event ingest client (public API).
|
|
3
3
|
*/
|
|
4
4
|
export { Nexly } from './nexly.js';
|
|
5
|
-
export { collectBrowserMeta } from './browser-meta.js';
|
|
5
|
+
export { collectBrowserMeta, collectSessionMeta, collectEventMeta } from './browser-meta.js';
|
|
6
6
|
export { getSessionId, getVisitorId } from './session.js';
|
|
7
7
|
export { buildCollectPayload, sendBeaconCollect, } from './collect.js';
|
|
8
8
|
export { getDefaultPathname, sendPageViewBeacon, startEngagementTracking } from './events/index.js';
|
package/dist/nexly.d.ts
CHANGED
|
@@ -5,9 +5,11 @@ export type NexlyInit = {
|
|
|
5
5
|
appId: string;
|
|
6
6
|
key: string;
|
|
7
7
|
};
|
|
8
|
+
/** Allowed event types. The backend rejects any other value. */
|
|
9
|
+
export type NexlyEventType = 'pageview' | 'engagement' | 'custom';
|
|
8
10
|
export type NexlyEventInput = {
|
|
9
11
|
name: string;
|
|
10
|
-
type:
|
|
12
|
+
type: NexlyEventType;
|
|
11
13
|
data?: Record<string, unknown>;
|
|
12
14
|
/** Merged on top of default browser context (see {@link collectBrowserMeta}) and current `path`. */
|
|
13
15
|
context?: Record<string, unknown>;
|
|
@@ -35,7 +37,8 @@ export declare class Nexly {
|
|
|
35
37
|
*/
|
|
36
38
|
pageview(path?: string): boolean;
|
|
37
39
|
/**
|
|
38
|
-
* Sends a custom event. Default context is
|
|
40
|
+
* Sends a custom event. Default context is per-event meta + path; pass `context` to merge or override fields.
|
|
41
|
+
* Includes session_context so the backend can upsert session metadata.
|
|
39
42
|
*/
|
|
40
43
|
event(input: NexlyEventInput): boolean;
|
|
41
44
|
/**
|
package/dist/nexly.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nexly.d.ts","sourceRoot":"","sources":["../src/nexly.ts"],"names":[],"mappings":"AAMA,kGAAkG;AAClG,MAAM,MAAM,SAAS,GAAG;IACtB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"nexly.d.ts","sourceRoot":"","sources":["../src/nexly.ts"],"names":[],"mappings":"AAMA,kGAAkG;AAClG,MAAM,MAAM,SAAS,GAAG;IACtB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,gEAAgE;AAChE,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,YAAY,GAAG,QAAQ,CAAA;AAEjE,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,cAAc,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,oGAAoG;IACpG,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClC,CAAA;AAED;;GAEG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqB;IAE5C;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,KAAK;IAKtC,uFAAuF;IACvF,MAAM,CAAC,WAAW,IAAI,KAAK,GAAG,IAAI;IAIlC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;gBAER,IAAI,EAAE,SAAS;IAM3B,OAAO,KAAK,WAAW,GAMtB;IAED,OAAO,CAAC,cAAc;IAOtB;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO;IAIhC;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO;IAetC;;OAEG;IACH,eAAe,IAAI,MAAM,IAAI;CAG9B"}
|
package/dist/nexly.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { collectEventMeta, collectSessionMeta } from './browser-meta.js';
|
|
2
2
|
import { sendBeaconCollect } from './collect.js';
|
|
3
3
|
import { getDefaultPathname, sendPageViewBeacon, startEngagementTracking } from './events/index.js';
|
|
4
4
|
const DEFAULT_COLLECT_URL = 'https://gate.nexly.to/v1/collect';
|
|
@@ -36,7 +36,7 @@ export class Nexly {
|
|
|
36
36
|
}
|
|
37
37
|
defaultContext() {
|
|
38
38
|
return {
|
|
39
|
-
...
|
|
39
|
+
...collectEventMeta(),
|
|
40
40
|
path: getDefaultPathname(),
|
|
41
41
|
};
|
|
42
42
|
}
|
|
@@ -47,7 +47,8 @@ export class Nexly {
|
|
|
47
47
|
return sendPageViewBeacon(this.credentials, path ?? getDefaultPathname());
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
-
* Sends a custom event. Default context is
|
|
50
|
+
* Sends a custom event. Default context is per-event meta + path; pass `context` to merge or override fields.
|
|
51
|
+
* Includes session_context so the backend can upsert session metadata.
|
|
51
52
|
*/
|
|
52
53
|
event(input) {
|
|
53
54
|
const context = input.context
|
|
@@ -60,6 +61,7 @@ export class Nexly {
|
|
|
60
61
|
eventType: input.type,
|
|
61
62
|
context,
|
|
62
63
|
data: input.data ?? {},
|
|
64
|
+
sessionContext: collectSessionMeta(),
|
|
63
65
|
});
|
|
64
66
|
}
|
|
65
67
|
/**
|