@prosdevlab/experience-sdk-plugins 0.1.0 → 0.1.3
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/.turbo/turbo-build.log +17 -0
- package/CHANGELOG.md +37 -0
- package/LICENSE +21 -0
- package/README.md +154 -0
- package/dist/index.d.ts +213 -0
- package/dist/index.js +634 -0
- package/dist/index.js.map +1 -0
- package/package.json +18 -11
- package/src/banner/banner.test.ts +370 -10
- package/src/banner/banner.ts +246 -119
- package/src/types.ts +22 -0
- package/src/utils/sanitize.test.ts +412 -0
- package/src/utils/sanitize.ts +196 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
> @prosdevlab/experience-sdk-plugins@0.1.3 build /home/runner/work/experience-sdk/experience-sdk/packages/plugins
|
|
3
|
+
> tsup
|
|
4
|
+
|
|
5
|
+
[34mCLI[39m Building entry: src/index.ts
|
|
6
|
+
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
|
+
[34mCLI[39m tsup v8.5.1
|
|
8
|
+
[34mCLI[39m Using tsup config: /home/runner/work/experience-sdk/experience-sdk/packages/plugins/tsup.config.ts
|
|
9
|
+
[34mCLI[39m Target: es2024
|
|
10
|
+
[34mCLI[39m Cleaning output folder
|
|
11
|
+
[34mESM[39m Build start
|
|
12
|
+
[32mESM[39m [1mdist/index.js [22m[32m17.87 KB[39m
|
|
13
|
+
[32mESM[39m [1mdist/index.js.map [22m[32m44.45 KB[39m
|
|
14
|
+
[32mESM[39m ⚡️ Build success in 190ms
|
|
15
|
+
[34mDTS[39m Build start
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 873ms
|
|
17
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m5.09 KB[39m
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# @prosdevlab/experience-sdk-plugins
|
|
2
|
+
|
|
3
|
+
## 0.1.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 41c0aa5: Fix npm publishing error by adding repository field to package.json
|
|
8
|
+
|
|
9
|
+
- Add repository field required for npm provenance verification
|
|
10
|
+
|
|
11
|
+
## 0.1.2
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- a6842e2: Fix npm publishing error by adding repository field to package.json
|
|
16
|
+
|
|
17
|
+
- Add repository field required for npm provenance verification
|
|
18
|
+
|
|
19
|
+
## 0.1.1
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- c5e46c0: Fix BannerContent type definition, add CSS customization support, and implement HTML sanitization:
|
|
24
|
+
|
|
25
|
+
- Add `buttons` array property with variant and metadata support
|
|
26
|
+
- Add `position` property (top/bottom)
|
|
27
|
+
- Make `title` optional (message is the only required field)
|
|
28
|
+
- Add `className` and `style` props for banner and buttons
|
|
29
|
+
- Update banner plugin to use `.xp-*` CSS classes
|
|
30
|
+
- Provide minimal, functional default styles
|
|
31
|
+
- Add HTML sanitizer for XSS prevention in title and message fields
|
|
32
|
+
- Support safe HTML tags (strong, em, a, br, span, b, i, p)
|
|
33
|
+
- Block dangerous tags and event handlers
|
|
34
|
+
- Sanitize URLs to prevent javascript: and data: attacks
|
|
35
|
+
- Aligns core types with banner plugin implementation
|
|
36
|
+
|
|
37
|
+
This enables users to customize banners with Tailwind, design systems, or CSS frameworks while maintaining SDK's focus on targeting logic. HTML sanitization ensures safe rendering of user-provided content.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 prosdevlab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# @prosdevlab/experience-sdk-plugins
|
|
2
|
+
|
|
3
|
+
Official plugins for [Experience SDK](https://github.com/prosdevlab/experience-sdk).
|
|
4
|
+
|
|
5
|
+
**Size:** 13.4 KB (ESM)
|
|
6
|
+
|
|
7
|
+
## Included Plugins
|
|
8
|
+
|
|
9
|
+
### Banner Plugin
|
|
10
|
+
|
|
11
|
+
Renders banner experiences in the DOM with automatic positioning, theming, and responsive layout.
|
|
12
|
+
|
|
13
|
+
**Features:**
|
|
14
|
+
- Multiple buttons with variants (primary, secondary, link)
|
|
15
|
+
- Responsive layout (desktop inline, mobile stack)
|
|
16
|
+
- Automatic theme detection (light/dark mode)
|
|
17
|
+
- Top/bottom positioning
|
|
18
|
+
- Dismissable with close button
|
|
19
|
+
- **CSS customization** via `className` and `style` props
|
|
20
|
+
- Stable `.xp-*` CSS classes for styling
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { createInstance, bannerPlugin } from '@prosdevlab/experience-sdk-plugins';
|
|
24
|
+
|
|
25
|
+
const sdk = createInstance();
|
|
26
|
+
sdk.use(bannerPlugin);
|
|
27
|
+
|
|
28
|
+
sdk.banner.show({
|
|
29
|
+
id: 'welcome',
|
|
30
|
+
type: 'banner',
|
|
31
|
+
content: {
|
|
32
|
+
title: 'Welcome!',
|
|
33
|
+
message: 'Thanks for visiting.',
|
|
34
|
+
buttons: [
|
|
35
|
+
{ text: 'Get Started', url: '/start', variant: 'primary' }
|
|
36
|
+
],
|
|
37
|
+
position: 'top',
|
|
38
|
+
dismissable: true
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Customization:**
|
|
44
|
+
|
|
45
|
+
The banner plugin uses `.xp-*` CSS classes and supports custom styling:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// With Tailwind
|
|
49
|
+
content: {
|
|
50
|
+
message: 'Flash Sale!',
|
|
51
|
+
className: 'bg-gradient-to-r from-blue-600 to-purple-600 text-white',
|
|
52
|
+
buttons: [{
|
|
53
|
+
text: 'Shop Now',
|
|
54
|
+
className: 'bg-white text-blue-600 hover:bg-gray-100'
|
|
55
|
+
}]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// With inline styles
|
|
59
|
+
content: {
|
|
60
|
+
message: 'Flash Sale!',
|
|
61
|
+
style: {
|
|
62
|
+
background: 'linear-gradient(90deg, #667eea 0%, #764ba2 100%)',
|
|
63
|
+
color: 'white'
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
See the [Plugins documentation](https://prosdevlab.github.io/experience-sdk/reference/plugins#customization) for more customization examples.
|
|
69
|
+
|
|
70
|
+
### Frequency Plugin
|
|
71
|
+
|
|
72
|
+
Manages impression tracking and frequency capping with persistent storage.
|
|
73
|
+
|
|
74
|
+
**Features:**
|
|
75
|
+
- Session/day/week impression tracking
|
|
76
|
+
- Automatic storage management
|
|
77
|
+
- Manual impression recording
|
|
78
|
+
- Reset capabilities
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { createInstance, frequencyPlugin } from '@prosdevlab/experience-sdk-plugins';
|
|
82
|
+
|
|
83
|
+
const sdk = createInstance();
|
|
84
|
+
sdk.use(frequencyPlugin);
|
|
85
|
+
|
|
86
|
+
// Check impression count
|
|
87
|
+
const count = sdk.frequency.getImpressionCount('welcome', 'session');
|
|
88
|
+
|
|
89
|
+
// Record impression
|
|
90
|
+
sdk.frequency.recordImpression('welcome');
|
|
91
|
+
|
|
92
|
+
// Reset counts
|
|
93
|
+
sdk.frequency.reset('welcome');
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Debug Plugin
|
|
97
|
+
|
|
98
|
+
Provides console logging and window event emission for debugging and Chrome extension integration.
|
|
99
|
+
|
|
100
|
+
**Features:**
|
|
101
|
+
- Console logging with prefix
|
|
102
|
+
- Window event emission
|
|
103
|
+
- Automatic decision logging
|
|
104
|
+
- Configurable logging levels
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { createInstance, debugPlugin } from '@prosdevlab/experience-sdk-plugins';
|
|
108
|
+
|
|
109
|
+
const sdk = createInstance({ debug: true });
|
|
110
|
+
sdk.use(debugPlugin);
|
|
111
|
+
|
|
112
|
+
// Manual logging
|
|
113
|
+
sdk.debug.log('Custom message', { foo: 'bar' });
|
|
114
|
+
|
|
115
|
+
// Listen to debug events
|
|
116
|
+
window.addEventListener('experiences:debug', (event) => {
|
|
117
|
+
console.log(event.detail);
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Installation
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npm install @prosdevlab/experience-sdk-plugins
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Or use the main package which includes these plugins:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npm install @prosdevlab/experience-sdk
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Usage
|
|
134
|
+
|
|
135
|
+
These plugins are automatically included when using `@prosdevlab/experience-sdk`. You only need this package if you want to use the plugins separately with a custom sdk-kit setup.
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import { createInstance } from '@prosdevlab/experience-sdk';
|
|
139
|
+
|
|
140
|
+
// Plugins are already included and available
|
|
141
|
+
const experiences = createInstance({ debug: true });
|
|
142
|
+
experiences.register('banner', { ... });
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Documentation
|
|
146
|
+
|
|
147
|
+
- [Full Documentation](https://prosdevlab.github.io/experience-sdk)
|
|
148
|
+
- [Plugins Guide](https://prosdevlab.github.io/experience-sdk/reference/plugins)
|
|
149
|
+
- [Banner Examples](https://prosdevlab.github.io/experience-sdk/demo/banner)
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
MIT
|
|
154
|
+
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { PluginFunction } from '@lytics/sdk-kit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared types for Experience SDK plugins
|
|
5
|
+
* These types are re-exported by core for user convenience
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Experience content - varies by type
|
|
9
|
+
*/
|
|
10
|
+
type ExperienceContent = BannerContent | ModalContent | TooltipContent;
|
|
11
|
+
/**
|
|
12
|
+
* Banner content configuration
|
|
13
|
+
*/
|
|
14
|
+
interface BannerContent {
|
|
15
|
+
title?: string;
|
|
16
|
+
message: string;
|
|
17
|
+
buttons?: Array<{
|
|
18
|
+
text: string;
|
|
19
|
+
action?: string;
|
|
20
|
+
url?: string;
|
|
21
|
+
variant?: 'primary' | 'secondary' | 'link';
|
|
22
|
+
metadata?: Record<string, any>;
|
|
23
|
+
className?: string;
|
|
24
|
+
style?: Record<string, string>;
|
|
25
|
+
}>;
|
|
26
|
+
dismissable?: boolean;
|
|
27
|
+
position?: 'top' | 'bottom';
|
|
28
|
+
className?: string;
|
|
29
|
+
style?: Record<string, string>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Modal content configuration
|
|
33
|
+
*/
|
|
34
|
+
interface ModalContent {
|
|
35
|
+
title: string;
|
|
36
|
+
message: string;
|
|
37
|
+
confirmText?: string;
|
|
38
|
+
cancelText?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Modal content configuration
|
|
42
|
+
*/
|
|
43
|
+
interface ModalContent {
|
|
44
|
+
title: string;
|
|
45
|
+
message: string;
|
|
46
|
+
confirmText?: string;
|
|
47
|
+
cancelText?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Tooltip content configuration
|
|
51
|
+
*/
|
|
52
|
+
interface TooltipContent {
|
|
53
|
+
message: string;
|
|
54
|
+
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Tooltip content configuration
|
|
58
|
+
*/
|
|
59
|
+
interface TooltipContent {
|
|
60
|
+
message: string;
|
|
61
|
+
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Experience definition
|
|
65
|
+
*/
|
|
66
|
+
interface Experience {
|
|
67
|
+
id: string;
|
|
68
|
+
type: 'banner' | 'modal' | 'tooltip';
|
|
69
|
+
targeting: Record<string, any>;
|
|
70
|
+
content: ExperienceContent;
|
|
71
|
+
frequency?: {
|
|
72
|
+
max: number;
|
|
73
|
+
per: 'session' | 'day' | 'week';
|
|
74
|
+
};
|
|
75
|
+
priority?: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Decision output from evaluation
|
|
79
|
+
*/
|
|
80
|
+
interface Decision {
|
|
81
|
+
show: boolean;
|
|
82
|
+
experienceId?: string;
|
|
83
|
+
reasons: string[];
|
|
84
|
+
trace: TraceStep[];
|
|
85
|
+
context: Record<string, any>;
|
|
86
|
+
metadata: DecisionMetadata;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Trace step for decision path
|
|
90
|
+
*/
|
|
91
|
+
interface TraceStep {
|
|
92
|
+
step: string;
|
|
93
|
+
timestamp: number;
|
|
94
|
+
duration: number;
|
|
95
|
+
input?: any;
|
|
96
|
+
output?: any;
|
|
97
|
+
passed: boolean;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Decision metadata
|
|
101
|
+
*/
|
|
102
|
+
interface DecisionMetadata {
|
|
103
|
+
evaluatedAt: number;
|
|
104
|
+
experienceCount: number;
|
|
105
|
+
evaluationTimeMs: number;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Banner Plugin
|
|
110
|
+
*
|
|
111
|
+
* Renders banner experiences at the top or bottom of the page.
|
|
112
|
+
* Auto-shows banners when experiences are evaluated.
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
interface BannerPluginConfig {
|
|
116
|
+
banner?: {
|
|
117
|
+
position?: 'top' | 'bottom';
|
|
118
|
+
dismissable?: boolean;
|
|
119
|
+
zIndex?: number;
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
interface BannerPlugin {
|
|
123
|
+
show(experience: Experience): void;
|
|
124
|
+
remove(): void;
|
|
125
|
+
isShowing(): boolean;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Banner Plugin
|
|
129
|
+
*
|
|
130
|
+
* Automatically renders banner experiences when they are evaluated.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* import { createInstance } from '@prosdevlab/experience-sdk';
|
|
135
|
+
* import { bannerPlugin } from '@prosdevlab/experience-sdk-plugins';
|
|
136
|
+
*
|
|
137
|
+
* const sdk = createInstance({ banner: { position: 'top', dismissable: true } });
|
|
138
|
+
* sdk.use(bannerPlugin);
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
declare const bannerPlugin: PluginFunction;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Debug Plugin
|
|
145
|
+
*
|
|
146
|
+
* Emits structured debug events to window and optionally logs to console.
|
|
147
|
+
* Useful for debugging and Chrome extension integration.
|
|
148
|
+
*/
|
|
149
|
+
|
|
150
|
+
interface DebugPluginConfig {
|
|
151
|
+
debug?: {
|
|
152
|
+
enabled?: boolean;
|
|
153
|
+
console?: boolean;
|
|
154
|
+
window?: boolean;
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
interface DebugPlugin {
|
|
158
|
+
log(message: string, data?: unknown): void;
|
|
159
|
+
isEnabled(): boolean;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Debug Plugin
|
|
163
|
+
*
|
|
164
|
+
* Listens to all SDK events and emits them as window events for debugging.
|
|
165
|
+
* Also optionally logs to console.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* import { createInstance } from '@prosdevlab/experience-sdk';
|
|
170
|
+
* import { debugPlugin } from '@prosdevlab/experience-sdk-plugins';
|
|
171
|
+
*
|
|
172
|
+
* const sdk = createInstance({ debug: { enabled: true, console: true } });
|
|
173
|
+
* sdk.use(debugPlugin);
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
declare const debugPlugin: PluginFunction;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Frequency Capping Plugin
|
|
180
|
+
*
|
|
181
|
+
* Tracks experience impressions and enforces frequency caps.
|
|
182
|
+
* Uses sdk-kit's storage plugin for persistence.
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
interface FrequencyPluginConfig {
|
|
186
|
+
frequency?: {
|
|
187
|
+
enabled?: boolean;
|
|
188
|
+
namespace?: string;
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
interface FrequencyPlugin {
|
|
192
|
+
getImpressionCount(experienceId: string): number;
|
|
193
|
+
hasReachedCap(experienceId: string, max: number, per: 'session' | 'day' | 'week'): boolean;
|
|
194
|
+
recordImpression(experienceId: string): void;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Frequency Capping Plugin
|
|
198
|
+
*
|
|
199
|
+
* Automatically tracks impressions and enforces frequency caps.
|
|
200
|
+
* Requires storage plugin for persistence.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```typescript
|
|
204
|
+
* import { createInstance } from '@prosdevlab/experience-sdk';
|
|
205
|
+
* import { frequencyPlugin } from '@prosdevlab/experience-sdk-plugins';
|
|
206
|
+
*
|
|
207
|
+
* const sdk = createInstance({ frequency: { enabled: true } });
|
|
208
|
+
* sdk.use(frequencyPlugin);
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
declare const frequencyPlugin: PluginFunction;
|
|
212
|
+
|
|
213
|
+
export { type BannerContent, type BannerPlugin, type BannerPluginConfig, type DebugPlugin, type DebugPluginConfig, type Decision, type DecisionMetadata, type Experience, type ExperienceContent, type FrequencyPlugin, type FrequencyPluginConfig, type ModalContent, type TooltipContent, type TraceStep, bannerPlugin, debugPlugin, frequencyPlugin };
|