@levi123/experiment 4.0.0-dev.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.
Files changed (39) hide show
  1. package/README.md +464 -0
  2. package/dist/esm/components/experiment-wrapper.d.ts +16 -0
  3. package/dist/esm/components/index.d.ts +1 -0
  4. package/dist/esm/constants/index.d.ts +12 -0
  5. package/dist/esm/core/ab-testing.d.ts +3 -0
  6. package/dist/esm/core/index.d.ts +1 -0
  7. package/dist/esm/index.d.ts +5 -0
  8. package/dist/esm/index.js +685 -0
  9. package/dist/esm/index.mjs +685 -0
  10. package/dist/esm/tracking/tracker.d.ts +12 -0
  11. package/dist/esm/types/devices.d.ts +5 -0
  12. package/dist/esm/types/experiments.d.ts +82 -0
  13. package/dist/esm/types/index.d.ts +2 -0
  14. package/dist/esm/utils/cookie.d.ts +21 -0
  15. package/dist/esm/utils/devices.d.ts +2 -0
  16. package/dist/esm/utils/experiment-wrapper-helpers.d.ts +21 -0
  17. package/dist/esm/utils/index.d.ts +6 -0
  18. package/dist/esm/utils/session.d.ts +1 -0
  19. package/dist/esm/utils/storage.d.ts +3 -0
  20. package/dist/esm/utils/user.d.ts +2 -0
  21. package/dist/umd/components/experiment-wrapper.d.ts +16 -0
  22. package/dist/umd/components/index.d.ts +1 -0
  23. package/dist/umd/constants/index.d.ts +12 -0
  24. package/dist/umd/core/ab-testing.d.ts +3 -0
  25. package/dist/umd/core/index.d.ts +1 -0
  26. package/dist/umd/index.d.ts +5 -0
  27. package/dist/umd/index.js +1 -0
  28. package/dist/umd/tracking/tracker.d.ts +12 -0
  29. package/dist/umd/types/devices.d.ts +5 -0
  30. package/dist/umd/types/experiments.d.ts +82 -0
  31. package/dist/umd/types/index.d.ts +2 -0
  32. package/dist/umd/utils/cookie.d.ts +21 -0
  33. package/dist/umd/utils/devices.d.ts +2 -0
  34. package/dist/umd/utils/experiment-wrapper-helpers.d.ts +21 -0
  35. package/dist/umd/utils/index.d.ts +6 -0
  36. package/dist/umd/utils/session.d.ts +1 -0
  37. package/dist/umd/utils/storage.d.ts +3 -0
  38. package/dist/umd/utils/user.d.ts +2 -0
  39. package/package.json +64 -0
