@guidelytech/sdk-core 0.2.0 → 0.4.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/index.d.cts CHANGED
@@ -1,168 +1,12 @@
1
1
  import * as _guidelytech_guide_runtime from '@guidelytech/guide-runtime';
2
- import { PublishedGuide, FrequencyConfig, ProjectTheme, SdkConfigResponse, ChecklistTask, MessengerMessage, MessengerConversation, SdkEvent, TargetingContext, SelectorStrategy, AuthoringPick, AppSnapshot } from '@guidelytech/shared';
3
- export { AppSnapshot, GuideConfig, GuideStep, PublishedGuide, SdkConfigResponse, SdkEvent, TargetingContext } from '@guidelytech/shared';
2
+ import { TargetingContext, PublishedGuide, ProjectTheme, SelectorStrategy, AuthoringPick, AppSnapshot } from '@guidelytech/shared';
3
+ export { AppSnapshot, AutocaptureSettings, ExceptionProperties, GuideConfig, GuideStep, PublishedGuide, SdkConfigResponse, SdkEvent, StackFrame, TargetingContext } from '@guidelytech/shared';
4
4
  import { MessengerTab } from '@guidelytech/guide-runtime/messenger';
5
-
6
- /** Per-guide state kept locally and merged with the server's `IdentifyResponse.guideState`. */
7
- interface GuideLocalState {
8
- impressions: number;
9
- completedAt?: string | null;
10
- dismissedAt?: string | null;
11
- lastShownAt?: string | null;
12
- }
13
- /**
14
- * Pure frequency evaluation. `shownThisSession` comes from session storage.
15
- * - `once`: a single impression ever (unless `reshowAfterDismiss` and it was only dismissed).
16
- * - `once_per_session`: at most once per browser session.
17
- * - `every_time`: on every trigger (still blocked by completion/dismissal rules below).
18
- * - `interval`: at most once every `intervalHours`.
19
- * `maxImpressions` caps total impressions; dismissal blocks re-showing unless `reshowAfterDismiss`
20
- * (then `cooldownHours` must have elapsed); completion blocks unless mode is `every_time`.
21
- */
22
- declare function isFrequencyEligible(freq: FrequencyConfig, state: GuideLocalState | undefined, shownThisSession: boolean, now?: number): boolean;
23
- /**
24
- * Exclusive guides (flows, modals, tooltips, announcements, surveys) run one at a time.
25
- * Banners, checklists and hotspot-only tooltips can coexist with an active flow.
26
- */
27
- declare function isExclusiveGuide(guide: PublishedGuide): boolean;
28
- /** Is `a` mutually exclusive with `b` (by id or key, in either direction)? */
29
- declare function areMutuallyExclusive(a: PublishedGuide, b: PublishedGuide): boolean;
30
- /** Survey scheduling window. */
31
- declare function isWithinSchedule(guide: PublishedGuide, now?: number): boolean;
32
-
33
- type StorageKind = "local" | "session" | "memory";
34
- /** Minimal synchronous key/value store; never throws (private mode, quota, SSR). */
35
- interface KeyValueStore {
36
- get(key: string): string | null;
37
- set(key: string, value: string): void;
38
- remove(key: string): void;
39
- }
40
- /** Creates a store of the requested kind, degrading to memory when unavailable. */
41
- declare function createStorage(kind?: StorageKind): KeyValueStore;
42
- /** Storage keys used by the SDK (documented for integrators). */
43
- declare const KEYS: {
44
- readonly anon: "guidely:anon";
45
- readonly seen: "guidely:seen";
46
- readonly config: (key: string) => string;
47
- readonly etag: (key: string) => string;
48
- readonly state: (key: string) => string;
49
- readonly user: (key: string) => string;
50
- readonly queue: (key: string) => string;
51
- readonly session: "guidely:session";
52
- readonly active: "guidely:active";
53
- readonly authoring: "guidely:authoring";
54
- /** Messenger conversations this browser can read: [{ id, token }]. */
55
- readonly conversations: (key: string) => string;
56
- };
57
-
58
- type GuidelyEnvironment = "development" | "staging" | "production";
59
- type ConsentState = "granted" | "denied" | "pending";
60
- interface GuidelyAccount {
61
- id: string;
62
- traits?: Record<string, unknown>;
63
- }
64
- interface GuidelyUser {
65
- id: string;
66
- traits?: Record<string, unknown>;
67
- account?: GuidelyAccount;
68
- }
69
- interface GuidelyOptions {
70
- /** Environment public key, e.g. `pk_dev_…`. Not a secret. */
71
- projectId: string;
72
- environment?: GuidelyEnvironment;
73
- /** Base URL of the Guidely API (default `https://api.guidely.app`; use `http://localhost:3000` locally). */
74
- apiUrl?: string;
75
- /** Log trigger decisions and requests to the console. */
76
- debug?: boolean;
77
- /** Send analytics events (default `true`). Guides still render when disabled. */
78
- analytics?: boolean;
79
- /** `pending` buffers events until `setConsent("granted")`; `denied` disables analytics. */
80
- consent?: ConsentState;
81
- /** Where to persist identity, cached config and the event queue (default `local`). */
82
- storage?: StorageKind;
83
- /** Interval for re-checking element-visibility triggers while the page is idle (default 1000ms). */
84
- pollIntervalMs?: number;
85
- /** How often to refresh the published config (default 5 minutes). */
86
- configRefreshMs?: number;
87
- /** Elements whose text must never be captured (authoring snapshots). Merged with the project setting. */
88
- maskSelectors?: string[];
89
- onError?: (error: Error) => void;
90
- /** Overrides for the project theme (colors, radius, font). */
91
- theme?: Partial<ProjectTheme>;
92
- /** Identify this user as soon as the client initialises. */
93
- user?: GuidelyUser;
94
- /** Custom fetch (tests / polyfills). */
95
- fetch?: typeof fetch;
96
- /** Disable the authoring-mode URL parameter detection. */
97
- disableAuthoring?: boolean;
98
- }
99
- interface ChecklistProgressState {
100
- completedTaskIds: string[];
101
- completedAt?: string | null;
102
- dismissedAt?: string | null;
103
- }
104
- /** Everything the client persists per project key (`guidely:state:<key>`). */
105
- interface PersistedState {
106
- guides: Record<string, GuideLocalState>;
107
- checklists: Record<string, ChecklistProgressState>;
108
- surveysSubmitted: string[];
109
- audienceIds: string[];
110
- firstSeenAt?: string;
111
- }
112
- interface SessionState {
113
- id: string;
114
- startedAt: string;
115
- shownGuides: string[];
116
- events: string[];
117
- }
118
- interface GuideStepInfo {
119
- guide: PublishedGuide;
120
- stepId: string;
121
- stepIndex: number;
122
- }
123
- interface GuidelyEvents {
124
- /** Config loaded (from network or cache) and triggers evaluated. */
125
- ready: (config: SdkConfigResponse) => void;
126
- /** Config (re)loaded. */
127
- config: (config: SdkConfigResponse) => void;
128
- "guide:start": (guide: PublishedGuide) => void;
129
- "guide:step": (info: GuideStepInfo) => void;
130
- "guide:complete": (guide: PublishedGuide) => void;
131
- "guide:dismiss": (guide: PublishedGuide) => void;
132
- "guide:skip": (guide: PublishedGuide) => void;
133
- "checklist:task": (info: {
134
- guide: PublishedGuide;
135
- task: ChecklistTask;
136
- progress: ChecklistProgressState;
137
- }) => void;
138
- "checklist:complete": (guide: PublishedGuide) => void;
139
- "survey:submit": (info: {
140
- guide: PublishedGuide;
141
- answers: Record<string, unknown>;
142
- responseId: string;
143
- }) => void;
144
- "resource-center:open": () => void;
145
- "messenger:open": () => void;
146
- /** A Scout or teammate message arrived in the messenger. */
147
- "conversation:message": (info: {
148
- message: MessengerMessage;
149
- conversation: MessengerConversation;
150
- }) => void;
151
- error: (error: Error) => void;
152
- /** Every tracked event (custom and lifecycle). */
153
- track: (event: SdkEvent) => void;
154
- identify: (info: {
155
- userId: string | null;
156
- anonymousId: string;
157
- }) => void;
158
- authoring: (info: {
159
- active: boolean;
160
- }) => void;
161
- }
162
- type GuidelyEventName = keyof GuidelyEvents;
5
+ import { k as GuidelyOptions, c as GuidelyAccount, a as ConsentState, C as ChecklistProgressState, l as GuidelyEvents, e as GuidelyUser, G as GuideLocalState, S as SessionState } from './types-BZ9r3Fs9.cjs';
6
+ export { E as EventQueue, b as EventQueueOptions, n as GuideStepInfo, d as GuidelyEnvironment, o as GuidelyEventName, K as KEYS, f as KeyValueStore, P as PersistedState, p as StorageKind, g as areMutuallyExclusive, q as createStorage, i as isExclusiveGuide, h as isFrequencyEligible, j as isWithinSchedule } from './types-BZ9r3Fs9.cjs';
163
7
 
