@v-tilt/browser 1.11.0 → 1.13.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/all-external-dependencies.js +1 -1
- package/dist/all-external-dependencies.js.map +1 -1
- package/dist/array.full.js +1 -1
- package/dist/array.full.js.map +1 -1
- package/dist/array.js +1 -1
- package/dist/array.js.map +1 -1
- package/dist/array.no-external.js +1 -1
- package/dist/array.no-external.js.map +1 -1
- package/dist/autocapture-types.d.ts +17 -0
- package/dist/autocapture-utils.d.ts +24 -1
- package/dist/autocapture.d.ts +94 -5
- package/dist/chat.js +1 -1
- package/dist/chat.js.map +1 -1
- package/dist/config.d.ts +8 -1
- package/dist/constants.d.ts +19 -13
- package/dist/core/capture.d.ts +15 -5
- package/dist/core/config-utils.d.ts +15 -0
- package/dist/core/consent.d.ts +62 -0
- package/dist/core/event-buffer.d.ts +60 -0
- package/dist/core/fb-cookies.d.ts +32 -0
- package/dist/core/feature-manager.d.ts +61 -69
- package/dist/core/fifo-queue.d.ts +23 -0
- package/dist/core/identity.d.ts +23 -33
- package/dist/core/index.d.ts +7 -1
- package/dist/core/page-lifecycle.d.ts +41 -0
- package/dist/core/remote-config.d.ts +14 -17
- package/dist/extensions/chat/bubble-drag.d.ts +30 -0
- package/dist/extensions/chat/chat-api.d.ts +15 -0
- package/dist/extensions/chat/chat-styles.d.ts +27 -0
- package/dist/extensions/chat/chat-wrapper.d.ts +20 -145
- package/dist/extensions/chat/chat.d.ts +261 -14
- package/dist/extensions/chat/message-content-styles.d.ts +1 -0
- package/dist/extensions/chat/message-html.d.ts +6 -0
- package/dist/extensions/chat/message-markdown.d.ts +8 -0
- package/dist/extensions/chat/normalize-send-content.d.ts +24 -0
- package/dist/extensions/chat/types.d.ts +19 -57
- package/dist/extensions/chat/widget-registry.d.ts +53 -0
- package/dist/extensions/chat/widgets/collect-email.d.ts +6 -0
- package/dist/extensions/chat/widgets/escalate-to-human.d.ts +6 -0
- package/dist/extensions/ga4-proxy.d.ts +59 -0
- package/dist/extensions/google-tag-gateway/consent-bridge.d.ts +27 -0
- package/dist/extensions/google-tag-gateway/enhanced-conversions.d.ts +35 -0
- package/dist/extensions/google-tag-gateway/event-bridge.d.ts +74 -0
- package/dist/extensions/google-tag-gateway/google-tag-gateway.d.ts +95 -0
- package/dist/extensions/google-tag-gateway/gtag-loader.d.ts +85 -0
- package/dist/extensions/google-tag-gateway/index.d.ts +7 -0
- package/dist/extensions/google-tag-gateway/normalize.d.ts +28 -0
- package/dist/extensions/google-tag-gateway/public-api.d.ts +23 -0
- package/dist/extensions/history-autocapture.d.ts +2 -2
- package/dist/extensions/replay/index.d.ts +1 -1
- package/dist/extensions/replay/session-recording-utils.d.ts +13 -43
- package/dist/extensions/replay/session-recording-wrapper.d.ts +10 -66
- package/dist/extensions/replay/session-recording.d.ts +53 -1
- package/dist/extensions/replay/types.d.ts +6 -1
- package/dist/extensions/web-vitals/web-vitals-manager.d.ts +14 -43
- package/dist/external-scripts-loader.js +1 -1
- package/dist/external-scripts-loader.js.map +1 -1
- package/dist/feature.d.ts +54 -172
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/module.d.ts +728 -753
- package/dist/module.js +1 -1
- package/dist/module.js.map +1 -1
- package/dist/module.no-external.d.ts +728 -753
- package/dist/module.no-external.js +1 -1
- package/dist/module.no-external.js.map +1 -1
- package/dist/rate-limiter.d.ts +0 -1
- package/dist/recorder.js +1 -1
- package/dist/recorder.js.map +1 -1
- package/dist/request.d.ts +34 -20
- package/dist/scroll-depth-tracker.d.ts +42 -0
- package/dist/server.d.ts +114 -0
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/session.d.ts +12 -0
- package/dist/types.d.ts +204 -9
- package/dist/user-manager.d.ts +26 -52
- package/dist/utils/base64.d.ts +30 -0
- package/dist/utils/bot-detection.d.ts +28 -0
- package/dist/utils/endpoint-url.d.ts +36 -0
- package/dist/utils/event-emitter.d.ts +1 -0
- package/dist/utils/globals.d.ts +71 -2
- package/dist/utils/index.d.ts +20 -5
- package/dist/utils/logger.d.ts +66 -0
- package/dist/utils/request-utils.d.ts +5 -0
- package/dist/utils/safewrap.d.ts +6 -1
- package/dist/utils/transport-health.d.ts +55 -0
- package/dist/vtilt.d.ts +85 -25
- package/dist/web-vitals.js.map +1 -1
- package/package.json +71 -66
package/dist/config.d.ts
CHANGED
|
@@ -3,7 +3,14 @@ export declare class ConfigManager {
|
|
|
3
3
|
private config;
|
|
4
4
|
constructor(config?: Partial<VTiltConfig>);
|
|
5
5
|
/**
|
|
6
|
-
* Parse configuration from script attributes
|
|
6
|
+
* Parse configuration from script attributes.
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT: do not back-fill `log_level` with a resolved default here.
|
|
9
|
+
* `log_level` in VTiltConfig represents the integrator's explicit intent —
|
|
10
|
+
* `setLevelFromConfig` (logger.ts) treats `log_level !== undefined` as
|
|
11
|
+
* "integrator pinned the level", which then locks remote /decide overrides.
|
|
12
|
+
* Baking in `'warn'` for every integrator who didn't pass anything would
|
|
13
|
+
* silently disable dashboard-driven log-level changes via diagnostics.
|
|
7
14
|
*/
|
|
8
15
|
private parseConfigFromScript;
|
|
9
16
|
/**
|
package/dist/constants.d.ts
CHANGED
|
@@ -57,14 +57,6 @@ export declare const PERSISTENCE_METHODS: {
|
|
|
57
57
|
sessionStorage: "sessionStorage";
|
|
58
58
|
memory: "memory";
|
|
59
59
|
};
|
|
60
|
-
/** @deprecated Use PERSISTENCE_METHODS instead */
|
|
61
|
-
export declare const STORAGE_METHODS: {
|
|
62
|
-
cookie: "cookie";
|
|
63
|
-
localStorage: "localStorage";
|
|
64
|
-
localStoragePlusCookie: "localStorage+cookie";
|
|
65
|
-
sessionStorage: "sessionStorage";
|
|
66
|
-
memory: "memory";
|
|
67
|
-
};
|
|
68
60
|
/** Enable person processing flag */
|
|
69
61
|
export declare const ENABLE_PERSON_PROCESSING = "$epp";
|
|
70
62
|
/** Initial person info (referrer, URL, UTM params) */
|
|
@@ -87,23 +79,25 @@ export declare const EVENT_PAGELEAVE = "$pageleave";
|
|
|
87
79
|
/** Identify event */
|
|
88
80
|
export declare const EVENT_IDENTIFY = "$identify";
|
|
89
81
|
/** Alias event */
|
|
90
|
-
export declare const EVENT_ALIAS = "$
|
|
82
|
+
export declare const EVENT_ALIAS = "$alias";
|
|
91
83
|
/** Set person properties event */
|
|
92
84
|
export declare const EVENT_SET = "$set";
|
|
93
|
-
/** Group identify event */
|
|
94
|
-
export declare const EVENT_GROUP_IDENTIFY = "$groupidentify";
|
|
95
85
|
/** Performance event */
|
|
96
86
|
export declare const EVENT_PERFORMANCE = "$performance_event";
|
|
87
|
+
/** Autocapture event */
|
|
88
|
+
export declare const EVENT_AUTOCAPTURE = "$autocapture";
|
|
89
|
+
/** Scroll depth milestone event (autocapture) */
|
|
90
|
+
export declare const EVENT_SCROLL_DEPTH = "$scroll_depth";
|
|
97
91
|
/** Snapshot event (session recording) */
|
|
98
92
|
export declare const EVENT_SNAPSHOT = "$snapshot";
|
|
93
|
+
/** Snapshot batch items event */
|
|
94
|
+
export declare const EVENT_SNAPSHOT_ITEMS = "$snapshot_items";
|
|
99
95
|
/** Rate limit warning event */
|
|
100
96
|
export declare const EVENT_RATE_LIMIT_WARNING = "$$client_ingestion_warning";
|
|
101
97
|
/** Process person profile flag */
|
|
102
98
|
export declare const PROP_PROCESS_PERSON_PROFILE = "$process_person_profile";
|
|
103
99
|
/** Is identified flag */
|
|
104
100
|
export declare const PROP_IS_IDENTIFIED = "$is_identified";
|
|
105
|
-
/** Anonymous distinct ID */
|
|
106
|
-
export declare const PROP_ANON_DISTINCT_ID = "$anon_distinct_id";
|
|
107
101
|
/** Session ID property */
|
|
108
102
|
export declare const PROP_SESSION_ID = "$session_id";
|
|
109
103
|
/** Window ID property */
|
|
@@ -114,6 +108,18 @@ export declare const PROP_CURRENT_URL = "$current_url";
|
|
|
114
108
|
export declare const PROP_HOST = "$host";
|
|
115
109
|
/** Pathname */
|
|
116
110
|
export declare const PROP_PATHNAME = "$pathname";
|
|
111
|
+
/** Seconds on the page being left ($pageleave) */
|
|
112
|
+
export declare const PROP_PREV_PAGEVIEW_DURATION = "$prev_pageview_duration";
|
|
113
|
+
/** Pathname of the page being left */
|
|
114
|
+
export declare const PROP_PREV_PAGEVIEW_PATHNAME = "$prev_pageview_pathname";
|
|
115
|
+
/** URL of the page being left */
|
|
116
|
+
export declare const PROP_PREV_PAGEVIEW_URL = "$prev_pageview_url";
|
|
117
|
+
/** Scroll depth milestone threshold (0–100) */
|
|
118
|
+
export declare const PROP_SCROLL_DEPTH_PCT = "$scroll_depth_pct";
|
|
119
|
+
/** Max scroll depth % at time of milestone event */
|
|
120
|
+
export declare const PROP_SCROLL_DEPTH_MAX_PCT = "$scroll_depth_max_pct";
|
|
121
|
+
/** Max scroll depth % on the page being left ($pageleave) */
|
|
122
|
+
export declare const PROP_PREV_PAGEVIEW_SCROLL_DEPTH_PCT = "$prev_pageview_scroll_depth_pct";
|
|
117
123
|
/** Referrer URL */
|
|
118
124
|
export declare const PROP_REFERRER = "$referrer";
|
|
119
125
|
/** Referring domain */
|
package/dist/core/capture.d.ts
CHANGED
|
@@ -15,21 +15,31 @@ export interface CaptureHost {
|
|
|
15
15
|
setSessionId(): void;
|
|
16
16
|
getSessionId(): string | null;
|
|
17
17
|
getWindowId(): string;
|
|
18
|
+
consumeSessionStart(): boolean;
|
|
18
19
|
};
|
|
19
20
|
userManager: {
|
|
20
21
|
getAnonymousId(): string;
|
|
21
22
|
getDistinctId(): string | null;
|
|
22
23
|
getUserProperties(): Record<string, any>;
|
|
23
24
|
get_initial_props(): Record<string, any>;
|
|
25
|
+
consumeFirstVisit(): boolean;
|
|
26
|
+
};
|
|
27
|
+
consentManager?: {
|
|
28
|
+
hasConsent(): boolean;
|
|
29
|
+
getConsentProperties(): Record<string, boolean>;
|
|
24
30
|
};
|
|
25
31
|
rateLimiter: {
|
|
26
32
|
shouldAllowEvent(): boolean;
|
|
27
33
|
};
|
|
28
|
-
sendRequest(url: string, event: TrackingEvent
|
|
34
|
+
sendRequest(url: string, event: TrackingEvent): void;
|
|
35
|
+
bufferEvent(name: string, url: string, event: TrackingEvent): void;
|
|
29
36
|
buildUrl(): string;
|
|
37
|
+
buildEndpointUrl(path: string): string;
|
|
30
38
|
}
|
|
31
39
|
export interface CaptureOptions {
|
|
32
40
|
skip_client_rate_limiting?: boolean;
|
|
41
|
+
/** When true, do not add inter-capture engagement_time_msec (e.g. $pageleave uses dwell). */
|
|
42
|
+
skip_engagement?: boolean;
|
|
33
43
|
}
|
|
34
44
|
export declare class CaptureManager {
|
|
35
45
|
private _host;
|
|
@@ -37,6 +47,7 @@ export declare class CaptureManager {
|
|
|
37
47
|
private _initial_pageview_captured;
|
|
38
48
|
private _visibility_state_listener;
|
|
39
49
|
private _vt_person_id;
|
|
50
|
+
private readonly _pageLifecycle;
|
|
40
51
|
constructor(host: CaptureHost);
|
|
41
52
|
/** Set the vt person ID from URL parameter */
|
|
42
53
|
setVtPersonId(id: string | null): void;
|
|
@@ -54,15 +65,14 @@ export declare class CaptureManager {
|
|
|
54
65
|
* Used for system events like rate limit warnings.
|
|
55
66
|
*/
|
|
56
67
|
captureInternal(name: string, payload: EventPayload): void;
|
|
57
|
-
/**
|
|
58
|
-
* Track a custom event (alias for capture).
|
|
59
|
-
*/
|
|
60
|
-
trackEvent(name: string, payload?: EventPayload): void;
|
|
61
68
|
/**
|
|
62
69
|
* Capture initial pageview with visibility check.
|
|
63
70
|
* Waits for page to become visible before capturing.
|
|
64
71
|
*/
|
|
65
72
|
captureInitialPageview(): void;
|
|
73
|
+
tryCapturePageleave(reason: string, extraProps?: EventPayload): void;
|
|
74
|
+
resetPageleaveDedupe(): void;
|
|
75
|
+
private _isDebugMode;
|
|
66
76
|
/**
|
|
67
77
|
* Build enriched event payload with all common properties.
|
|
68
78
|
*/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolved config helpers (VTiltConfig may contain sentinel values like
|
|
3
|
+
* `if_capture_pageview` that are not booleans until interpreted).
|
|
4
|
+
*/
|
|
5
|
+
import type { VTiltConfig } from "../types";
|
|
6
|
+
/**
|
|
7
|
+
* Whether automatic $pageleave should run.
|
|
8
|
+
* - `capture_pageleave === false` → off
|
|
9
|
+
* - `capture_pageleave === true` → on
|
|
10
|
+
* - `undefined` or `'if_capture_pageview'` → on iff pageviews are enabled
|
|
11
|
+
*
|
|
12
|
+
* Server-side $config_pending filter handles the edge case where events
|
|
13
|
+
* are captured before fresh remote config loads.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isPageleaveEnabled(config: VTiltConfig): boolean;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consent Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages user consent state for analytics, marketing, and advertising.
|
|
5
|
+
* Stores consent in a first-party cookie (_vtilt_consent) and provides
|
|
6
|
+
* consent properties to attach to every event.
|
|
7
|
+
*
|
|
8
|
+
* When `requireConsent` is true in config, the CaptureManager gates
|
|
9
|
+
* non-essential events until setConsent() is called.
|
|
10
|
+
*/
|
|
11
|
+
export interface ConsentState {
|
|
12
|
+
analytics?: boolean;
|
|
13
|
+
marketing?: boolean;
|
|
14
|
+
advertising?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface ConsentHost {
|
|
17
|
+
_emitter?: {
|
|
18
|
+
emit(event: string, payload?: unknown): void;
|
|
19
|
+
};
|
|
20
|
+
getConfig(): {
|
|
21
|
+
require_consent?: boolean;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export declare class ConsentManager {
|
|
25
|
+
private _host;
|
|
26
|
+
private _state;
|
|
27
|
+
private _hasBeenSet;
|
|
28
|
+
constructor(host: ConsentHost);
|
|
29
|
+
/**
|
|
30
|
+
* Set consent state. Merges with existing state.
|
|
31
|
+
* Persists to cookie and emits consent:updated.
|
|
32
|
+
*/
|
|
33
|
+
setConsent(consent: ConsentState): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get current consent state.
|
|
36
|
+
* Returns undefined fields for categories not yet set.
|
|
37
|
+
*/
|
|
38
|
+
getConsent(): ConsentState;
|
|
39
|
+
/**
|
|
40
|
+
* Whether setConsent() has been called (or consent was loaded from cookie).
|
|
41
|
+
* Used by CaptureManager to gate events when requireConsent is true.
|
|
42
|
+
*/
|
|
43
|
+
hasConsent(): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Apply default-all-granted state when no explicit consent exists.
|
|
46
|
+
* Sets all categories to true in memory but does NOT persist to cookie
|
|
47
|
+
* (implicit defaults don't need storage — only explicit user choices do).
|
|
48
|
+
*/
|
|
49
|
+
setDefaultGranted(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Returns event properties to attach to every captured event.
|
|
52
|
+
* Only includes fields that have been explicitly set.
|
|
53
|
+
*/
|
|
54
|
+
getConsentProperties(): Record<string, boolean>;
|
|
55
|
+
/**
|
|
56
|
+
* Reset consent state (e.g. on user logout).
|
|
57
|
+
*/
|
|
58
|
+
reset(): void;
|
|
59
|
+
private _readFromCookie;
|
|
60
|
+
private _writeToCookie;
|
|
61
|
+
private _removeCookie;
|
|
62
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Buffer
|
|
3
|
+
*
|
|
4
|
+
* Buffers events until fresh remote config is resolved. Ensures every
|
|
5
|
+
* event respects current project config.
|
|
6
|
+
*
|
|
7
|
+
* Ready condition:
|
|
8
|
+
* - _configReady: fresh /api/d response applied (or fetch failed)
|
|
9
|
+
*
|
|
10
|
+
* When config IS ready, queued events are filtered against the resolved
|
|
11
|
+
* analytics toggles (capture_pageview, capture_pageleave, etc.) and
|
|
12
|
+
* dropped if disabled — mirroring the server-side $config_pending filter.
|
|
13
|
+
*
|
|
14
|
+
* Events that flush before config is ready (safety timeout, page unload)
|
|
15
|
+
* are tagged with $config_pending for server-side filtering.
|
|
16
|
+
*/
|
|
17
|
+
import type { TrackingEvent, VTiltConfig } from "../types";
|
|
18
|
+
export interface BufferedEvent {
|
|
19
|
+
name: string;
|
|
20
|
+
url: string;
|
|
21
|
+
event: TrackingEvent;
|
|
22
|
+
}
|
|
23
|
+
export interface EventBufferHost {
|
|
24
|
+
sendRequest(url: string, event: TrackingEvent): void;
|
|
25
|
+
requestQueue: {
|
|
26
|
+
flush(): void;
|
|
27
|
+
};
|
|
28
|
+
getConfig(): VTiltConfig;
|
|
29
|
+
}
|
|
30
|
+
export declare class EventBuffer {
|
|
31
|
+
private _host;
|
|
32
|
+
private readonly _queue;
|
|
33
|
+
private _ready;
|
|
34
|
+
private _configReady;
|
|
35
|
+
private _safetyTimer;
|
|
36
|
+
constructor(host: EventBufferHost);
|
|
37
|
+
/**
|
|
38
|
+
* Push an event into the buffer.
|
|
39
|
+
* If ready, processes inline (pass-through). Otherwise queues.
|
|
40
|
+
*/
|
|
41
|
+
push(item: BufferedEvent): void;
|
|
42
|
+
/** Signal that fresh remote config has been loaded (or fetch failed). */
|
|
43
|
+
markConfigReady(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Force-flush all buffered events (page unload / safety timeout).
|
|
46
|
+
* Tags events with $config_pending when config hasn't loaded.
|
|
47
|
+
*/
|
|
48
|
+
forceFlush(): void;
|
|
49
|
+
private _checkReady;
|
|
50
|
+
private _tryFlush;
|
|
51
|
+
private _flush;
|
|
52
|
+
private _process;
|
|
53
|
+
/**
|
|
54
|
+
* Check whether the event should be dropped based on resolved config.
|
|
55
|
+
* Mirrors the server-side checkProjectConfigFilter logic.
|
|
56
|
+
*/
|
|
57
|
+
private _isDisabledByConfig;
|
|
58
|
+
private _tagConfigPending;
|
|
59
|
+
private _clearSafetyTimer;
|
|
60
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Facebook Cookie Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages _fbp (Facebook Browser ID) and _fbc (Facebook Click ID) cookies
|
|
5
|
+
* as first-party cookies for server-side Facebook CAPI integration.
|
|
6
|
+
*
|
|
7
|
+
* _fbp format: fb.1.{creation_timestamp_ms}.{random_10_digits}
|
|
8
|
+
* - Set on first visit, 180-day expiry (Meta spec)
|
|
9
|
+
*
|
|
10
|
+
* _fbc format: fb.1.{click_timestamp_ms}.{fbclid}
|
|
11
|
+
* - Set when fbclid URL parameter is present, 90-day expiry (Meta spec)
|
|
12
|
+
* - Persisted so CAPI events carry the correct click timestamp
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Initialize Facebook cookies on SDK boot.
|
|
16
|
+
* - Generates _fbp if missing
|
|
17
|
+
* - Persists _fbc from fbclid URL parameter if present
|
|
18
|
+
*/
|
|
19
|
+
export declare function initFacebookCookies(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Read the current _fbp cookie value.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getFbp(): string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Read the current _fbc cookie value.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getFbc(): string | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Remove both _fbp and _fbc cookies.
|
|
30
|
+
* Called when advertising consent is revoked.
|
|
31
|
+
*/
|
|
32
|
+
export declare function removeFacebookCookies(): void;
|
|
@@ -1,95 +1,87 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Feature Manager
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Central registry for SDK features. Features self-describe via descriptors
|
|
5
|
+
* that declare their config keys, remote config mappings, and class references.
|
|
6
|
+
*
|
|
7
|
+
* Responsibilities:
|
|
8
|
+
* - Registration: features register descriptors before init
|
|
9
|
+
* - Instance creation: createInstances() constructs instances during init() (pre-boot)
|
|
10
|
+
* - Starting: initAll() starts created instances at boot via startIfEnabled
|
|
11
|
+
* - Config propagation: notifyAll() calls onConfigUpdate on each instance
|
|
12
|
+
* - Descriptor exposure: getDescriptors() lets RemoteConfigManager._apply iterate
|
|
13
|
+
*
|
|
14
|
+
* @see docs/patterns/tracker-feature-lifecycle.md
|
|
7
15
|
*/
|
|
8
|
-
import { VTiltConfig
|
|
16
|
+
import type { VTiltConfig } from "../types";
|
|
9
17
|
import type { Feature } from "../feature";
|
|
10
18
|
/**
|
|
11
|
-
*
|
|
19
|
+
* Self-describing metadata for a feature.
|
|
20
|
+
* Declared once at registration time; used by FeatureManager and RemoteConfigManager.
|
|
12
21
|
*/
|
|
13
|
-
export interface
|
|
14
|
-
|
|
15
|
-
extractConfig?(config: VTiltConfig): any;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Feature registration entry
|
|
19
|
-
*/
|
|
20
|
-
export interface FeatureEntry<T extends Feature = Feature> {
|
|
22
|
+
export interface FeatureDescriptor {
|
|
23
|
+
/** Unique name (used as map key and for get()) */
|
|
21
24
|
name: string;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
isExtension?: boolean;
|
|
26
|
-
/** Config key to check for disabled state */
|
|
25
|
+
/** VTiltConfig key that holds this feature's config (e.g. "session_recording") */
|
|
26
|
+
configKey?: keyof VTiltConfig;
|
|
27
|
+
/** VTiltConfig boolean key that hard-disables the feature (e.g. "disable_session_recording") */
|
|
27
28
|
disableKey?: keyof VTiltConfig;
|
|
28
|
-
/**
|
|
29
|
-
|
|
29
|
+
/** Remote config mapping — tells _apply how to extract config from RemoteConfig */
|
|
30
|
+
remoteConfig?: {
|
|
31
|
+
/** Key on the RemoteConfig object (e.g. "sessionRecording") */
|
|
32
|
+
key: string;
|
|
33
|
+
/** Transform remote section into the shape written to VTiltConfig[configKey] */
|
|
34
|
+
map: (remote: Record<string, unknown>) => Record<string, unknown>;
|
|
35
|
+
};
|
|
36
|
+
/** Feature class — must have a static extractConfig and a constructor */
|
|
37
|
+
FeatureClass: {
|
|
38
|
+
new (instance: any, config?: any): Feature;
|
|
39
|
+
extractConfig(config: VTiltConfig): any;
|
|
40
|
+
};
|
|
30
41
|
}
|
|
31
42
|
/**
|
|
32
|
-
*
|
|
43
|
+
* Minimal host interface to avoid circular dependency with VTilt.
|
|
33
44
|
*/
|
|
34
45
|
export interface FeatureHost {
|
|
35
46
|
getConfig(): VTiltConfig;
|
|
36
47
|
}
|
|
37
48
|
export declare class FeatureManager {
|
|
38
49
|
private _host;
|
|
39
|
-
private
|
|
40
|
-
private
|
|
41
|
-
private _onFeatureStopped?;
|
|
50
|
+
private _descriptors;
|
|
51
|
+
private _instances;
|
|
42
52
|
constructor(host: FeatureHost);
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
/** Set callback for when a feature stops */
|
|
46
|
-
onFeatureStopped(callback: (name: string) => void): void;
|
|
53
|
+
/** Register a feature descriptor. Call before initAll(). */
|
|
54
|
+
register(desc: FeatureDescriptor): void;
|
|
47
55
|
/**
|
|
48
|
-
*
|
|
56
|
+
* Create instances for all registered features without starting them.
|
|
57
|
+
* Safe to call before DOM boot — constructors are lightweight.
|
|
58
|
+
* Idempotent: skips features that already have an instance.
|
|
59
|
+
*
|
|
60
|
+
* Hard-disabled features are skipped (instance not created):
|
|
61
|
+
* - `disableKey` is true (e.g. `disable_chat: true`)
|
|
62
|
+
* - `configKey` section has `enabled: false` (e.g. `chat: { enabled: false }`)
|
|
49
63
|
*/
|
|
50
|
-
|
|
64
|
+
createInstances(): void;
|
|
51
65
|
/**
|
|
52
|
-
*
|
|
53
|
-
|
|
54
|
-
get<T extends Feature>(name: string): T | undefined;
|
|
55
|
-
/**
|
|
56
|
-
* Initialize all registered features.
|
|
66
|
+
* Create and start all registered features.
|
|
67
|
+
* Calls `createInstances()` first (idempotent), then `startIfEnabled()` on each.
|
|
57
68
|
*/
|
|
58
69
|
initAll(): void;
|
|
70
|
+
/** Notify all initialized features of a config change. */
|
|
71
|
+
notifyAll(config: VTiltConfig): void;
|
|
72
|
+
/** Get a feature instance by name. */
|
|
73
|
+
get<T extends Feature>(name: string): T | undefined;
|
|
74
|
+
/** Register a late-created feature instance (e.g. from a public start*() call). */
|
|
75
|
+
set(name: string, instance: Feature): void;
|
|
76
|
+
/** Expose descriptors so RemoteConfigManager._apply can iterate for remote config mapping. */
|
|
77
|
+
getDescriptors(): Map<string, FeatureDescriptor>;
|
|
59
78
|
/**
|
|
60
|
-
*
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
*
|
|
65
|
-
|
|
66
|
-
start(name: string): void;
|
|
67
|
-
/**
|
|
68
|
-
* Stop a feature by name.
|
|
69
|
-
*/
|
|
70
|
-
stop(name: string): void;
|
|
71
|
-
/**
|
|
72
|
-
* Check if a feature is active.
|
|
73
|
-
*/
|
|
74
|
-
isActive(name: string): boolean;
|
|
75
|
-
/**
|
|
76
|
-
* Notify all features of configuration update.
|
|
77
|
-
*/
|
|
78
|
-
notifyConfigUpdate(config: VTiltConfig): void;
|
|
79
|
-
/**
|
|
80
|
-
* Notify all features of remote configuration update.
|
|
81
|
-
*/
|
|
82
|
-
notifyRemoteConfig(remote: RemoteConfig): void;
|
|
83
|
-
/**
|
|
84
|
-
* Get all feature instances.
|
|
85
|
-
*/
|
|
86
|
-
getAll(): Feature[];
|
|
87
|
-
/**
|
|
88
|
-
* Initialize a single feature.
|
|
79
|
+
* True when the integrator explicitly hard-disabled this feature in code config.
|
|
80
|
+
* Two signals: `disableKey` flag (e.g. `disable_chat: true`) or
|
|
81
|
+
* `configKey` section with `enabled: false` (e.g. `chat: { enabled: false }`).
|
|
82
|
+
*
|
|
83
|
+
* When `enabled` is omitted (undefined), the feature may still auto-configure
|
|
84
|
+
* from dashboard settings, so we must construct the instance.
|
|
89
85
|
*/
|
|
90
|
-
private
|
|
86
|
+
private _isHardDisabled;
|
|
91
87
|
}
|
|
92
|
-
/**
|
|
93
|
-
* Create and configure a FeatureManager with standard vTilt features.
|
|
94
|
-
*/
|
|
95
|
-
export declare function createFeatureManager(host: FeatureHost): FeatureManager;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory FIFO used by transport layers that must not drop ordering
|
|
3
|
+
* (EventBuffer, GoogleTagGateway pending captures).
|
|
4
|
+
*
|
|
5
|
+
* - Optional capacity: when full, {@link FifoQueue.enqueue} returns false
|
|
6
|
+
* and the item is not stored (same semantics as the previous hand-rolled
|
|
7
|
+
* `length < max` checks).
|
|
8
|
+
* - Default capacity is unbounded (`Number.POSITIVE_INFINITY`).
|
|
9
|
+
*/
|
|
10
|
+
export declare class FifoQueue<T> {
|
|
11
|
+
private readonly _maxItems;
|
|
12
|
+
private _items;
|
|
13
|
+
constructor(_maxItems?: number);
|
|
14
|
+
get length(): number;
|
|
15
|
+
/** Append one item when under capacity. */
|
|
16
|
+
enqueue(item: T): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Atomically remove every item in arrival order. Returns a new array
|
|
19
|
+
* reference owned by the caller; the queue is empty after this call.
|
|
20
|
+
*/
|
|
21
|
+
takeAll(): T[];
|
|
22
|
+
clear(): void;
|
|
23
|
+
}
|
package/dist/core/identity.d.ts
CHANGED
|
@@ -1,74 +1,64 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Identity Manager
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Orchestrates user identification, property updates, and alias creation.
|
|
5
|
+
* All state lives in UserManager; this layer owns validation, dedup,
|
|
6
|
+
* event capture, and lifecycle events.
|
|
7
7
|
*/
|
|
8
|
-
import { EventPayload } from "../types";
|
|
8
|
+
import type { EventPayload, IdentityUpdate } from "../types";
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* Minimal interface for the VTilt host.
|
|
11
|
+
* Avoids circular dependency while giving IdentityManager access to
|
|
12
|
+
* capture, user state reads, batched writes, session reset, and events.
|
|
12
13
|
*/
|
|
13
14
|
export interface IdentityHost {
|
|
14
15
|
capture(name: string, payload: EventPayload): void;
|
|
15
16
|
userManager: {
|
|
16
17
|
getDistinctId(): string | null;
|
|
17
|
-
setDistinctId(id: string): void;
|
|
18
18
|
getAnonymousId(): string;
|
|
19
19
|
getDeviceId(): string;
|
|
20
|
-
ensureDeviceId(id: string): void;
|
|
21
20
|
getUserState(): "anonymous" | "identified";
|
|
22
|
-
setUserState(state: "anonymous" | "identified"): void;
|
|
23
21
|
getUserIdentity(): Record<string, any>;
|
|
24
22
|
getUserProperties(): Record<string, any>;
|
|
25
|
-
|
|
26
|
-
setUserProperties(set?: Record<string, any>, setOnce?: Record<string, any>): boolean;
|
|
27
|
-
isDistinctIdStringLikePublic(id: string): boolean;
|
|
28
|
-
createAlias(alias: string, original?: string): {
|
|
29
|
-
distinct_id: string;
|
|
30
|
-
original: string;
|
|
31
|
-
} | null;
|
|
23
|
+
applyUpdate(update: IdentityUpdate): void;
|
|
32
24
|
reset(resetDeviceId?: boolean): void;
|
|
33
25
|
};
|
|
34
26
|
sessionManager: {
|
|
35
27
|
resetSessionId(): void;
|
|
36
28
|
};
|
|
37
29
|
_emitter?: {
|
|
38
|
-
emit(event: string, payload?:
|
|
30
|
+
emit(event: string, payload?: unknown): void;
|
|
39
31
|
};
|
|
40
32
|
}
|
|
41
33
|
export declare class IdentityManager {
|
|
42
34
|
private _host;
|
|
35
|
+
private _lastIdentifyHash;
|
|
36
|
+
private _lastSetPropertiesHash;
|
|
43
37
|
constructor(host: IdentityHost);
|
|
44
38
|
/**
|
|
45
|
-
* Identify a user
|
|
46
|
-
* Sends $identify event when transitioning from anonymous to identified.
|
|
39
|
+
* Identify a user.
|
|
47
40
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
41
|
+
* - Anonymous → identified: sends $identify (merge), persists after capture.
|
|
42
|
+
* - Already identified, different user: sends $identify (re-identify).
|
|
43
|
+
* - Same user, new properties only: delegates to setUserProperties.
|
|
44
|
+
* - Identical consecutive calls are deduplicated (React re-render safety).
|
|
51
45
|
*/
|
|
52
46
|
identify(newDistinctId?: string, userPropertiesToSet?: Record<string, any>, userPropertiesToSetOnce?: Record<string, any>): void;
|
|
53
47
|
/**
|
|
54
48
|
* Set user properties without changing identity.
|
|
49
|
+
* Dedup mirrors identify: identical consecutive calls are skipped.
|
|
55
50
|
*/
|
|
56
51
|
setUserProperties(userPropertiesToSet?: Record<string, any>, userPropertiesToSetOnce?: Record<string, any>): void;
|
|
57
52
|
/**
|
|
58
|
-
* Reset
|
|
59
|
-
* Clears
|
|
60
|
-
*
|
|
61
|
-
* @param reset_device_id - If true, also resets device_id
|
|
53
|
+
* Reset identity (logout).
|
|
54
|
+
* Clears user data, generates new anonymous ID, resets session.
|
|
62
55
|
*/
|
|
63
|
-
resetUser(
|
|
56
|
+
resetUser(resetDeviceId?: boolean): void;
|
|
64
57
|
/**
|
|
65
|
-
* Create an alias
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* @param alias - A unique identifier that you want to use for this user
|
|
69
|
-
* @param original - The current identifier being used (optional)
|
|
58
|
+
* Create an alias linking two distinct IDs.
|
|
59
|
+
* If alias matches current identity, falls back to identify().
|
|
70
60
|
*/
|
|
71
|
-
|
|
61
|
+
alias(alias: string, original?: string): void;
|
|
72
62
|
getUserIdentity(): Record<string, any>;
|
|
73
63
|
getDeviceId(): string;
|
|
74
64
|
getUserState(): "anonymous" | "identified";
|
package/dist/core/index.d.ts
CHANGED
|
@@ -10,4 +10,10 @@
|
|
|
10
10
|
export { RemoteConfigManager, type RemoteConfigHost, type RemoteConfigCallback, } from "./remote-config";
|
|
11
11
|
export { CaptureManager, type CaptureHost, type CaptureOptions, } from "./capture";
|
|
12
12
|
export { IdentityManager, type IdentityHost } from "./identity";
|
|
13
|
-
export {
|
|
13
|
+
export { ConsentManager, type ConsentHost, type ConsentState } from "./consent";
|
|
14
|
+
export { initFacebookCookies, removeFacebookCookies, getFbp, getFbc, } from "./fb-cookies";
|
|
15
|
+
export { FeatureManager, type FeatureHost, type FeatureDescriptor, } from "./feature-manager";
|
|
16
|
+
export { isPageleaveEnabled } from "./config-utils";
|
|
17
|
+
export { PageLifecycleTracker } from "./page-lifecycle";
|
|
18
|
+
export { EventBuffer, type EventBufferHost, type BufferedEvent, } from "./event-buffer";
|
|
19
|
+
export { FifoQueue } from "./fifo-queue";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page context, dwell time, and inter-event engagement for GA4-style metrics.
|
|
3
|
+
*/
|
|
4
|
+
import type { EventPayload } from "../types";
|
|
5
|
+
import type { VTiltConfig } from "../types";
|
|
6
|
+
export interface PageleaveCaptureFn {
|
|
7
|
+
(name: string, payload: EventPayload, options?: {
|
|
8
|
+
skip_engagement?: boolean;
|
|
9
|
+
}): void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Tracks time on current URL and milliseconds since last capture for engagement_time_msec.
|
|
13
|
+
*/
|
|
14
|
+
export declare class PageLifecycleTracker {
|
|
15
|
+
private _pageEnterPerf;
|
|
16
|
+
/** Null until first engagement-consuming event; then wall clock for next delta */
|
|
17
|
+
private _lastCapturePerf;
|
|
18
|
+
private readonly _bootPerf;
|
|
19
|
+
private _prevUrl;
|
|
20
|
+
private _prevPathname;
|
|
21
|
+
private _prevTitle;
|
|
22
|
+
/** Dedupe pagehide + visibility hidden for the same page */
|
|
23
|
+
private _leaveEmittedForPageKey;
|
|
24
|
+
/**
|
|
25
|
+
* Call after a $pageview is sent (initial or SPA) to reset dwell timer and snapshot.
|
|
26
|
+
*/
|
|
27
|
+
onAfterPageview(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Milliseconds since last capture (or since boot on the first event). Does not advance the clock.
|
|
30
|
+
*/
|
|
31
|
+
peekEngagementSinceLastCaptureMs(): number;
|
|
32
|
+
/** Call after a capture is enqueued so the next peek measures from this point. */
|
|
33
|
+
commitCaptureClock(): void;
|
|
34
|
+
private _pageKey;
|
|
35
|
+
/** Call when the tab becomes visible again so a later hide can emit another $pageleave. */
|
|
36
|
+
clearLeaveDedupe(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Fire $pageleave if enabled and not already emitted for this page.
|
|
39
|
+
*/
|
|
40
|
+
tryCapturePageleave(config: VTiltConfig, capture: PageleaveCaptureFn, reason: string, extraProps?: EventPayload): void;
|
|
41
|
+
}
|