@cognior/iap-sdk 0.0.2
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/LICENSE +9 -0
- package/README.md +1117 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.d.ts +113 -0
- package/dist/index.esm.js +1 -0
- package/dist/index.umd.js +1 -0
- package/package.json +82 -0
package/README.md
ADDED
|
@@ -0,0 +1,1117 @@
|
|
|
1
|
+
# Digital Adoption Platform (DAP) SDK
|
|
2
|
+
|
|
3
|
+
A framework-agnostic JavaScript/TypeScript SDK for creating interactive user flows, onboarding experiences, tooltips, surveys, and walkthroughs in web applications.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The DAP SDK enables developers to create guided user experiences driven by backend-defined Flow JSON configurations. It provides a comprehensive suite of UI components and interaction patterns that help users navigate and learn your application.
|
|
8
|
+
|
|
9
|
+
**Architecture**: Backend Flow Engine → DAP SDK → Interactive UI Components
|
|
10
|
+
|
|
11
|
+
### Typical Use Cases
|
|
12
|
+
|
|
13
|
+
- **User Onboarding**: Step-by-step guided tours for new users
|
|
14
|
+
- **Feature Discovery**: Interactive tooltips and hotspots highlighting new features
|
|
15
|
+
- **Contextual Help**: Smart assistance based on user location and behavior
|
|
16
|
+
- **Surveys & Feedback**: In-app surveys and micro-surveys for user insights
|
|
17
|
+
- **Task Guidance**: Walkthrough workflows and complex processes
|
|
18
|
+
- **Knowledge Base**: Embedded help content and documentation
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
### Core Capabilities
|
|
23
|
+
- ✅ **Step-based Flow System**: Linear and AnyOrder execution models
|
|
24
|
+
- ✅ **Mandatory vs Optional Steps**: Flexible flow completion requirements
|
|
25
|
+
- ✅ **Advanced Trigger System**: DOM, Input, Lifecycle, and Time-based triggers
|
|
26
|
+
- ✅ **Rule-based Branching**: Dynamic flow paths based on user input
|
|
27
|
+
- ✅ **Multi-page Support**: Seamless flows across SPAs and traditional pages
|
|
28
|
+
- ✅ **Real-time Analytics**: Comprehensive telemetry and user behavior tracking
|
|
29
|
+
- ✅ **One-time vs Recurring**: Configurable flow frequency and targeting
|
|
30
|
+
|
|
31
|
+
### UI Components
|
|
32
|
+
- **Modals**: Rich content modals with dragging, resizing, and accessibility
|
|
33
|
+
- **Tooltips**: Contextual help tooltips with smart positioning
|
|
34
|
+
- **Popovers**: Interactive popovers with custom content
|
|
35
|
+
- **Banners**: Page-level announcements and notifications
|
|
36
|
+
- **Hotspots**: Visual indicators for interactive elements
|
|
37
|
+
- **Surveys**: Inline and modal survey components
|
|
38
|
+
- **Walkthroughs**: Multi-step guided tours
|
|
39
|
+
- **Task Lists**: Interactive checklists and progress tracking
|
|
40
|
+
|
|
41
|
+
## Browser & Platform Support
|
|
42
|
+
|
|
43
|
+
- **Modern Browsers**: Chrome 80+, Firefox 75+, Safari 13+, Edge 80+
|
|
44
|
+
- **SPA Compatibility**: React, Angular, Vue, Svelte, and vanilla JavaScript
|
|
45
|
+
- **MPA Support**: Traditional multi-page applications
|
|
46
|
+
- **Mobile**: Responsive design with touch support
|
|
47
|
+
- **Accessibility**: WCAG 2.1 AA compliant components
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
### Option A: NPM Package (Recommended for Modern Development)
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Install via npm
|
|
55
|
+
npm install @cognior/dap-sdk
|
|
56
|
+
|
|
57
|
+
# Or install via yarn
|
|
58
|
+
yarn add @cognior/dap-sdk
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**ES Modules (Webpack, Vite, Rollup)**
|
|
62
|
+
```javascript
|
|
63
|
+
import { init, setUser } from '@cognior/dap-sdk';
|
|
64
|
+
|
|
65
|
+
await init({
|
|
66
|
+
configUrl: 'https://api.yourcompany.com/config'
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
setUser({
|
|
70
|
+
id: 'user_123',
|
|
71
|
+
role: 'admin',
|
|
72
|
+
email: 'admin@company.com'
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**CommonJS (Node.js, Legacy Bundlers)**
|
|
77
|
+
```javascript
|
|
78
|
+
const { init, setUser } = require('@cognior/dap-sdk');
|
|
79
|
+
|
|
80
|
+
init({
|
|
81
|
+
configUrl: 'https://api.yourcompany.com/config'
|
|
82
|
+
}).then(() => {
|
|
83
|
+
setUser({
|
|
84
|
+
id: 'user_123',
|
|
85
|
+
role: 'admin'
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Option B: Script Tag (Quick Setup/Testing)
|
|
91
|
+
|
|
92
|
+
```html
|
|
93
|
+
<!DOCTYPE html>
|
|
94
|
+
<html>
|
|
95
|
+
<head>
|
|
96
|
+
<!-- Load DAP SDK -->
|
|
97
|
+
<script src="https://cdn.your-domain.com/dap-sdk/latest/dap.min.js"></script>
|
|
98
|
+
</head>
|
|
99
|
+
<body>
|
|
100
|
+
<script>
|
|
101
|
+
// Initialize after page load
|
|
102
|
+
window.addEventListener('DOMContentLoaded', async () => {
|
|
103
|
+
await window.DAP.init({
|
|
104
|
+
configUrl: 'https://api.your-domain.com/config',
|
|
105
|
+
debug: false
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Set user context for personalized experiences
|
|
109
|
+
window.DAP.setUser({
|
|
110
|
+
id: 'user_123',
|
|
111
|
+
role: 'user',
|
|
112
|
+
email: 'user@company.com'
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
</script>
|
|
116
|
+
</body>
|
|
117
|
+
</html>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Option C: Direct Download
|
|
121
|
+
|
|
122
|
+
Download the latest build files from the [releases page](https://github.com/CogniorAI/WebUserModule/releases) and include in your project:
|
|
123
|
+
|
|
124
|
+
- `index.umd.js` - For script tag usage (global `DAP` variable)
|
|
125
|
+
- `index.esm.js` - For ES module imports
|
|
126
|
+
- `index.cjs.js` - For CommonJS require()
|
|
127
|
+
- `index.d.ts` - TypeScript definitions
|
|
128
|
+
|
|
129
|
+
## SDK Initialization
|
|
130
|
+
|
|
131
|
+
### Required Configuration
|
|
132
|
+
|
|
133
|
+
| Option | Description | Example |
|
|
134
|
+
|--------|-------------|---------|
|
|
135
|
+
| `configUrl` | URL to fetch DAP configuration | `"https://api.dap.com/config"` |
|
|
136
|
+
|
|
137
|
+
### Optional Configuration
|
|
138
|
+
|
|
139
|
+
| Option | Description | Default |
|
|
140
|
+
|--------|-------------|---------|
|
|
141
|
+
| `debug` | Enable verbose console logging | `false` |
|
|
142
|
+
| `screenId` | Custom screen identifier | Current pathname |
|
|
143
|
+
| `user` | Initial user context for personalized flows | `undefined` |
|
|
144
|
+
|
|
145
|
+
### Example Initialization
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
// Basic initialization
|
|
149
|
+
await DAP.init({
|
|
150
|
+
configUrl: 'https://api.yourcompany.com/config',
|
|
151
|
+
debug: false
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// With user context and debug mode
|
|
155
|
+
await DAP.init({
|
|
156
|
+
configUrl: 'https://api.yourcompany.com/config',
|
|
157
|
+
debug: true,
|
|
158
|
+
screenId: 'dashboard',
|
|
159
|
+
user: {
|
|
160
|
+
id: 'user_123',
|
|
161
|
+
role: 'admin',
|
|
162
|
+
email: 'admin@company.com',
|
|
163
|
+
attributes: {
|
|
164
|
+
department: 'engineering',
|
|
165
|
+
subscription: 'enterprise'
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Configuration File Format
|
|
172
|
+
|
|
173
|
+
The `configUrl` should return a JSON configuration with the following structure:
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"organizationid": "your-org-id",
|
|
178
|
+
"siteid": "your-site-id",
|
|
179
|
+
"apikey": "your-api-key",
|
|
180
|
+
"apiurl": "https://api.yourcompany.com",
|
|
181
|
+
"enableDraggableModals": true
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
## User Context Management
|
|
185
|
+
|
|
186
|
+
### Setting User Information
|
|
187
|
+
|
|
188
|
+
The SDK supports comprehensive user context management for personalized experiences and analytics. User information should be provided after initialization or when user state changes.
|
|
189
|
+
|
|
190
|
+
#### User Data Structure
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
interface DapUser {
|
|
194
|
+
id: string; // Required: Unique user identifier
|
|
195
|
+
role?: string; // Optional: User role (admin, user, guest)
|
|
196
|
+
email?: string; // Optional: User email address
|
|
197
|
+
attributes?: Record<string, string>; // Optional: Custom user attributes
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### Setting User Context
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
// Set complete user context
|
|
205
|
+
DAP.setUser({
|
|
206
|
+
id: 'user_12345',
|
|
207
|
+
role: 'premium',
|
|
208
|
+
email: 'user@company.com',
|
|
209
|
+
attributes: {
|
|
210
|
+
department: 'engineering',
|
|
211
|
+
experience_level: 'advanced',
|
|
212
|
+
subscription: 'pro',
|
|
213
|
+
signup_date: '2024-01-15'
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Update existing user context (merges with existing data)
|
|
218
|
+
DAP.updateUser({
|
|
219
|
+
role: 'admin',
|
|
220
|
+
attributes: {
|
|
221
|
+
last_login: '2024-01-22'
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// Get current user context
|
|
226
|
+
const user = DAP.getUser();
|
|
227
|
+
console.log('Current user:', user);
|
|
228
|
+
|
|
229
|
+
// Clear user context (for logout)
|
|
230
|
+
DAP.clearUser();
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### Integration Examples
|
|
234
|
+
|
|
235
|
+
**React Integration**
|
|
236
|
+
```javascript
|
|
237
|
+
// In your authentication component
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
if (authUser) {
|
|
240
|
+
DAP.setUser({
|
|
241
|
+
id: authUser.id,
|
|
242
|
+
role: authUser.role,
|
|
243
|
+
email: authUser.email,
|
|
244
|
+
attributes: {
|
|
245
|
+
subscription_tier: authUser.subscription,
|
|
246
|
+
signup_date: authUser.createdAt,
|
|
247
|
+
last_active: new Date().toISOString()
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
} else {
|
|
251
|
+
DAP.clearUser();
|
|
252
|
+
}
|
|
253
|
+
}, [authUser]);
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Angular Integration**
|
|
257
|
+
```typescript
|
|
258
|
+
// In your auth service
|
|
259
|
+
@Injectable()
|
|
260
|
+
export class AuthService {
|
|
261
|
+
private updateDapUser(user: User) {
|
|
262
|
+
DAP.setUser({
|
|
263
|
+
id: user.id,
|
|
264
|
+
role: user.role,
|
|
265
|
+
email: user.email,
|
|
266
|
+
attributes: {
|
|
267
|
+
department: user.department,
|
|
268
|
+
experience_level: user.experience,
|
|
269
|
+
feature_flags: user.featureFlags?.join(',') || ''
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Login/Logout Workflow**
|
|
277
|
+
```javascript
|
|
278
|
+
// On successful login
|
|
279
|
+
async function handleLogin(credentials) {
|
|
280
|
+
const user = await authenticate(credentials);
|
|
281
|
+
|
|
282
|
+
// Set user context for DAP
|
|
283
|
+
DAP.setUser({
|
|
284
|
+
id: user.id,
|
|
285
|
+
role: user.role,
|
|
286
|
+
email: user.email,
|
|
287
|
+
attributes: {
|
|
288
|
+
login_method: 'email',
|
|
289
|
+
user_segment: user.segment,
|
|
290
|
+
onboarding_completed: user.onboardingCompleted.toString()
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Flows will now be evaluated with user context
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// On logout
|
|
298
|
+
function handleLogout() {
|
|
299
|
+
DAP.clearUser();
|
|
300
|
+
// User-specific flows will stop, anonymous flows may continue
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### User Context Benefits
|
|
305
|
+
|
|
306
|
+
#### Personalized Experiences
|
|
307
|
+
```javascript
|
|
308
|
+
// Flows can target specific user roles
|
|
309
|
+
{
|
|
310
|
+
"targeting": {
|
|
311
|
+
"userAttributes": {
|
|
312
|
+
"role": "admin",
|
|
313
|
+
"experience_level": "beginner"
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Dynamic content based on user data
|
|
319
|
+
{
|
|
320
|
+
"modalContent": {
|
|
321
|
+
"title": "Welcome {{user.attributes.department}} Team!"
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
#### Analytics & Insights
|
|
327
|
+
- **User Journey Tracking**: Complete user flow analytics
|
|
328
|
+
- **Segmentation**: Analyze behavior by role, department, subscription tier
|
|
329
|
+
- **Personalization**: Adapt experiences based on user attributes
|
|
330
|
+
- **A/B Testing**: Target specific user segments for experiments
|
|
331
|
+
|
|
332
|
+
#### Privacy & Security
|
|
333
|
+
- **Data Minimization**: Only required data is stored
|
|
334
|
+
- **Session Storage**: User context persists only during browser session
|
|
335
|
+
- **Anonymous Fallback**: SDK works without user context using anonymous IDs
|
|
336
|
+
- **Secure Handling**: No sensitive data logged or exposed
|
|
337
|
+
|
|
338
|
+
### Best Practices
|
|
339
|
+
|
|
340
|
+
#### Required vs Optional Data
|
|
341
|
+
```javascript
|
|
342
|
+
// ✅ Minimal required data
|
|
343
|
+
DAP.setUser({
|
|
344
|
+
id: 'user_123' // Only ID is required
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// ✅ Rich context for better targeting
|
|
348
|
+
DAP.setUser({
|
|
349
|
+
id: 'user_123',
|
|
350
|
+
role: 'admin',
|
|
351
|
+
attributes: {
|
|
352
|
+
subscription: 'enterprise',
|
|
353
|
+
onboarding_step: '3'
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
#### Attribute Naming Conventions
|
|
359
|
+
```javascript
|
|
360
|
+
// ✅ Use consistent, descriptive attribute names
|
|
361
|
+
attributes: {
|
|
362
|
+
'subscription_tier': 'pro',
|
|
363
|
+
'signup_date': '2024-01-15',
|
|
364
|
+
'feature_access': 'advanced',
|
|
365
|
+
'user_segment': 'power_user'
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// ❌ Avoid unclear or inconsistent naming
|
|
369
|
+
attributes: {
|
|
370
|
+
'sub': 'pro', // Too abbreviated
|
|
371
|
+
'dt': '2024-01-15', // Unclear meaning
|
|
372
|
+
'hasAccess': 'true' // Inconsistent format
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
#### Timing Considerations
|
|
377
|
+
```javascript
|
|
378
|
+
// ✅ Set user context early in app lifecycle
|
|
379
|
+
async function initializeApp() {
|
|
380
|
+
// Initialize DAP with user context
|
|
381
|
+
await DAP.init({
|
|
382
|
+
configUrl: 'https://api.yourcompany.com/config',
|
|
383
|
+
user: currentUser,
|
|
384
|
+
debug: process.env.NODE_ENV === 'development'
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// Flows will evaluate with proper context immediately
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// ✅ Update context on relevant changes
|
|
391
|
+
function handleSubscriptionUpgrade(newTier) {
|
|
392
|
+
DAP.updateUser({
|
|
393
|
+
attributes: {
|
|
394
|
+
subscription_tier: newTier,
|
|
395
|
+
upgrade_date: new Date().toISOString()
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
#### Error Handling
|
|
402
|
+
```javascript
|
|
403
|
+
try {
|
|
404
|
+
DAP.setUser({
|
|
405
|
+
id: user.id,
|
|
406
|
+
role: user.role,
|
|
407
|
+
email: user.email,
|
|
408
|
+
attributes: userAttributes
|
|
409
|
+
});
|
|
410
|
+
} catch (error) {
|
|
411
|
+
console.warn('Failed to set DAP user context:', error);
|
|
412
|
+
// Application continues to work, flows may use anonymous context
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
## Embedding the SDK
|
|
417
|
+
|
|
418
|
+
### Single Page Applications (SPA)
|
|
419
|
+
|
|
420
|
+
For SPAs, initialize the SDK once and it will automatically track page changes:
|
|
421
|
+
|
|
422
|
+
```javascript
|
|
423
|
+
// Initialize once on app startup
|
|
424
|
+
await DAP.init({
|
|
425
|
+
configUrl: 'https://api.yourcompany.com/config',
|
|
426
|
+
debug: false,
|
|
427
|
+
user: currentUser // Optional: set initial user context
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// The SDK automatically detects route changes via:
|
|
431
|
+
// - History API changes (pushState/replaceState)
|
|
432
|
+
// - PopState events (back/forward buttons)
|
|
433
|
+
// - Hash changes
|
|
434
|
+
// No manual refresh needed for most frameworks
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Multi-Page Applications (MPA)
|
|
438
|
+
|
|
439
|
+
Initialize on each page load:
|
|
440
|
+
|
|
441
|
+
```javascript
|
|
442
|
+
// Add to your main JavaScript file
|
|
443
|
+
window.addEventListener('DOMContentLoaded', async () => {
|
|
444
|
+
await DAP.init({
|
|
445
|
+
configUrl: 'https://api.yourcompany.com/config'
|
|
446
|
+
});
|
|
447
|
+
// Flows automatically start based on page context
|
|
448
|
+
});
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Page Change Detection
|
|
452
|
+
|
|
453
|
+
The SDK automatically detects:
|
|
454
|
+
- Browser navigation (back/forward buttons)
|
|
455
|
+
- History API changes (`pushState`/`replaceState`)
|
|
456
|
+
- Hash changes
|
|
457
|
+
- Manual page transitions
|
|
458
|
+
|
|
459
|
+
### Selector Best Practices
|
|
460
|
+
|
|
461
|
+
Use stable, semantic selectors for reliable step targeting:
|
|
462
|
+
|
|
463
|
+
```html
|
|
464
|
+
<!-- ✅ Good: Stable, semantic selectors -->
|
|
465
|
+
<button data-dap="onboarding-next" id="next-step">Next</button>
|
|
466
|
+
<div class="user-profile" data-testid="profile-section">...</div>
|
|
467
|
+
|
|
468
|
+
<!-- ❌ Avoid: Generated classes, fragile selectors -->
|
|
469
|
+
<button class="btn-x7j2k9">Next</button>
|
|
470
|
+
<div class="css-1234567">...</div>
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
## Flow Execution Model
|
|
474
|
+
|
|
475
|
+
### Execution Types
|
|
476
|
+
|
|
477
|
+
**Linear Flows**: Steps execute in sequential order
|
|
478
|
+
```json
|
|
479
|
+
{
|
|
480
|
+
"execution": {
|
|
481
|
+
"mode": "Linear"
|
|
482
|
+
},
|
|
483
|
+
"steps": [
|
|
484
|
+
{ "stepOrder": 1, "stepType": "Mandatory", "stepId": "step1" },
|
|
485
|
+
{ "stepOrder": 2, "stepType": "Optional", "stepId": "step2" },
|
|
486
|
+
{ "stepOrder": 3, "stepType": "Mandatory", "stepId": "step3" }
|
|
487
|
+
]
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
**AnyOrder Flows**: Steps can be completed in any sequence
|
|
492
|
+
```json
|
|
493
|
+
{
|
|
494
|
+
"execution": {
|
|
495
|
+
"mode": "AnyOrder"
|
|
496
|
+
},
|
|
497
|
+
"steps": [
|
|
498
|
+
{ "stepType": "Mandatory", "stepId": "intro" },
|
|
499
|
+
{ "stepType": "Optional", "stepId": "tooltip1" },
|
|
500
|
+
{ "stepType": "Mandatory", "stepId": "survey" }
|
|
501
|
+
]
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### Step Types
|
|
506
|
+
|
|
507
|
+
- **Mandatory**: Required for flow completion
|
|
508
|
+
- **Optional**: Can be skipped without blocking flow completion
|
|
509
|
+
|
|
510
|
+
### Trigger Precedence
|
|
511
|
+
|
|
512
|
+
1. `step.trigger` - Direct step trigger override
|
|
513
|
+
2. `step.uxExperience.elementTrigger` - Component-specific trigger
|
|
514
|
+
3. Default component trigger (e.g., "click" for buttons)
|
|
515
|
+
|
|
516
|
+
### Rule-based Branching
|
|
517
|
+
|
|
518
|
+
Steps can include conditional rules that determine next flow transitions:
|
|
519
|
+
|
|
520
|
+
```json
|
|
521
|
+
{
|
|
522
|
+
"stepType": "Rule",
|
|
523
|
+
"userInputSelector": "#user-role-select",
|
|
524
|
+
"conditionRuleBlocks": [
|
|
525
|
+
{
|
|
526
|
+
"ruleBlockId": "admin-path",
|
|
527
|
+
"rules": [{"condition": "equals", "value": "admin"}],
|
|
528
|
+
"nextFlowId": "admin-onboarding"
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
"ruleBlockId": "user-path",
|
|
532
|
+
"rules": [{"condition": "equals", "value": "user"}],
|
|
533
|
+
"nextFlowId": "user-onboarding"
|
|
534
|
+
}
|
|
535
|
+
]
|
|
536
|
+
}
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
## Trigger System
|
|
540
|
+
|
|
541
|
+
### Trigger Types
|
|
542
|
+
|
|
543
|
+
| Type | Description | Example |
|
|
544
|
+
|------|-------------|---------|
|
|
545
|
+
| **Dom** | Element interaction triggers | `click`, `hover`, `focus`, `blur` |
|
|
546
|
+
| **Input** | Form input events | `change`, `input`, `keydown`, `keyup` |
|
|
547
|
+
| **Lifecycle** | Page/application events | `page load`, `on page load`, `pageload` |
|
|
548
|
+
|
|
549
|
+
### Trigger Normalization
|
|
550
|
+
|
|
551
|
+
The SDK automatically normalizes trigger strings from the backend:
|
|
552
|
+
|
|
553
|
+
```javascript
|
|
554
|
+
// These all normalize to the same trigger:
|
|
555
|
+
"click" → "click"
|
|
556
|
+
"on click" → "click"
|
|
557
|
+
"Click" → "click"
|
|
558
|
+
|
|
559
|
+
// Hover triggers:
|
|
560
|
+
"hover" → "mouseenter"
|
|
561
|
+
"on hover" → "mouseenter"
|
|
562
|
+
"mouseover" → "mouseenter"
|
|
563
|
+
|
|
564
|
+
// Page load triggers:
|
|
565
|
+
"page load" → "pageload" (synthetic)
|
|
566
|
+
"on page load" → "pageload" (synthetic)
|
|
567
|
+
"pageload" → "pageload" (synthetic)
|
|
568
|
+
|
|
569
|
+
// Input triggers:
|
|
570
|
+
"input" → "input"
|
|
571
|
+
"typing" → "input"
|
|
572
|
+
"on input" → "input"
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### Single vs Composite Triggers
|
|
576
|
+
|
|
577
|
+
**Single Triggers**: Direct element events
|
|
578
|
+
```json
|
|
579
|
+
{
|
|
580
|
+
"elementSelector": "#get-started-btn",
|
|
581
|
+
"elementTrigger": "click"
|
|
582
|
+
}
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
**Normalized Triggers**: Backend trigger strings are automatically normalized
|
|
586
|
+
```json
|
|
587
|
+
{
|
|
588
|
+
"elementSelector": "#form-input",
|
|
589
|
+
"elementTrigger": "on input" // Becomes "input" event
|
|
590
|
+
}
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
### Debounce and Once Behavior
|
|
594
|
+
|
|
595
|
+
- **Debounce**: Prevents rapid-fire trigger execution
|
|
596
|
+
- **Once**: Ensures triggers fire only once per session
|
|
597
|
+
- **Automatic**: Intelligent trigger management for optimal UX
|
|
598
|
+
|
|
599
|
+
## Analytics & Telemetry
|
|
600
|
+
|
|
601
|
+
### Captured Events
|
|
602
|
+
|
|
603
|
+
- **Flow Events**: Start, complete, abandon, skip
|
|
604
|
+
- **Step Events**: View, interact, complete, error
|
|
605
|
+
- **User Behavior**: Click patterns, time on step, navigation paths
|
|
606
|
+
- **Performance**: Load times, render performance, error rates
|
|
607
|
+
|
|
608
|
+
### Event Timing
|
|
609
|
+
|
|
610
|
+
- **Real-time**: Critical events sent immediately
|
|
611
|
+
- **Batched**: Non-critical events batched for efficiency
|
|
612
|
+
- **Offline**: Events queued when offline, sent when reconnected
|
|
613
|
+
|
|
614
|
+
### Privacy Considerations
|
|
615
|
+
|
|
616
|
+
- **User Consent**: Respects user privacy preferences
|
|
617
|
+
- **Data Minimization**: Only necessary data collected
|
|
618
|
+
- **Anonymization**: Personal data anonymized by default
|
|
619
|
+
- **GDPR Compliant**: Supports data protection regulations
|
|
620
|
+
|
|
621
|
+
### Debug vs Production Logging
|
|
622
|
+
|
|
623
|
+
```javascript
|
|
624
|
+
// Enable debug mode for development
|
|
625
|
+
await DAP.init({
|
|
626
|
+
configUrl: 'https://api.yourcompany.com/config',
|
|
627
|
+
debug: true // Verbose console logging
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
// Production mode (default)
|
|
631
|
+
await DAP.init({
|
|
632
|
+
configUrl: 'https://api.yourcompany.com/config'
|
|
633
|
+
}); // Minimal logging
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
## Error Handling & Debugging
|
|
637
|
+
|
|
638
|
+
### Common Issues
|
|
639
|
+
|
|
640
|
+
**Selector Not Found**
|
|
641
|
+
```javascript
|
|
642
|
+
// Check selector specificity
|
|
643
|
+
console.log(document.querySelector('#my-button'));
|
|
644
|
+
|
|
645
|
+
// Ensure element exists before step triggers
|
|
646
|
+
await DAP.waitForElement('#my-button', { timeout: 5000 });
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
**Step Not Triggering**
|
|
650
|
+
```javascript
|
|
651
|
+
// Verify trigger configuration
|
|
652
|
+
console.log(step.elementTrigger); // Check trigger type
|
|
653
|
+
console.log(step.elementSelector); // Verify selector
|
|
654
|
+
|
|
655
|
+
// Check page context
|
|
656
|
+
console.log(DAP.getCurrentPageContext());
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
**Flow Not Starting**
|
|
660
|
+
```javascript
|
|
661
|
+
// Verify flow targeting
|
|
662
|
+
console.log(await DAP.getVisibleFlows()); // Check available flows
|
|
663
|
+
console.log(DAP.isFlowRelevant(flowId)); // Check relevance
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
### Debug Mode
|
|
667
|
+
|
|
668
|
+
Enable detailed logging for troubleshooting:
|
|
669
|
+
|
|
670
|
+
```javascript
|
|
671
|
+
// Set debug flag globally
|
|
672
|
+
window.__DAP_DEBUG__ = true;
|
|
673
|
+
|
|
674
|
+
// Or via initialization
|
|
675
|
+
await DAP.initialize({ ...config, debug: true });
|
|
676
|
+
|
|
677
|
+
// Console output will include:
|
|
678
|
+
// [DAP] Flow evaluation started
|
|
679
|
+
// [DAP] Step triggered: tooltip-1
|
|
680
|
+
// [DAP] Selector resolved: #help-button
|
|
681
|
+
// [DAP] Analytics event sent: step_view
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
### Console Log Levels
|
|
685
|
+
|
|
686
|
+
| Level | Purpose | Example |
|
|
687
|
+
|-------|---------|---------|
|
|
688
|
+
| `debug` | Detailed execution flow | Step transitions, selector resolution |
|
|
689
|
+
| `info` | General information | Flow starts, completions |
|
|
690
|
+
| `warn` | Potential issues | Missing selectors, deprecated features |
|
|
691
|
+
| `error` | Critical problems | API failures, configuration errors |
|
|
692
|
+
|
|
693
|
+
## SDK Development Setup
|
|
694
|
+
|
|
695
|
+
### Prerequisites
|
|
696
|
+
|
|
697
|
+
- **Node.js**: Version 18+ required
|
|
698
|
+
- **Package Manager**: npm 8+ or yarn 1.22+
|
|
699
|
+
- **TypeScript**: 5.0+ for type safety
|
|
700
|
+
|
|
701
|
+
### Local Development Setup
|
|
702
|
+
|
|
703
|
+
```bash
|
|
704
|
+
# Clone the repository
|
|
705
|
+
git clone https://github.com/your-org/dap-sdk.git
|
|
706
|
+
cd dap-sdk
|
|
707
|
+
|
|
708
|
+
# Install dependencies
|
|
709
|
+
npm install
|
|
710
|
+
|
|
711
|
+
# Start development server with hot reload
|
|
712
|
+
npm run dev
|
|
713
|
+
|
|
714
|
+
# Build for production
|
|
715
|
+
npm run build
|
|
716
|
+
|
|
717
|
+
# Serve built files locally (serves on http://localhost:5173)
|
|
718
|
+
npm run serve
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
### Project Structure
|
|
722
|
+
|
|
723
|
+
```
|
|
724
|
+
src/
|
|
725
|
+
├── core/ # Core engine and flow management
|
|
726
|
+
│ ├── flowEngine.ts # Main flow execution engine
|
|
727
|
+
│ └── triggerManager.ts # Trigger system management
|
|
728
|
+
├── experiences/ # UI component renderers
|
|
729
|
+
│ ├── modal.ts # Modal experience
|
|
730
|
+
│ ├── tooltip.ts # Tooltip experience
|
|
731
|
+
│ ├── survey.ts # Survey components
|
|
732
|
+
│ └── ... # Other UI experiences
|
|
733
|
+
├── services/ # Core services
|
|
734
|
+
│ ├── flowManager.ts # Flow lifecycle management
|
|
735
|
+
│ ├── userContextService.ts # User context tracking
|
|
736
|
+
│ └── pageContextService.ts # Page navigation tracking
|
|
737
|
+
├── utils/ # Utility functions
|
|
738
|
+
│ ├── selectors.ts # DOM selector helpers
|
|
739
|
+
│ ├── analytics.ts # Analytics and tracking
|
|
740
|
+
│ └── validation.ts # Input validation
|
|
741
|
+
└── styles/ # Component styles
|
|
742
|
+
├── modal.css.ts # Modal styling
|
|
743
|
+
└── ... # Other component styles
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
### Key Components
|
|
747
|
+
|
|
748
|
+
- **FlowEngine**: Orchestrates flow execution and step management
|
|
749
|
+
- **TriggerManager**: Handles DOM event binding and trigger evaluation
|
|
750
|
+
- **PageContextService**: Tracks page navigation and context changes
|
|
751
|
+
- **UserContextService**: Manages user state and preferences
|
|
752
|
+
- **ValidationInterceptor**: Handles form validation integration
|
|
753
|
+
|
|
754
|
+
## Running & Testing
|
|
755
|
+
|
|
756
|
+
### Local Testing Strategy
|
|
757
|
+
|
|
758
|
+
1. **Development Server**: Use `npm run dev` for hot reloading
|
|
759
|
+
2. **Test Pages**: Create HTML pages in `public/` for manual testing
|
|
760
|
+
3. **Flow JSON**: Place test flow configurations in `public/test-flows/`
|
|
761
|
+
4. **Browser DevTools**: Use debug mode for real-time inspection
|
|
762
|
+
|
|
763
|
+
### Sample Flow JSON for Testing
|
|
764
|
+
|
|
765
|
+
```json
|
|
766
|
+
{
|
|
767
|
+
"flowId": "test-onboarding",
|
|
768
|
+
"flowName": "Test Onboarding Flow",
|
|
769
|
+
"execution": {
|
|
770
|
+
"mode": "Linear",
|
|
771
|
+
"frequency": {
|
|
772
|
+
"type": "OneTime",
|
|
773
|
+
"maxRuns": 1
|
|
774
|
+
}
|
|
775
|
+
},
|
|
776
|
+
"steps": [
|
|
777
|
+
{
|
|
778
|
+
"stepId": "welcome-modal",
|
|
779
|
+
"stepOrder": 1,
|
|
780
|
+
"stepType": "Mandatory",
|
|
781
|
+
"uxExperience": {
|
|
782
|
+
"uxExperienceType": "modal",
|
|
783
|
+
"elementSelector": "body",
|
|
784
|
+
"elementTrigger": "immediate",
|
|
785
|
+
"modalContent": {
|
|
786
|
+
"title": "Welcome!",
|
|
787
|
+
"body": [
|
|
788
|
+
{ "kind": "text", "html": "<p>Welcome to our application!</p>" },
|
|
789
|
+
{ "kind": "text", "html": "<p>Let's get you started!</p>" }
|
|
790
|
+
]
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
"stepId": "feature-tooltip",
|
|
796
|
+
"stepOrder": 2,
|
|
797
|
+
"stepType": "Optional",
|
|
798
|
+
"uxExperience": {
|
|
799
|
+
"uxExperienceType": "tooltip",
|
|
800
|
+
"elementSelector": "#main-feature",
|
|
801
|
+
"elementTrigger": "hover",
|
|
802
|
+
"content": {
|
|
803
|
+
"text": "This is our main feature!"
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
]
|
|
808
|
+
}
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
### Debug Tips
|
|
812
|
+
|
|
813
|
+
```javascript
|
|
814
|
+
// Inspect current SDK state
|
|
815
|
+
console.log(DAP.getFlowState());
|
|
816
|
+
|
|
817
|
+
// Check user context
|
|
818
|
+
console.log(DAP.getUserState());
|
|
819
|
+
|
|
820
|
+
// Execute custom flow
|
|
821
|
+
await DAP.executeFlow(customFlowData);
|
|
822
|
+
|
|
823
|
+
// Register flow for later execution
|
|
824
|
+
DAP.registerFlow(flowData);
|
|
825
|
+
|
|
826
|
+
// Start registered flow by ID
|
|
827
|
+
await DAP.startFlow('my-flow-id');
|
|
828
|
+
|
|
829
|
+
// Validate selectors
|
|
830
|
+
const element = DAP.resolveSelector('#my-button'); // Returns element or null
|
|
831
|
+
|
|
832
|
+
// Debug utilities (only available when debug=true)
|
|
833
|
+
if (window.__DAP_DEBUG__) {
|
|
834
|
+
await DAP.testFlow('flow-id'); // Test specific flow
|
|
835
|
+
DAP.renderModal(modalConfig); // Test modal rendering
|
|
836
|
+
}
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
## Advanced API
|
|
840
|
+
|
|
841
|
+
### Flow Management
|
|
842
|
+
|
|
843
|
+
#### Register Custom Flows
|
|
844
|
+
```javascript
|
|
845
|
+
// Register a flow for later execution
|
|
846
|
+
DAP.registerFlow({
|
|
847
|
+
flowId: 'custom-onboarding',
|
|
848
|
+
flowName: 'Custom Onboarding Flow',
|
|
849
|
+
execution: {
|
|
850
|
+
mode: 'Linear',
|
|
851
|
+
frequency: { type: 'OneTime', maxRuns: 1 }
|
|
852
|
+
},
|
|
853
|
+
steps: [
|
|
854
|
+
{
|
|
855
|
+
stepId: 'welcome',
|
|
856
|
+
stepOrder: 1,
|
|
857
|
+
stepType: 'Mandatory',
|
|
858
|
+
uxExperience: {
|
|
859
|
+
uxExperienceType: 'modal',
|
|
860
|
+
elementTrigger: 'immediate',
|
|
861
|
+
modalContent: {
|
|
862
|
+
title: 'Welcome!',
|
|
863
|
+
body: [{ kind: 'text', html: '<p>Welcome to our app!</p>' }]
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
]
|
|
868
|
+
});
|
|
869
|
+
|
|
870
|
+
// Execute registered flow
|
|
871
|
+
await DAP.startFlow('custom-onboarding');
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
#### Execute Dynamic Flows
|
|
875
|
+
```javascript
|
|
876
|
+
// Execute a flow without registering
|
|
877
|
+
await DAP.executeFlow({
|
|
878
|
+
flowId: 'dynamic-help',
|
|
879
|
+
flowName: 'Dynamic Help Flow',
|
|
880
|
+
steps: [
|
|
881
|
+
{
|
|
882
|
+
stepId: 'help-tooltip',
|
|
883
|
+
uxExperience: {
|
|
884
|
+
uxExperienceType: 'tooltip',
|
|
885
|
+
elementSelector: '#help-button',
|
|
886
|
+
elementTrigger: 'hover',
|
|
887
|
+
content: { text: 'Click here for help!' }
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
]
|
|
891
|
+
});
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
### Debug and Development
|
|
895
|
+
|
|
896
|
+
#### State Inspection
|
|
897
|
+
```javascript
|
|
898
|
+
// Get current flow engine state
|
|
899
|
+
const flowState = DAP.getFlowState();
|
|
900
|
+
console.log('Active flow:', flowState.activeFlowId);
|
|
901
|
+
console.log('Flow in progress:', flowState.flowInProgress);
|
|
902
|
+
|
|
903
|
+
// Get user context debug state
|
|
904
|
+
const userState = DAP.getUserState();
|
|
905
|
+
console.log('Has user:', userState.hasUser);
|
|
906
|
+
console.log('User ID:', userState.userId);
|
|
907
|
+
console.log('Is anonymous:', userState.isAnonymous);
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
#### Element Resolution
|
|
911
|
+
```javascript
|
|
912
|
+
// Test selector resolution (useful for debugging)
|
|
913
|
+
const element = DAP.resolveSelector('#my-button');
|
|
914
|
+
if (element) {
|
|
915
|
+
console.log('Element found:', element);
|
|
916
|
+
} else {
|
|
917
|
+
console.warn('Element not found');
|
|
918
|
+
}
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
#### Debug Mode Features
|
|
922
|
+
```javascript
|
|
923
|
+
// Available only when debug=true during initialization
|
|
924
|
+
if (window.__DAP_DEBUG__) {
|
|
925
|
+
// Test any flow by ID
|
|
926
|
+
await DAP.testFlow('flow-id-from-backend');
|
|
927
|
+
|
|
928
|
+
// Test modal rendering directly
|
|
929
|
+
DAP.renderModal({
|
|
930
|
+
title: 'Test Modal',
|
|
931
|
+
body: [{ kind: 'text', html: '<p>Testing modal</p>' }]
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
### Core Services Access
|
|
937
|
+
|
|
938
|
+
For advanced use cases, you can access core services directly:
|
|
939
|
+
|
|
940
|
+
```javascript
|
|
941
|
+
// Location context service
|
|
942
|
+
const locationService = DAP.locationContext;
|
|
943
|
+
console.log('Current context:', locationService.getContext());
|
|
944
|
+
|
|
945
|
+
// User context service
|
|
946
|
+
const userService = DAP.userContext;
|
|
947
|
+
console.log('Analytics context:', userService.getAnalyticsContext());
|
|
948
|
+
|
|
949
|
+
// Flow engine (use with caution)
|
|
950
|
+
const engine = DAP.flowEngine;
|
|
951
|
+
console.log('Engine state:', engine.getState());
|
|
952
|
+
```
|
|
953
|
+
|
|
954
|
+
## Configuration Reference
|
|
955
|
+
|
|
956
|
+
### Execution Configuration
|
|
957
|
+
|
|
958
|
+
```typescript
|
|
959
|
+
interface ExecutionConfig {
|
|
960
|
+
mode: 'Linear' | 'AnyOrder';
|
|
961
|
+
multiPage?: boolean; // Enable multi-page flows
|
|
962
|
+
frequency?: {
|
|
963
|
+
type: 'OneTime' | 'Daily' | 'Weekly' | 'Monthly';
|
|
964
|
+
maxRuns: number; // Maximum execution count
|
|
965
|
+
};
|
|
966
|
+
targeting?: {
|
|
967
|
+
pages?: string[]; // URL patterns
|
|
968
|
+
userSegments?: string[]; // User segments
|
|
969
|
+
devices?: string[]; // Device types
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
### Trigger Configuration
|
|
975
|
+
|
|
976
|
+
```typescript
|
|
977
|
+
interface TriggerConfig {
|
|
978
|
+
elementSelector: string; // CSS selector
|
|
979
|
+
elementTrigger: string; // Event type
|
|
980
|
+
debounce?: number; // Debounce delay (ms)
|
|
981
|
+
once?: boolean; // Fire only once
|
|
982
|
+
conditions?: string[]; // Additional conditions
|
|
983
|
+
}
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
### Step Configuration
|
|
987
|
+
|
|
988
|
+
```typescript
|
|
989
|
+
interface StepConfig {
|
|
990
|
+
stepId: string;
|
|
991
|
+
stepOrder?: number; // For Linear flows
|
|
992
|
+
stepType: 'Mandatory' | 'Optional' | 'Rule';
|
|
993
|
+
uxExperience: UXExperience;
|
|
994
|
+
targeting?: PageTargeting; // Step-specific targeting
|
|
995
|
+
}
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
### Rule Configuration
|
|
999
|
+
|
|
1000
|
+
```typescript
|
|
1001
|
+
interface RuleConfig {
|
|
1002
|
+
userInputSelector: string; // Input element selector
|
|
1003
|
+
conditionRuleBlocks: {
|
|
1004
|
+
ruleBlockId: string;
|
|
1005
|
+
rules: {
|
|
1006
|
+
condition: 'equals' | 'contains' | 'matches';
|
|
1007
|
+
value: string;
|
|
1008
|
+
}[];
|
|
1009
|
+
nextFlowId: string; // Target flow for this rule
|
|
1010
|
+
}[];
|
|
1011
|
+
}
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
## FAQ
|
|
1015
|
+
|
|
1016
|
+
### Why isn't my step triggering?
|
|
1017
|
+
|
|
1018
|
+
1. **Check selector**: Verify the element exists: `document.querySelector(selector)`
|
|
1019
|
+
2. **Check page context**: Ensure you're on the correct page
|
|
1020
|
+
3. **Check timing**: Element might not be ready; add delays or use `waitForElement`
|
|
1021
|
+
4. **Check trigger type**: Verify the trigger event is appropriate for the element
|
|
1022
|
+
|
|
1023
|
+
### How does multi-page support work?
|
|
1024
|
+
|
|
1025
|
+
The SDK automatically:
|
|
1026
|
+
- Detects page navigation events
|
|
1027
|
+
- Preserves flow state across pages
|
|
1028
|
+
- Re-evaluates step relevance on each page
|
|
1029
|
+
- Handles both SPA and traditional page navigation
|
|
1030
|
+
|
|
1031
|
+
### Why are rules evaluated late in the flow?
|
|
1032
|
+
|
|
1033
|
+
Rule steps are evaluated when:
|
|
1034
|
+
- The user interacts with the specified input element
|
|
1035
|
+
- Input value changes trigger rule evaluation
|
|
1036
|
+
- This allows for dynamic flow branching based on user choices
|
|
1037
|
+
|
|
1038
|
+
### How do I avoid selector issues?
|
|
1039
|
+
|
|
1040
|
+
1. **Use stable selectors**: Prefer `data-*` attributes over CSS classes
|
|
1041
|
+
2. **Test selectors**: Verify selectors work in browser DevTools
|
|
1042
|
+
3. **Add fallbacks**: Provide alternative selectors when possible
|
|
1043
|
+
4. **Use semantic HTML**: Leverage semantic elements with stable attributes
|
|
1044
|
+
|
|
1045
|
+
### Can I customize component styles?
|
|
1046
|
+
|
|
1047
|
+
Yes! Components support:
|
|
1048
|
+
- **CSS custom properties**: Override default styles
|
|
1049
|
+
- **Theme configuration**: Pass custom themes via flow JSON
|
|
1050
|
+
- **Style injection**: Inject custom CSS for specific experiences
|
|
1051
|
+
|
|
1052
|
+
### How do I handle dynamic content?
|
|
1053
|
+
|
|
1054
|
+
- **Observer patterns**: SDK automatically observes DOM changes
|
|
1055
|
+
- **Refresh triggers**: Call `DAP.refreshFlows()` after content updates
|
|
1056
|
+
- **Dynamic selectors**: Use flexible selectors that work with dynamic IDs
|
|
1057
|
+
|
|
1058
|
+
## Versioning & Compatibility
|
|
1059
|
+
|
|
1060
|
+
### SDK Versioning
|
|
1061
|
+
|
|
1062
|
+
The SDK follows [Semantic Versioning](https://semver.org/):
|
|
1063
|
+
|
|
1064
|
+
- **Major** (X.0.0): Breaking changes, requires code updates
|
|
1065
|
+
- **Minor** (0.X.0): New features, backward compatible
|
|
1066
|
+
- **Patch** (0.0.X): Bug fixes, backward compatible
|
|
1067
|
+
|
|
1068
|
+
### Flow JSON Compatibility
|
|
1069
|
+
|
|
1070
|
+
- **Backward Compatible**: New SDK versions support older Flow JSON schemas
|
|
1071
|
+
- **Deprecation Notices**: Old features marked deprecated with migration guidance
|
|
1072
|
+
- **Schema Evolution**: New flow features added incrementally
|
|
1073
|
+
|
|
1074
|
+
### Upgrade Notes
|
|
1075
|
+
|
|
1076
|
+
```javascript
|
|
1077
|
+
// Version 2.x → 3.x Migration Example
|
|
1078
|
+
// OLD (deprecated)
|
|
1079
|
+
await DAP.init(config);
|
|
1080
|
+
|
|
1081
|
+
// NEW (recommended)
|
|
1082
|
+
await DAP.initialize(config);
|
|
1083
|
+
|
|
1084
|
+
// Check for deprecation warnings in console during development
|
|
1085
|
+
```
|
|
1086
|
+
|
|
1087
|
+
### Browser Support Policy
|
|
1088
|
+
|
|
1089
|
+
- **Current**: Support for current and previous major browser versions
|
|
1090
|
+
- **Legacy**: Best-effort support for IE 11 (with polyfills)
|
|
1091
|
+
- **Testing**: Automated testing across major browser combinations
|
|
1092
|
+
|
|
1093
|
+
## License & Support
|
|
1094
|
+
|
|
1095
|
+
### License
|
|
1096
|
+
|
|
1097
|
+
This SDK is proprietary software licensed under the [Your Company License Agreement]. See `LICENSE.md` for complete terms.
|
|
1098
|
+
|
|
1099
|
+
### Support & Contact
|
|
1100
|
+
|
|
1101
|
+
- **Documentation**: [https://docs.your-company.com/dap-sdk](https://docs.your-company.com/dap-sdk)
|
|
1102
|
+
- **Support Portal**: [https://support.your-company.com](https://support.your-company.com)
|
|
1103
|
+
- **Community Forum**: [https://community.your-company.com](https://community.your-company.com)
|
|
1104
|
+
- **Email Support**: [dap-support@your-company.com](mailto:dap-support@your-company.com)
|
|
1105
|
+
|
|
1106
|
+
### Contributing
|
|
1107
|
+
|
|
1108
|
+
We welcome contributions from the community! Please see `CONTRIBUTING.md` for guidelines on:
|
|
1109
|
+
|
|
1110
|
+
- Code standards and style guide
|
|
1111
|
+
- Testing requirements
|
|
1112
|
+
- Pull request process
|
|
1113
|
+
- Issue reporting templates
|
|
1114
|
+
|
|
1115
|
+
---
|
|
1116
|
+
|
|
1117
|
+
**Built with ❤️ by the DAP Team**
|