164
8
  declare const SDK_NAME = "@guidelytech/sdk-core";
165
- declare const SDK_VERSION = "0.2.0";
9
+ declare const SDK_VERSION = "0.4.0";
166
10
  declare const DEFAULT_API_URL = "https://api.guidely.app";
167
11
  /**
168
12
  * Framework-independent Guidely client. Create one per page with {@link createGuidely} or
@@ -204,6 +48,18 @@ declare class GuidelyClient {
204
48
  private lastAudiences;
205
49
  /** Set once the app calls identify()/reset(); bootstrap then leaves identity alone instead of re-identifying. */
206
50
  private identitySettled;
51
+ /** Created once the recorder chunk has loaded (it carries the replay controller). */
52
+ private replay;
53
+ private replayLoading;
54
+ private readonly pageTracker;
55
+ private readonly rage;
56
+ private readonly heatmap;
57
+ private readonly exceptionThrottle;
58
+ /** Exceptions seen before the config was loaded (reported once it is known whether the server accepts them). */
59
+ private earlyExceptions;
60
+ private initialPageViewSent;
61
+ private pageViewUrl;
62
+ private pageLeft;
207
63
  constructor(options: GuidelyOptions);
208
64
  /** Loads config (cache first, then network), wires listeners and evaluates triggers. Idempotent. */