package/README.md ADDED
@@ -0,0 +1,464 @@
1
+ # @levi123/experiment (develop)
2
+
3
+ <!-- [![npm version](https://badge.fury.io/js/%40gemx%ab-2Fexperiment.svg)](https://badge.fury.io/js/%40gemx%ab-2Fexperiment)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/) -->
6
+
7
+ > **The most developer-friendly A/B testing library for modern web applications**
8
+
9
+ A powerful, framework-agnostic A/B testing library that works seamlessly with React, Vue, Angular, and vanilla JavaScript. Built with TypeScript for type safety and designed for optimal developer experience.
10
+
11
+ ## ✨ Features
12
+
13
+ - 🚀 **Zero Configuration** - Start testing in minutes with our intuitive API
14
+ - 🛡️ **Type-Safe** - Full TypeScript support with intelligent autocompletion
15
+ - 🌐 **Framework Agnostic** - Works with React, Vue, Angular, or vanilla JavaScript
16
+ - 📊 **Built-in Analytics** - Seamless integration with Google Analytics, Mixpanel, and more
17
+ - 🎯 **Smart Targeting** - Device, location, and custom targeting rules
18
+ - 🔧 **Developer Experience** - Built-in debugging, error handling, and clean APIs
19
+ - 📦 **Lightweight** - Minimal bundle size with tree-shaking support
20
+ - 🔄 **Persistent** - User assignments persist across sessions
21
+ - 🎨 **Flexible** - Support for weighted variants and custom metadata
22
+
23
+ ## 📦 Installation
24
+
25
+ ```bash
26
+ # npm
27
+ npm install @levi123/experiment
28
+
29
+ # yarn
30
+ yarn add @levi123/experiment
31
+
32
+ # pnpm
33
+ pnpm add @levi123/experiment
34
+ ```
35
+
36
+ ## 🚀 Quick Start
37
+
38
+ ### React
39
+
40
+ ```tsx
41
+ import { GxExperimentWrapper, getVariant } from '@levi123/experiment/react';
42
+
43
+ const variant = getVariant({
44
+ experimentId: 'hero-test',
45
+ variants: [
46
+ { name: 'A', weight: 0.5 },
47
+ { name: 'B', weight: 0.5 },
48
+ ],
49
+ });
50
+
51
+ function HeroSection() {
52
+ return (
53
+ <GxExperimentWrapper variant={variant} experimentId="hero-test" onTrack={(event, data) => console.log(event, data)}>
54
+ <div data-variant="A">
55
+ <h1>Welcome to our amazing product!</h1>
56
+ <button>Get Started</button>
57
+ </div>
58
+ <div data-variant="B">
59
+ <h1>Discover something incredible!</h1>
60
+ <button>Try Now</button>
61
+ </div>
62
+ </GxExperimentWrapper>
63
+ );
64
+ }
65
+ ```
66
+
67
+ ### Vue
68
+
69
+ ```vue
70
+ <template>
71
+ <GxExperimentWrapper :variant="variant" experiment-id="hero-test" @track="handleTrack">
72
+ <div data-variant="A">
73
+ <h1>Welcome to our amazing product!</h1>
74
+ <button>Get Started</button>
75
+ </div>
76
+ <div data-variant="B">
77
+ <h1>Discover something incredible!</h1>
78
+ <button>Try Now</button>
79
+ </div>
80
+ </GxExperimentWrapper>
81
+ </template>
82
+
83
+ <script setup lang="ts">
84
+ import { getVariant } from '@levi123/experiment';
85
+ import { GxExperimentWrapper } from '@levi123/experiment/vue';
86
+ import { ref } from 'vue';
87
+
88
+ const variant = ref(
89
+ getVariant({
90
+ experimentId: 'hero-test',
91
+ variants: [
92
+ { name: 'A', weight: 0.5 },
93
+ { name: 'B', weight: 0.5 },
94
+ ],
95
+ }),
96
+ );
97
+
98
+ const handleTrack = (event: string, data: any) => {
99
+ console.log(`Event: ${event}`, data);
100
+ };
101
+ </script>
102
+ ```
103
+
104
+ ### Vanilla JavaScript / HTML
105
+
106
+ ```html
107
+ <!DOCTYPE html>
108
+ <html>
109
+ <head>
110
+ <script src="https://unpkg.com/@levi123/experiment/dist/index.js"></script>
111
+ </head>
112
+ <body>
113
+ <gx-experiment-wrapper variant="A" experiment-id="hero-test">
114
+ <div data-variant="A">
115
+ <h1>Welcome to our amazing product!</h1>
116
+ <button>Get Started</button>
117
+ </div>
118
+ <div data-variant="B">
119
+ <h1>Discover something incredible!</h1>
120
+ <button>Try Now</button>
121
+ </div>
122
+ </gx-experiment-wrapper>
123
+ </body>
124
+ </html>
125
+ ```
126
+
127
+ ## 📚 API Reference
128
+
129
+ ### Core Functions
130
+
131
+ #### `getVariant(config: ExperimentConfig): string`
132
+
133
+ Determines which variant a user should see based on the experiment configuration.
134
+
135
+ ```typescript
136
+ const variant = getVariant({
137
+ experimentId: 'my-experiment',
138
+ variants: [
139
+ { name: 'control', weight: 0.5 },
140
+ { name: 'treatment', weight: 0.5 },
141
+ ],
142
+ weights: [0.5, 0.5], // Optional: override individual variant weights
143
+ description: 'Testing new button color',
144
+ targeting: {
145
+ trafficPercentage: 0.1, // 10% of traffic
146
+ deviceType: 'mobile',
147
+ country: 'US',
148
+ },
149
+ });
150
+ ```
151
+
152
+ ### React Components
153
+
154
+ #### `GxExperimentWrapper`
155
+
156
+ A React wrapper component that handles variant assignment and tracking.
157
+
158
+ ```tsx
159
+ interface ExperimentWrapperProps {
160
+ config: ExperimentConfig;
161
+ trackingEndpoint?: string;
162
+ gaTracking?: boolean;
163
+ autoTrack?: boolean;
164
+ fallbackVariant?: string;
165
+ debug?: boolean;
166
+ loading?: boolean;
167
+ onTrack?: (event: string, data: TrackingEvent) => void;
168
+ onVariantAssigned?: (variant: string, experimentId: string) => void;
169
+ onError?: (error: string, experimentId?: string) => void;
170
+ children: React.ReactNode;
171
+ }
172
+ ```
173
+
174
+ ### Vue Components
175
+
176
+ #### `GxExperimentWrapper`
177
+
178
+ A Vue wrapper component with similar functionality to the React version.
179
+
180
+ ```vue
181
+ <GxExperimentWrapper
182
+ :variant="variant"
183
+ experiment-id="my-experiment"
184
+ :ga-tracking="true"
185
+ :debug="true"
186
+ @track="handleTrack"
187
+ @variant-assigned="handleVariantAssigned"
188
+ @error="handleError"
189
+ >
190
+ <!-- Your variants here -->
191
+ </GxExperimentWrapper>
192
+ ```
193
+
194
+ ### Web Components
195
+
196
+ #### `<gx-experiment-wrapper>`
197
+
198
+ A custom HTML element that works in any framework or vanilla JavaScript.
199
+
200
+ ```html
201
+ <gx-experiment-wrapper variant="A" experiment-id="my-experiment" ga-tracking="true" debug="true">
202
+ <div data-variant="A">Variant A</div>
203
+ <div data-variant="B">Variant B</div>
204
+ </gx-experiment-wrapper>
205
+ ```
206
+
207
+ ### TypeScript Interfaces
208
+
209
+ #### `ExperimentConfig`
210
+
211
+ ```typescript
212
+ interface ExperimentConfig {
213
+ experimentId: string;
214
+ variants: Variant[];
215
+ weights?: number[];
216
+ description?: string;
217
+ targeting?: TargetingConfig;
218
+ metadata?: Record<string, any>;
219
+ }
220
+
221
+ interface Variant {
222
+ name: string;
223
+ weight?: number;
224
+ component?: any;
225
+ metadata?: Record<string, any>;
226
+ }
227
+
228
+ interface TargetingConfig {
229
+ trafficPercentage?: number;
230
+ deviceType?: 'mobile' | 'desktop' | 'tablet';
231
+ country?: string;
232
+ userSegment?: string;
233
+ customRules?: Record<string, any>;
234
+ }
235
+ ```
236
+
237
+ #### `TrackingEvent`
238
+
239
+ ```typescript
240
+ interface TrackingEvent {
241
+ event: string;
242
+ experimentId: string;
243
+ variant: string;
244
+ timestamp: number;
245
+ sessionId?: string;
246
+ userId?: string;
247
+ customData?: Record<string, any>;
248
+ }
249
+ ```
250
+
251
+ ## 🎯 Advanced Usage
252
+
253
+ ### Custom Targeting
254
+
255
+ ```typescript
256
+ const variant = getVariant({
257
+ experimentId: 'premium-feature-test',
258
+ variants: [{ name: 'control' }, { name: 'premium' }],
259
+ targeting: {
260
+ trafficPercentage: 0.2, // 20% of users
261
+ deviceType: 'desktop',
262
+ country: 'US',
263
+ userSegment: 'premium',
264
+ customRules: {
265
+ userAge: { min: 25, max: 65 },
266
+ subscriptionTier: ['pro', 'enterprise'],
267
+ },
268
+ },
269
+ });
270
+ ```
271
+
272
+ ### Analytics Integration
273
+
274
+ ```tsx
275
+ <GxExperimentWrapper
276
+ config={experimentConfig}
277
+ gaTracking={true}
278
+ trackingEndpoint="https://api.yourapp.com/analytics"
279
+ onTrack={(event, data) => {
280
+ // Custom analytics
281
+ analytics.track(event, data);
282
+
283
+ // Google Analytics
284
+ gtag('event', event, {
285
+ experiment_id: data.experimentId,
286
+ variant: data.variant,
287
+ custom_parameter: data.customData,
288
+ });
289
+ }}
290
+ >
291
+ {/* Your variants */}
292
+ </GxExperimentWrapper>
293
+ ```
294
+
295
+ ### Debug Mode
296
+
297
+ ```tsx
298
+ <GxExperimentWrapper
299
+ config={experimentConfig}
300
+ debug={true}
301
+ onVariantAssigned={(variant, experimentId) => {
302
+ console.log(`User assigned to variant ${variant} in experiment ${experimentId}`);
303
+ }}
304
+ onError={(error, experimentId) => {
305
+ console.error(`Experiment error: ${error}`, experimentId);
306
+ }}
307
+ >
308
+ {/* Your variants */}
309
+ </GxExperimentWrapper>
310
+ ```
311
+
312
+ ### Programmatic Control
313
+
314
+ ```typescript
315
+ // Check if user is in a specific variant
316
+ const isVariant = (targetVariant: string) => {
317
+ return getVariant(experimentConfig) === targetVariant;
318
+ };
319
+
320
+ // Reassign variant (useful for testing)
321
+ const reassignVariant = () => {
322
+ localStorage.removeItem(`gx_experiment_${experimentId}`);
323
+ // Next page load will reassign
324
+ };
325
+
326
+ // Get experiment status
327
+ const getExperimentStatus = () => {
328
+ return {
329
+ experimentId,
330
+ variant: getVariant(experimentConfig),
331
+ isInitialized: true,
332
+ sessionId: getSessionId(),
333
+ userId: getUserId(),
334
+ };
335
+ };
336
+ ```
337
+
338
+ ## 🧪 Testing
339
+
340
+ ### Unit Tests
341
+
342
+ ```bash
343
+ npm test
344
+ ```
345
+
346
+ ### Integration Tests
347
+
348
+ ```bash
349
+ npm run test:integration
350
+ ```
351
+
352
+ ### Demo Applications
353
+
354
+ ```bash
355
+ # Start all demos
356
+ npm run demo
357
+
358
+ # React demo only
359
+ npm run demo:react
360
+
361
+ # Vue demo only
362
+ npm run demo:vue
363
+
364
+ # HTML demo
365
+ npm run demo:html
366
+ ```
367
+
368
+ ## 📊 Analytics & Tracking
369
+
370
+ ### Built-in Events
371
+
372
+ - `experiment_viewed` - When a user sees an experiment
373
+ - `variant_assigned` - When a variant is assigned to a user
374
+ - `experiment_error` - When an error occurs
375
+
376
+ ### Custom Events
377
+
378
+ ```tsx
379
+ <GxExperimentWrapper
380
+ config={experimentConfig}
381
+ onTrack={(event, data) => {
382
+ // Track custom events
383
+ if (event === 'button_clicked') {
384
+ analytics.track('Button Clicked', {
385
+ experiment: data.experimentId,
386
+ variant: data.variant,
387
+ button_text: data.customData?.buttonText,
388
+ });
389
+ }
390
+ }}
391
+ >
392
+ <div data-variant="A">
393
+ <button onClick={() => track('button_clicked', { buttonText: 'Get Started' })}>Get Started</button>
394
+ </div>
395
+ </GxExperimentWrapper>
396
+ ```
397
+
398
+ ## 🔧 Configuration
399
+
400
+ ### Environment Variables
401
+
402
+ ```bash
403
+ # Optional: Custom tracking endpoint
404
+ GX_TRACKING_ENDPOINT=https://api.yourapp.com/analytics
405
+
406
+ # Optional: Enable debug mode
407
+ GX_DEBUG=true
408
+
409
+ # Optional: Default experiment configuration
410
+ GX_DEFAULT_CONFIG=./experiments.json
411
+ ```
412
+
413
+ ### Build Configuration
414
+
415
+ The library supports multiple build targets:
416
+
417
+ - **ES Modules** (`dist/index.mjs`) - For modern bundlers
418
+ - **CommonJS** (`dist/index.js`) - For Node.js and older bundlers
419
+ - **TypeScript** (`dist/index.d.ts`) - For type definitions
420
+
421
+ ### Development Setup
422
+
423
+ ```bash
424
+ # Clone the repository
425
+ git clone https://github.com/gempages/gemx-package.git
426
+ cd gemx-package
427
+
428
+ # Install dependencies
429
+ npm install
430
+
431
+ # Build the library
432
+ npm run build
433
+
434
+ # Run tests
435
+ npm test
436
+
437
+ # Start development server
438
+ npm run demo:react
439
+ ```
440
+
441
+ ### Project Structure
442
+
443
+ ```
444
+ src/
445
+ ├── adapters/ # Framework-specific adapters
446
+ │ ├── react/ # React components
447
+ │ └── vue/ # Vue components
448
+ ├── components/ # Web components
449
+ ├── core/ # Core A/B testing logic
450
+ ├── types/ # TypeScript type definitions
451
+ ├── utils/ # Utility functions
452
+ └── tracking/ # Analytics and tracking
453
+ ```
454
+
455
+ ## 🆘 Support
456
+
457
+ - 📖 [Documentation](https://github.com/gempages/gemx-package#readme)
458
+ - 🐛 [Bug Reports](https://github.com/gempages/gemx-package/issues)
459
+ - 💬 [Discussions](https://github.com/gempages/gemx-package/discussions)
460
+ - 📧 [Email Support](mailto:support@gemx.dev)
461
+
462
+ ---
463
+
464
+ **Made with ❤️ by the GemX team**
@@ -0,0 +1,16 @@
1
+ /**
2
+ * GxExperimentWrapper - Framework-Agnostic A/B Testing Web Component
3
+ *
4
+ * This is a comprehensive Web Component that contains ALL A/B testing logic,
5
+ * making it truly framework-agnostic. It can be used in React, Vue, Angular,
6
+ * Svelte, or vanilla JavaScript without any framework-specific dependencies.
7
+ */
8
+ import type { ExperimentStatus } from '../types';
9
+ export interface IExperimentWrapper extends HTMLElement {
10
+ getCurrentVariant(): string | null;
11
+ getExperimentStatus(): ExperimentStatus;
12
+ reassignVariant(): void;
13
+ isVariant(targetVariant: string): boolean;
14
+ trackEvent(event: string, data?: Record<string, any>): void;
15
+ }
16
+ export declare function registerExperimentWebComponent(): void;
@@ -0,0 +1 @@
1
+ export * from './experiment-wrapper';
@@ -0,0 +1,12 @@
1
+ import type { ExperimentWrapperProps } from '../types';
2
+ export declare const EXPERIMENT_STORAGE_KEYS: {
3
+ PREFIX: string;
4
+ SESSION_ID: string;
5
+ USER_ID: string;
6
+ };
7
+ export declare const EXPERIMENT_ATTRIBUTES: Record<keyof Omit<ExperimentWrapperProps, 'children'>, string>;
8
+ export declare const EXPERIMENT_EVENTS: {
9
+ VARIANT_ASSIGNED: string;
10
+ TRACK: string;
11
+ ERROR: string;
12
+ };
@@ -0,0 +1,3 @@
1
+ import type { ExperimentConfig } from '../types';
2
+ export declare function getExperimentKey(experimentId: string): string;
3
+ export declare function getVariant(config: ExperimentConfig, cookieString?: string): string;
@@ -0,0 +1 @@
1
+ export * from './ab-testing';
@@ -0,0 +1,5 @@
1
+ export * from './components';
2
+ export * from './constants';
3
+ export * from './core';
4
+ export * from './types';
5
+ export * from './utils';