@prosdevlab/experience-sdk 0.1.5 → 0.3.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 CHANGED
@@ -2,17 +2,20 @@
2
2
 
3
3
  A lightweight, explainable client-side experience runtime built on [@lytics/sdk-kit](https://github.com/lytics/sdk-kit).
4
4
 
5
- **Size:** 6.9 KB gzipped (includes core + 3 plugins)
5
+ **Size:** 13.4 KB gzipped core + 12.7 KB gzipped plugins = 26.1 KB total
6
6
 
7
7
  ## Features
8
8
 
9
9
  - **Explainability-First** - Every decision includes structured reasons
10
10
  - **Plugin-Based** - Built on sdk-kit's powerful plugin system
11
- - **Multiple Buttons** - Primary, secondary, and link variants
12
- - **Frequency Capping** - Control impression limits per session/day/week
11
+ - **Multiple Layouts** - Banners, modals, and inline experiences
12
+ - **Form Support** - Email capture with built-in validation
13
+ - **Display Conditions** - Exit intent, scroll depth, time delays, page visits
14
+ - **Frequency Capping** - Control impression limits per session/lifetime
13
15
  - **Responsive Layout** - Automatically adapts to mobile/desktop
14
16
  - **Script Tag Ready** - Works without build tools
15
17
  - **Type-Safe** - Full TypeScript support
18
+ - **CSS Variables** - Full theming support
16
19
 
17
20
  ## Installation
18
21
 
@@ -41,18 +44,41 @@ const experiences = createInstance({ debug: true });
41
44
  // Initialize
42
45
  await experiences.init();
43
46
 
44
- // Register a banner
47
+ // Register a modal with form
48
+ experiences.register('newsletter', {
49
+ type: 'modal',
50
+ targeting: {
51
+ custom: (context) => context.triggers.exitIntent
52
+ },
53
+ content: {
54
+ title: 'Before You Go!',
55
+ message: 'Subscribe for 10% off your first order.',
56
+ size: 'sm',
57
+ form: {
58
+ fields: [
59
+ { name: 'email', type: 'email', required: true, placeholder: 'you@example.com' }
60
+ ],
61
+ submitButton: { text: 'Get Discount', variant: 'primary' },
62
+ successState: {
63
+ title: '✓ Check Your Inbox',
64
+ message: 'Your discount code is on the way!'
65
+ }
66
+ }
67
+ }
68
+ });
69
+
70
+ // Or register a banner
45
71
  experiences.register('welcome', {
46
72
  type: 'banner',
47
73
  targeting: {
48
74
  url: { contains: '/' }
49
75
  },
50
76
  content: {
51
- title: 'Welcome!',
52
- message: 'Thanks for visiting.',
77
+ message: 'Welcome! Get 20% off today.',
53
78
  buttons: [
54
- { text: 'Get Started', url: '/start', variant: 'primary' }
55
- ]
79
+ { text: 'Shop Now', url: '/shop', variant: 'primary' }
80
+ ],
81
+ position: 'top'
56
82
  },
57
83
  frequency: {
58
84
  max: 3,
@@ -128,9 +154,20 @@ experiences.on('experiences:dismissed', ({ experienceId }) => {
128
154
 
129
155
  ## Included Plugins
130
156
 
131
- This package includes three official plugins:
157
+ This package auto-registers the following official plugins:
158
+
159
+ ### Layout Plugins
160
+ - **Banner Plugin** - Top/bottom notification bars
161
+ - **Modal Plugin** - Overlay dialogs with forms
162
+ - **Inline Plugin** - In-content experiences
163
+
164
+ ### Display Conditions
165
+ - **Exit Intent** - Detect when users are leaving
166
+ - **Scroll Depth** - Track scroll engagement
167
+ - **Page Visits** - Session and lifetime counters
168
+ - **Time Delay** - Show after time elapsed
132
169
 
133
- - **Banner Plugin** - DOM rendering with responsive layout
170
+ ### Utility Plugins
134
171
  - **Frequency Plugin** - Impression tracking and capping
135
172
  - **Debug Plugin** - Logging and window events
136
173
 
@@ -1,5 +1,6 @@
1
1
  import { BannerContent, ModalContent, TooltipContent } from '@prosdevlab/experience-sdk-plugins';
2
2
  export { BannerContent, ModalContent, TooltipContent, bannerPlugin, debugPlugin, frequencyPlugin } from '@prosdevlab/experience-sdk-plugins';
3
+ import { SDK } from '@lytics/sdk-kit';
3
4
 
4
5
  /**
5
6
  * Type Definitions for Experience SDK
@@ -17,7 +18,7 @@ interface Experience {
17
18
  /** Unique identifier for the experience */
18
19
  id: string;
19
20
  /** Type of experience to render */
20
- type: 'banner' | 'modal' | 'tooltip';
21
+ type: 'banner' | 'modal' | 'tooltip' | 'inline';
21
22
  /** Rules that determine when/where to show this experience */
22
23
  targeting: TargetingRules;
23
24
  /** Content to display (type-specific) */
@@ -26,6 +27,8 @@ interface Experience {
26
27
  frequency?: FrequencyConfig;
27
28
  /** Priority for ordering (higher = more important, default: 0) */
28
29
  priority?: number;
30
+ /** Display conditions (triggers, timing) */
31
+ display?: DisplayConditions;
29
32
  }
30
33
  /**
31
34
  * Targeting Rules
@@ -75,6 +78,19 @@ interface FrequencyConfig {
75
78
  /** Time period for the cap */
76
79
  per: 'session' | 'day' | 'week';
77
80
  }
81
+ /**
82
+ * Display Conditions
83
+ *
84
+ * Conditions that determine when an experience should be displayed.
85
+ */
86
+ interface DisplayConditions {
87
+ /** Trigger type (e.g., scrollDepth, exitIntent, timeDelay) */
88
+ trigger?: string;
89
+ /** Trigger-specific configuration data */
90
+ triggerData?: any;
91
+ /** Frequency capping for this experience */
92
+ frequency?: FrequencyConfig;
93
+ }
78
94
 
79
95
  /**
80
96
  * Experience Content (type-specific)
@@ -110,6 +126,68 @@ interface Context {
110
126
  timestamp?: number;
111
127
  /** Custom context properties */
112
128
  custom?: Record<string, any>;
129
+ /** Trigger state (for display condition plugins) */
130
+ triggers?: TriggerState;
131
+ }
132
+ /**
133
+ * Trigger State
134
+ *
135
+ * Tracks which trigger-based display conditions have fired.
136
+ * Used by plugins like exitIntent, scrollDepth, pageVisits, timeDelay.
137
+ */
138
+ interface TriggerState {
139
+ /** Exit intent trigger state */
140
+ exitIntent?: {
141
+ /** Whether the trigger has fired */
142
+ triggered: boolean;
143
+ /** When the trigger fired (unix timestamp) */
144
+ timestamp?: number;
145
+ /** Additional trigger-specific data */
146
+ lastY?: number;
147
+ previousY?: number;
148
+ velocity?: number;
149
+ timeOnPage?: number;
150
+ };
151
+ /** Scroll depth trigger state */
152
+ scrollDepth?: {
153
+ triggered: boolean;
154
+ timestamp?: number;
155
+ /** Current scroll percentage (0-100) */
156
+ percent?: number;
157
+ };
158
+ /** Page visits trigger state */
159
+ pageVisits?: {
160
+ triggered: boolean;
161
+ timestamp?: number;
162
+ /** Total visit count */
163
+ count?: number;
164
+ /** Whether this is the first visit */
165
+ firstVisit?: boolean;
166
+ };
167
+ /** Time delay trigger state */
168
+ timeDelay?: {
169
+ triggered: boolean;
170
+ timestamp?: number;
171
+ /** Total elapsed time (ms, includes paused time) */
172
+ elapsed?: number;
173
+ /** Active elapsed time (ms, excludes paused time) */
174
+ activeElapsed?: number;
175
+ /** Whether timer was paused */
176
+ wasPaused?: boolean;
177
+ /** Number of visibility changes */
178
+ visibilityChanges?: number;
179
+ };
180
+ /** Modal trigger state (when modal is shown) */
181
+ modal?: {
182
+ triggered: boolean;
183
+ timestamp?: number;
184
+ /** Experience ID of the shown modal */
185
+ experienceId?: string;
186
+ /** Whether the modal is currently showing */
187
+ shown?: boolean;
188
+ };
189
+ /** Extensible for future triggers */
190
+ [key: string]: any;
113
191
  }
114
192
  /**
115
193
  * User Context
@@ -218,12 +296,26 @@ interface RuntimeState {
218
296
  * - Explainability-first (every decision has reasons)
219
297
  */
220
298
  declare class ExperienceRuntime {
221
- private sdk;
299
+ sdk: SDK;
222
300
  private experiences;
223
301
  private decisions;
224
302
  private initialized;
225
303
  private destroyed;
304
+ private triggerContext;
226
305
  constructor(config?: ExperienceConfig);
306
+ /**
307
+ * Setup listeners for trigger:* events
308
+ * This enables event-driven display conditions
309
+ */
310
+ /**
311
+ * Setup listeners for trigger:* events
312
+ * This enables event-driven display conditions
313
+ *
314
+ * Note: sdk-kit's emitter passes only the event payload to wildcard listeners,
315
+ * not the event name. Display condition plugins must include trigger metadata
316
+ * in their payload (e.g., { trigger: 'exitIntent', ...data })
317
+ */
318
+ private setupTriggerListeners;
227
319
  /**
228
320
  * Initialize the runtime
229
321
  */
@@ -414,5 +506,16 @@ declare function on(event: string, handler: (...args: unknown[]) => void): () =>
414
506
  * ```
415
507
  */
416
508
  declare function destroy(): Promise<void>;
509
+ declare const experiencesProxy: {
510
+ createInstance: typeof createInstance;
511
+ init: typeof init;
512
+ register: typeof register;
513
+ evaluate: typeof evaluate;
514
+ evaluateAll: typeof evaluateAll;
515
+ explain: typeof explain;
516
+ getState: typeof getState;
517
+ on: typeof on;
518
+ destroy: typeof destroy;
519
+ };
417
520
 
418
- export { type Context, type Decision, type DecisionMetadata, type Experience, type ExperienceConfig, type ExperienceContent, ExperienceRuntime, type FrequencyConfig, type FrequencyRule, type ModalAction, type RuntimeState, type TargetingRules, type TraceStep, type UrlRule, type UserContext, buildContext, createInstance, destroy, evaluate, evaluateAll, evaluateExperience, evaluateUrlRule, explain, getState, init, on, register };
521
+ export { type Context, type Decision, type DecisionMetadata, type Experience, type ExperienceConfig, type ExperienceContent, ExperienceRuntime, type FrequencyConfig, type FrequencyRule, type ModalAction, type RuntimeState, type TargetingRules, type TraceStep, type UrlRule, type UserContext, buildContext, createInstance, destroy, evaluate, evaluateAll, evaluateExperience, evaluateUrlRule, experiencesProxy as experiences, explain, getState, init, on, register };