209
65
  init(): Promise<void>;
@@ -212,6 +68,8 @@ declare class GuidelyClient {
212
68
  private bootstrap;
213
69
  private fetchConfig;
214
70
  private wireListeners;
71
+ /** Uncaught errors + unhandled rejections; attached before the config loads so boot errors are kept. */
72
+ private wireErrorListeners;
215
73
  /** Re-fetches the published config and re-evaluates triggers. */
216
74
  refresh(): Promise<void>;
217
75
  /** Tears everything down: guides, widgets, listeners, timers, host element. Re-init is allowed via a new client. */
@@ -239,6 +97,49 @@ declare class GuidelyClient {
239
97
  private readonly eventBus;
240
98
  private handleNavigation;
241
99
  private handleDocumentClick;
100
+ /** Records activity; starts a new session after `sessionTimeoutMinutes` of inactivity or 24h. */
101
+ private touchSession;
102
+ private rotateSession;
103
+ /** Autocapture, error tracking and replay need analytics on, consent granted and no authoring session. */
104
+ private captureAllowed;
105
+ /** A capability is on when the project enables it (absent on old servers → off) and no option turns it off. */
106
+ private autocaptureOn;
107
+ /** Page views on SPA navigation predate autocapture: only an explicit opt-out stops them. */
108
+ private pageviewsOn;
109
+ private trackPageView;
110
+ /** Emits `page_leave` for the page being left and starts measuring `nextUrl` (null: page unload). */
111
+ private leavePage;
112
+ private autocaptureClick;
113
+ /** Bins one pointer sample into the heatmap buffer. Not session activity. */
114
+ private sampleMove;
115
+ /** Sends the buffered heatmap clicks as one `heatmap` event attributed to the page they happened on. */
116
+ private flushHeatmap;
117
+ private captureGlobalException;
118
+ /**
119
+ * Reports a caught error as an `exception` event (`source: "manual"`, `handled: true`), grouped
120
+ * into an issue on the Errors page. Extra properties are attached to the occurrence. Needs the
121
+ * project's error tracking on (plus analytics + consent); `captureErrors: false` does not stop it.
122
+ */
123
+ captureException(error: unknown, properties?: Record<string, unknown>): void;
124
+ private sendException;
125
+ private maskSelector;
126
+ private maskAllText;
127
+ /** Replay settings for this installation, or null when the project (or an option) disables replay. */
128
+ private replayConfig;
129
+ /** Reconciles capture with the current config / consent / authoring state. Idempotent. */
130
+ private syncCapture;
131
+ private syncReplay;
132
+ /**
133
+ * Records this session even when it was not sampled, provided the project has session replay
134
+ * enabled (and analytics + consent allow it). The decision sticks for the rest of the session.
135
+ */
136
+ startSessionRecording(): void;
137
+ /** Stops recording for the rest of this session (what was recorded so far is uploaded). */
138
+ stopSessionRecording(): void;
139
+ /** True while the session is being recorded. */
140
+ isRecording(): boolean;
141
+ /** The current analytics session id (rotates after inactivity; also the replay id). */
142
+ getSessionId(): string;
242
143
  /** Builds the targeting context for the current moment. */
243
144
  getContext(): TargetingContext;
244
145
  private isTargeted;
@@ -370,61 +271,13 @@ interface ContextInput {
370
271
  locale?: string;
371
272
  device?: DeviceInfo;
372
273
  now?: Date;
274
+ platform?: string;
275
+ screen?: string;
276
+ appVersion?: string;
373
277
  }
374
278
  /** Builds the `TargetingContext` consumed by `evaluateRules`. */
375
279
  declare function buildContext(input: ContextInput): TargetingContext;
376
280
 
377
- interface EventQueueOptions {
378
- store: KeyValueStore;
379
- storageKey: string;
380
- /** Sends one batch. Resolve `{ ok: true }` on success, `{ ok: false, retry }` otherwise. */
381
- send: (events: SdkEvent[]) => Promise<{
382
- ok: boolean;
383
- retry?: boolean;
384
- }>;
385
- /** Synchronous best-effort send used on page hide. */
386
- beacon?: (events: SdkEvent[]) => boolean;
387
- /** Should events be flushed right now? (analytics enabled + consent granted). */
388
- enabled: () => boolean;
389
- flushIntervalMs?: number;
390
- maxQueue?: number;
391
- batchSize?: number;
392
- maxAttempts?: number;
393
- onError?: (err: unknown) => void;
394
- }
395
- /**
396
- * Bounded, persisted event queue. Batches ≤50 events every 2s (or on demand), dedupes by
397
- * `eventId`, retries with exponential backoff (1s→30s, 5 attempts) and keeps failed events for
398
- * the next flush. Drops the oldest events once the queue exceeds 200.
399
- */
400
- declare class EventQueue {
401
- private readonly opts;
402
- private events;
403
- private timer;
404
- private retryTimer;
405
- private inflight;
406
- private inflightIds;
407
- private attempt;
408
- private destroyed;
409
- private readonly flushIntervalMs;
410
- private readonly maxQueue;
411
- private readonly batchSize;
412
- private readonly maxAttempts;
413
- constructor(opts: EventQueueOptions);
414
- get size(): number;
415
- /** Pending events (read-only copy, for debugging). */
416
- peek(): SdkEvent[];
417
- enqueue(event: SdkEvent): void;
418
- private persist;
419
- private schedule;
420
- /** Sends queued events now (one batch at a time). Safe to call at any time. */
421
- flush(): Promise<void>;
422
- /** Best-effort synchronous flush on unload using `sendBeacon`. */
423
- flushSync(): void;
424
- clear(): void;
425
- destroy(): void;
426
- }
427
-
428
281
  type Listener = (url: string) => void;
429
282
  /**
430
283
  * Detects SPA navigation: patches `history.pushState`/`replaceState` (reference counted, restored
@@ -501,6 +354,26 @@ type AuthoringIncomingMessage = {
501
354
  */
502
355
  declare function captureSnapshot(doc: Document, maskSelectors: string[], maxBytes?: number): AppSnapshot | null;
503
356
 
357
+ /** `click` / `rage_click` event properties. */
358
+ interface ClickProperties {
359
+ tag: string;
360
+ text?: string;
361
+ selector: string;
362
+ href?: string;
363
+ x: number;
364
+ y: number;
365
+ count?: number;
366
+ }
367
+
368
+ /** What `page_leave` reports for the page being left. */
369
+ interface PageLeaveInfo {
370
+ url: string;
371
+ /** Time the page was visible (pauses while `document.hidden`). */
372
+ durationMs: number;
373
+ /** Furthest point scrolled to, as a percentage (0–100) of the page height. */
374
+ scrollDepth: number;
375
+ }
376
+
504
377
  /**
505
378
  * @guidelytech/sdk-core — framework-independent Guidely browser SDK.
506
379
  *
@@ -516,4 +389,4 @@ declare const Guidely: {
516
389
  version: string;
517
390
  };
518
391
 
519
- export { AUTHORING_PARAM, type AuthoringIncomingMessage, type AuthoringOutgoingMessage, type ChecklistProgressState, type ConsentState, type ContextInput, DEFAULT_API_URL, type DeviceInfo, EventQueue, type EventQueueOptions, type GuideLocalState, type GuideStepInfo, Guidely, type GuidelyAccount, GuidelyClient, type GuidelyEnvironment, type GuidelyEventName, type GuidelyEvents, type GuidelyOptions, type GuidelyUser, HEARTBEAT_MS, KEYS, type KeyValueStore, type PersistedState, SDK_NAME, SDK_VERSION, type SessionState, type StorageKind, areMutuallyExclusive, buildContext, captureSnapshot, createGuidely, createStorage, Guidely as default, detectDevice, isExclusiveGuide, isFrequencyEligible, isWithinSchedule, watchNavigation };
392
+ export { AUTHORING_PARAM, type AuthoringIncomingMessage, type AuthoringOutgoingMessage, ChecklistProgressState, type ClickProperties, ConsentState, type ContextInput, DEFAULT_API_URL, type DeviceInfo, GuideLocalState, Guidely, GuidelyAccount, GuidelyClient, GuidelyEvents, GuidelyOptions, GuidelyUser, HEARTBEAT_MS, type PageLeaveInfo, SDK_NAME, SDK_VERSION, SessionState, buildContext, captureSnapshot, createGuidely, Guidely as default, detectDevice, watchNavigation };