@active-reach/web-sdk 1.0.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 (80) hide show
  1. package/README.md +576 -0
  2. package/dist/aegis-sw.js +1 -0
  3. package/dist/aegis.min.js +2 -0
  4. package/dist/aegis.min.js.map +1 -0
  5. package/dist/analytics-B11keZ55.mjs +1854 -0
  6. package/dist/analytics-B11keZ55.mjs.map +1 -0
  7. package/dist/cdn.d.ts +18 -0
  8. package/dist/cdn.d.ts.map +1 -0
  9. package/dist/core/analytics.d.ts +47 -0
  10. package/dist/core/analytics.d.ts.map +1 -0
  11. package/dist/core/queue.d.ts +35 -0
  12. package/dist/core/queue.d.ts.map +1 -0
  13. package/dist/core/sdk-config-poller.d.ts +59 -0
  14. package/dist/core/sdk-config-poller.d.ts.map +1 -0
  15. package/dist/core/session.d.ts +41 -0
  16. package/dist/core/session.d.ts.map +1 -0
  17. package/dist/core/transport.d.ts +50 -0
  18. package/dist/core/transport.d.ts.map +1 -0
  19. package/dist/inapp/AegisInAppManager.d.ts +126 -0
  20. package/dist/inapp/AegisInAppManager.d.ts.map +1 -0
  21. package/dist/inapp/index.d.ts +4 -0
  22. package/dist/inapp/index.d.ts.map +1 -0
  23. package/dist/inapp/renderPreview.d.ts +25 -0
  24. package/dist/inapp/renderPreview.d.ts.map +1 -0
  25. package/dist/index.d.ts +23 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +4296 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/integrations/react.d.ts +19 -0
  30. package/dist/integrations/react.d.ts.map +1 -0
  31. package/dist/placements/AegisPlacementManager.d.ts +88 -0
  32. package/dist/placements/AegisPlacementManager.d.ts.map +1 -0
  33. package/dist/plugins/registry.d.ts +13 -0
  34. package/dist/plugins/registry.d.ts.map +1 -0
  35. package/dist/push/AegisWebPush.d.ts +51 -0
  36. package/dist/push/AegisWebPush.d.ts.map +1 -0
  37. package/dist/push/AegisWebPush.js +203 -0
  38. package/dist/push/AegisWebPush.js.map +1 -0
  39. package/dist/react.js +70 -0
  40. package/dist/react.js.map +1 -0
  41. package/dist/snippet.min.js +1 -0
  42. package/dist/triggers/TriggerEngine.d.ts +114 -0
  43. package/dist/triggers/TriggerEngine.d.ts.map +1 -0
  44. package/dist/triggers/index.d.ts +3 -0
  45. package/dist/triggers/index.d.ts.map +1 -0
  46. package/dist/types/config.d.ts +73 -0
  47. package/dist/types/config.d.ts.map +1 -0
  48. package/dist/types/events.d.ts +127 -0
  49. package/dist/types/events.d.ts.map +1 -0
  50. package/dist/types/index.d.ts +5 -0
  51. package/dist/types/index.d.ts.map +1 -0
  52. package/dist/types/plugin.d.ts +21 -0
  53. package/dist/types/plugin.d.ts.map +1 -0
  54. package/dist/types/type-safe-events.d.ts +14 -0
  55. package/dist/types/type-safe-events.d.ts.map +1 -0
  56. package/dist/utils/canonical-identity.d.ts +29 -0
  57. package/dist/utils/canonical-identity.d.ts.map +1 -0
  58. package/dist/utils/consent.d.ts +40 -0
  59. package/dist/utils/consent.d.ts.map +1 -0
  60. package/dist/utils/debounce.d.ts +3 -0
  61. package/dist/utils/debounce.d.ts.map +1 -0
  62. package/dist/utils/device.d.ts +6 -0
  63. package/dist/utils/device.d.ts.map +1 -0
  64. package/dist/utils/identity.d.ts +27 -0
  65. package/dist/utils/identity.d.ts.map +1 -0
  66. package/dist/utils/index.d.ts +7 -0
  67. package/dist/utils/index.d.ts.map +1 -0
  68. package/dist/utils/logger.d.ts +15 -0
  69. package/dist/utils/logger.d.ts.map +1 -0
  70. package/dist/utils/storage.d.ts +20 -0
  71. package/dist/utils/storage.d.ts.map +1 -0
  72. package/dist/utils/url-parser.d.ts +23 -0
  73. package/dist/utils/url-parser.d.ts.map +1 -0
  74. package/dist/utils/uuid.d.ts +4 -0
  75. package/dist/utils/uuid.d.ts.map +1 -0
  76. package/dist/widgets/AegisWidgetManager.d.ts +194 -0
  77. package/dist/widgets/AegisWidgetManager.d.ts.map +1 -0
  78. package/dist/widgets/index.d.ts +3 -0
  79. package/dist/widgets/index.d.ts.map +1 -0
  80. package/package.json +73 -0
package/README.md ADDED
@@ -0,0 +1,576 @@
1
+ # @active-reach/web-sdk
2
+
3
+ Web SDK for **Active Reach Intelligence** — lightweight event tracking, identity resolution, in-app messaging, web push, and inline content placements.
4
+
5
+ **12KB gzipped** | **<1KB async loader** | **Zero impact on page load**
6
+
7
+ ---
8
+
9
+ ## Prerequisites
10
+
11
+ Before integrating, you need:
12
+
13
+ 1. **Write Key** — Retrieve from your Active Reach Intelligence dashboard under **Settings > Developer > API Keys**.
14
+ 2. **API Host** — Your cell endpoint URL (provided during onboarding).
15
+
16
+ > **Note:** The write key is a **publishable identifier** (like a Stripe publishable key). It is safe to include in client-side code. It can only send events — it cannot read data, modify configuration, or access other tenants. Never use your **Secret Key** in client-side code.
17
+
18
+ ---
19
+
20
+ ## Installation
21
+
22
+ ### NPM (Recommended)
23
+
24
+ ```bash
25
+ npm install @active-reach/web-sdk
26
+ ```
27
+
28
+ ### CDN (Async Loader)
29
+
30
+ Add this snippet to your `<head>` tag. The async loader queues all calls until the full SDK loads — zero blocking.
31
+
32
+ ```html
33
+ <script>
34
+ !function(){var e=window.aegis=window.aegis||[];if(!e.invoked){e.invoked=!0,e.methods=["init","track","identify","page","group","alias","reset","flush","use","debug","setCell","getCellInfo","getAnonymousId","getUserId","getSessionId","setConsent","grantConsent","denyConsent","hasConsent","getConsentPreferences","onConsentChange"],e.factory=function(t){return function(){var n=Array.prototype.slice.call(arguments);return n.unshift(t),e.push(n),e}};for(var t=0;t<e.methods.length;t++){var n=e.methods[t];e[n]=e.factory(n)}e.load=function(t,n){var o=document.createElement("script");o.type="text/javascript",o.async=!0,o.src=n&&n.cdnUrl?n.cdnUrl:"https://cdn.activereach.ai/sdk/aegis.min.js",o.onerror=function(){window.console&&console.error("Aegis SDK failed to load")};var r=document.getElementsByTagName("script")[0];r.parentNode.insertBefore(o,r),e._loadOptions={key:t,options:n}},e.SNIPPET_VERSION="1.0.0"}}();
35
+
36
+ aegis.load('YOUR_WRITE_KEY');
37
+ aegis.init('YOUR_WRITE_KEY', {
38
+ api_host: 'https://YOUR_CELL.activereach.ai'
39
+ });
40
+ </script>
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Quick Start
46
+
47
+ ### NPM / ES Modules
48
+
49
+ ```typescript
50
+ import aegis from '@active-reach/web-sdk';
51
+
52
+ await aegis.init('YOUR_WRITE_KEY', {
53
+ api_host: 'https://YOUR_CELL.activereach.ai',
54
+ auto_page_view: true,
55
+ });
56
+
57
+ // Track an event
58
+ aegis.track('Purchase Completed', {
59
+ order_id: 'ORD-123',
60
+ revenue: 99.99,
61
+ currency: 'INR',
62
+ });
63
+
64
+ // Identify a user
65
+ aegis.identify('user_123', {
66
+ email: 'user@example.com',
67
+ name: 'Priya Sharma',
68
+ plan: 'premium',
69
+ });
70
+ ```
71
+
72
+ ### React
73
+
74
+ ```tsx
75
+ import { AegisProvider, useAegis, useTrackEvent } from '@active-reach/web-sdk/react';
76
+
77
+ function App() {
78
+ return (
79
+ <AegisProvider
80
+ writeKey="YOUR_WRITE_KEY"
81
+ config={{ api_host: 'https://YOUR_CELL.activereach.ai', auto_page_view: true }}
82
+ >
83
+ <Dashboard />
84
+ </AegisProvider>
85
+ );
86
+ }
87
+
88
+ function Dashboard() {
89
+ const { isReady } = useAegis();
90
+ const trackEvent = useTrackEvent();
91
+
92
+ return (
93
+ <button onClick={() => trackEvent('Button Clicked', { button: 'CTA' })}>
94
+ Track Event
95
+ </button>
96
+ );
97
+ }
98
+ ```
99
+
100
+ ### Next.js
101
+
102
+ ```tsx
103
+ // app/providers.tsx
104
+ 'use client';
105
+
106
+ import { AegisProvider } from '@active-reach/web-sdk/react';
107
+
108
+ export function Providers({ children }: { children: React.ReactNode }) {
109
+ return (
110
+ <AegisProvider
111
+ writeKey={process.env.NEXT_PUBLIC_AEGIS_WRITE_KEY!}
112
+ config={{ api_host: process.env.NEXT_PUBLIC_AEGIS_API_HOST! }}
113
+ >
114
+ {children}
115
+ </AegisProvider>
116
+ );
117
+ }
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Configuration
123
+
124
+ ```typescript
125
+ await aegis.init('YOUR_WRITE_KEY', {
126
+ // Required
127
+ api_host: string;
128
+
129
+ // Batching & Performance
130
+ batch_size?: number; // default: 10
131
+ batch_interval?: number; // default: 1000ms
132
+
133
+ // Data Capture
134
+ capture_utm?: boolean; // default: true
135
+ capture_referrer?: boolean; // default: true
136
+ auto_page_view?: boolean; // default: false
137
+
138
+ // Session
139
+ session_timeout?: number; // default: 1800000 (30 min)
140
+
141
+ // Privacy & Consent
142
+ respect_dnt?: boolean; // default: true
143
+ enable_consent_mode?: boolean; // default: false
144
+ wait_for_consent?: boolean; // default: false
145
+ default_consent?: {
146
+ analytics?: boolean; // default: false
147
+ marketing?: boolean; // default: false
148
+ functional?: boolean; // default: true
149
+ };
150
+ integrate_onetrust?: boolean;
151
+ integrate_cookiebot?: boolean;
152
+ integrate_google_consent_mode?: boolean;
153
+
154
+ // Cookie
155
+ cross_domain_tracking?: boolean; // default: false
156
+ cookie_domain?: string;
157
+ secure_cookie?: boolean; // default: true
158
+
159
+ // Offline & Retry
160
+ enable_offline_mode?: boolean; // default: true
161
+ max_offline_events?: number; // default: 100
162
+ retry_failed_requests?: boolean; // default: true
163
+ max_retries?: number; // default: 3
164
+
165
+ // Regional Cell Selection
166
+ cell_endpoints?: CellEndpoint[];
167
+ preferred_region?: string;
168
+ auto_region_detection?: boolean; // default: true
169
+
170
+ // Debug
171
+ debug?: boolean; // default: false
172
+ });
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Core API
178
+
179
+ ### `aegis.track(eventName, properties?)`
180
+
181
+ Track a custom event.
182
+
183
+ ```typescript
184
+ aegis.track('Product Viewed', {
185
+ product_id: 'SKU-12345',
186
+ product_name: 'Leather Jacket',
187
+ price: 199.99,
188
+ category: 'Outerwear',
189
+ });
190
+ ```
191
+
192
+ ### `aegis.identify(userId, traits?)`
193
+
194
+ Identify a user and associate traits.
195
+
196
+ ```typescript
197
+ aegis.identify('user_123', {
198
+ email: 'user@example.com',
199
+ name: 'John Doe',
200
+ plan: 'premium',
201
+ });
202
+ ```
203
+
204
+ ### `aegis.page(name?, properties?)`
205
+
206
+ Track a page view.
207
+
208
+ ```typescript
209
+ aegis.page('Product Page', { product_id: 'SKU-12345' });
210
+ ```
211
+
212
+ ### `aegis.group(groupId, traits?)`
213
+
214
+ Associate a user with a group (company, organization).
215
+
216
+ ```typescript
217
+ aegis.group('company_789', {
218
+ name: 'Acme Corp',
219
+ industry: 'Technology',
220
+ employees: 500,
221
+ });
222
+ ```
223
+
224
+ ### `aegis.alias(newUserId)`
225
+
226
+ Merge two user identities.
227
+
228
+ ```typescript
229
+ aegis.alias('permanent_user_id');
230
+ ```
231
+
232
+ ### `aegis.reset()`
233
+
234
+ Clear user identity on logout. Generates a new anonymous ID.
235
+
236
+ ```typescript
237
+ aegis.reset();
238
+ ```
239
+
240
+ ### `aegis.flush()`
241
+
242
+ Force-send all queued events immediately.
243
+
244
+ ```typescript
245
+ await aegis.flush();
246
+ ```
247
+
248
+ ---
249
+
250
+ ## React Hooks
251
+
252
+ Import from `@active-reach/web-sdk/react`:
253
+
254
+ | Hook | Returns | Description |
255
+ |------|---------|-------------|
256
+ | `useAegis()` | `{ aegis, isReady }` | Access SDK instance and readiness state |
257
+ | `useTrackEvent()` | `(name, props?) => void` | Memoized event tracking callback |
258
+ | `usePageView(name?, props?, deps?)` | — | Track page views on mount/dependency change |
259
+ | `useIdentifyUser()` | `(userId, traits?) => void` | Memoized identify callback |
260
+
261
+ ---
262
+
263
+ ## Consent Management
264
+
265
+ Built-in support for GDPR/CCPA compliance.
266
+
267
+ ```typescript
268
+ // Set preferences
269
+ aegis.setConsent({ analytics: true, marketing: false, functional: true });
270
+
271
+ // Grant / deny
272
+ aegis.grantConsent(); // all categories
273
+ aegis.grantConsent('analytics'); // specific category
274
+
275
+ aegis.denyConsent();
276
+ aegis.denyConsent('marketing');
277
+
278
+ // Query
279
+ aegis.hasConsent('analytics'); // boolean
280
+ aegis.getConsentPreferences(); // full object
281
+
282
+ // Listen for changes
283
+ const unsubscribe = aegis.onConsentChange((prefs) => {
284
+ console.log('Consent updated:', prefs);
285
+ });
286
+ ```
287
+
288
+ ### Third-Party Integrations
289
+
290
+ ```typescript
291
+ // OneTrust
292
+ aegis.init('KEY', { enable_consent_mode: true, integrate_onetrust: true });
293
+
294
+ // Cookiebot
295
+ aegis.init('KEY', { enable_consent_mode: true, integrate_cookiebot: true });
296
+
297
+ // Google Consent Mode v2
298
+ aegis.init('KEY', { enable_consent_mode: true, integrate_google_consent_mode: true });
299
+ ```
300
+
301
+ ---
302
+
303
+ ## Web Push Notifications
304
+
305
+ Import from `@active-reach/web-sdk/push`:
306
+
307
+ ```typescript
308
+ import { AegisWebPush } from '@active-reach/web-sdk/push';
309
+
310
+ const push = new AegisWebPush({
311
+ writeKey: 'YOUR_WRITE_KEY',
312
+ apiHost: 'https://YOUR_CELL.activereach.ai',
313
+ vapidPublicKey: 'YOUR_VAPID_PUBLIC_KEY',
314
+ contactId: 'user_123',
315
+ organizationId: 'org_456',
316
+ serviceWorkerPath: '/aegis-sw.js',
317
+ });
318
+
319
+ await push.initialize();
320
+ ```
321
+
322
+ Copy `dist/aegis-sw.js` to your `public/` directory so the service worker is served at the root.
323
+
324
+ ---
325
+
326
+ ## In-App Messaging
327
+
328
+ ```typescript
329
+ import { AegisInAppManager } from '@active-reach/web-sdk';
330
+
331
+ const inApp = new AegisInAppManager({
332
+ writeKey: 'YOUR_WRITE_KEY',
333
+ apiHost: 'https://YOUR_CELL.activereach.ai',
334
+ contactId: 'user_123',
335
+ organizationId: 'org_456',
336
+ });
337
+
338
+ await inApp.initialize();
339
+ ```
340
+
341
+ Campaign display rules (modal, banner, tooltip, slide-in) are configured server-side. The SDK evaluates client-side triggers (scroll depth, time on page, exit intent, inactivity) and renders campaigns automatically.
342
+
343
+ ---
344
+
345
+ ## Inline Content Placements
346
+
347
+ ```typescript
348
+ import { AegisPlacementManager } from '@active-reach/web-sdk';
349
+
350
+ const placements = new AegisPlacementManager({
351
+ writeKey: 'YOUR_WRITE_KEY',
352
+ apiHost: 'https://YOUR_CELL.activereach.ai',
353
+ contactId: 'user_123',
354
+ organizationId: 'org_456',
355
+ enableSSE: true,
356
+ });
357
+
358
+ await placements.initialize();
359
+
360
+ // Register a slot in your page
361
+ placements.registerSlot({
362
+ placementId: 'homepage_hero',
363
+ containerId: 'aegis-hero-slot',
364
+ fallbackContent: '<p>Loading...</p>',
365
+ });
366
+ ```
367
+
368
+ Placements support banner, card, carousel, video, and HTML content types. Content is managed server-side and delivered via SSE for real-time updates.
369
+
370
+ > **HTML Placements:** For full HTML content rendering, add [DOMPurify](https://github.com/cure53/DOMPurify) to your page. Without it, HTML placements fall back to text-only rendering.
371
+ >
372
+ > ```html
373
+ > <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.2.4/purify.min.js"></script>
374
+ > ```
375
+
376
+ ---
377
+
378
+ ## Widgets (Exit Intent, Surveys, Gamification)
379
+
380
+ ```typescript
381
+ import { AegisWidgetManager, TriggerEngine } from '@active-reach/web-sdk';
382
+
383
+ const triggerEngine = new TriggerEngine();
384
+ const widgets = new AegisWidgetManager({
385
+ writeKey: 'YOUR_WRITE_KEY',
386
+ apiHost: 'https://YOUR_CELL.activereach.ai',
387
+ contactId: 'user_123',
388
+ organizationId: 'org_456',
389
+ triggerEngine,
390
+ enablePrefetch: true,
391
+ });
392
+
393
+ await widgets.initialize();
394
+ ```
395
+
396
+ ### Cart Recovery (Platform Auto-Detection)
397
+
398
+ The SDK auto-detects cart data from:
399
+
400
+ | Platform | Detection Method | Setup |
401
+ |----------|-----------------|-------|
402
+ | **Shopify** | `window.Shopify.checkout` / DOM `#cart-json` | None |
403
+ | **WooCommerce** | `window.aegis_cart` (injected by plugin) | Install WP plugin |
404
+ | **Magento 2** | `localStorage['mage-cache-storage']` | None |
405
+ | **Custom / Mobile** | Manual via `setCartData()` | Required |
406
+
407
+ ```typescript
408
+ // For custom platforms only
409
+ widgets.setCartData({
410
+ cart_id: 'cart_123',
411
+ cart_total: 149.99,
412
+ cart_currency: 'INR',
413
+ cart_items: [
414
+ { product_id: 'prod_456', product_name: 'Premium Widget', quantity: 2, price: 74.99 }
415
+ ],
416
+ });
417
+ ```
418
+
419
+ ---
420
+
421
+ ## Plugin System
422
+
423
+ Extend the SDK with custom plugins:
424
+
425
+ ```typescript
426
+ import type { Plugin } from '@active-reach/web-sdk';
427
+
428
+ const myPlugin: Plugin = {
429
+ name: 'my-plugin',
430
+ version: '1.0.0',
431
+
432
+ async init(config) { /* called on SDK init */ },
433
+
434
+ async beforeEventCapture(event) {
435
+ // Modify or enrich events before capture
436
+ event.properties = { ...event.properties, enriched: true };
437
+ return event;
438
+ },
439
+
440
+ async afterEventCapture(event) {
441
+ // Post-capture logic (external forwarding, logging, etc.)
442
+ },
443
+ };
444
+
445
+ aegis.use(myPlugin);
446
+ ```
447
+
448
+ ---
449
+
450
+ ## TypeScript Support
451
+
452
+ Full type definitions included. Extend for type-safe event tracking:
453
+
454
+ ```typescript
455
+ // types/aegis.d.ts
456
+ import '@active-reach/web-sdk';
457
+
458
+ declare module '@active-reach/web-sdk' {
459
+ interface TrackEventProperties {
460
+ 'Purchase Completed': {
461
+ order_id: string;
462
+ revenue: number;
463
+ currency: string;
464
+ };
465
+ 'Product Viewed': {
466
+ product_id: string;
467
+ product_name: string;
468
+ price: number;
469
+ };
470
+ }
471
+ }
472
+ ```
473
+
474
+ ---
475
+
476
+ ## Cookies & Storage
477
+
478
+ | Name | Type | Purpose | Duration |
479
+ |------|------|---------|----------|
480
+ | `aegis_anon_id` | Cookie | Anonymous user identifier | 365 days |
481
+ | `aegis_user_id` | Cookie | Identified user ID | 365 days |
482
+ | `aegis_session_id` | Cookie | Current session ID | Session |
483
+ | `aegis_session_time` | Cookie | Last activity timestamp | Session |
484
+ | `aegis_consent` | Cookie | Consent preferences | 365 days |
485
+ | `aegis_offline_queue` | localStorage | Offline event queue | Persistent |
486
+ | `aegis_active_cell` | localStorage | Active regional cell | 7 days |
487
+
488
+ All cookies: `SameSite=Lax`, `Secure` (HTTPS only), domain-scoped (optional).
489
+
490
+ ---
491
+
492
+ ## Content Security Policy (CSP)
493
+
494
+ If your site uses a Content Security Policy, add these directives:
495
+
496
+ ```
497
+ script-src: 'self' https://cdn.activereach.ai;
498
+ connect-src: 'self' https://*.activereach.ai;
499
+ style-src: 'self' 'unsafe-inline';
500
+ img-src: 'self' https://*.activereach.ai data:;
501
+ ```
502
+
503
+ If using DOMPurify via CDN, also add:
504
+
505
+ ```
506
+ script-src: https://cdnjs.cloudflare.com;
507
+ ```
508
+
509
+ **Common error when CSP is missing:** `Refused to connect to 'https://...activereach.ai'` — add the domain to `connect-src`.
510
+
511
+ ---
512
+
513
+ ## Security
514
+
515
+ - **Write Key**: Publishable client-side identifier. Cannot read data or modify server state. Safe to embed in source code.
516
+ - **HTML Sanitization**: Uses [DOMPurify](https://github.com/cure53/DOMPurify) when available with a strict allowlist. Falls back to text-only rendering.
517
+ - **URL Validation**: All URLs validated — `javascript:` and `data:` protocols blocked.
518
+ - **Consent**: Events are dropped (not queued) when consent is denied and `wait_for_consent` is enabled.
519
+ - **Transport**: All API calls use HTTPS with bearer token authentication.
520
+
521
+ ### What NOT to track
522
+
523
+ Never pass sensitive data as event properties:
524
+
525
+ ```typescript
526
+ // Never do this
527
+ aegis.track('Login', { password: '...' });
528
+ aegis.identify('user_123', { ssn: '...', credit_card: '...' });
529
+ ```
530
+
531
+ The SDK does not filter or redact properties. You are responsible for ensuring no PII beyond what you intend to collect is included in event payloads.
532
+
533
+ ---
534
+
535
+ ## Debugging
536
+
537
+ ```typescript
538
+ aegis.debug(true);
539
+
540
+ // Or via init
541
+ aegis.init('KEY', { debug: true });
542
+ ```
543
+
544
+ Console output:
545
+
546
+ ```
547
+ [Aegis] Initializing SDK...
548
+ [Aegis] Event queued: track { button_name: 'Sign Up' }
549
+ [Aegis] Flushing 5 events
550
+ [Aegis] Batch sent successfully
551
+ ```
552
+
553
+ ---
554
+
555
+ ## Subpath Exports
556
+
557
+ | Import Path | Description |
558
+ |-------------|-------------|
559
+ | `@active-reach/web-sdk` | Core SDK (track, identify, page, group, alias) |
560
+ | `@active-reach/web-sdk/react` | React Provider + hooks |
561
+ | `@active-reach/web-sdk/push` | Web Push notification manager |
562
+ | `@active-reach/web-sdk/cdn` | IIFE bundle for `<script>` tag (window.aegis) |
563
+ | `@active-reach/web-sdk/snippet` | Minified async loader snippet |
564
+ | `@active-reach/web-sdk/service-worker` | Push notification service worker |
565
+
566
+ ---
567
+
568
+ ## Browser Support
569
+
570
+ Chrome 80+, Firefox 78+, Safari 14+, Edge 80+.
571
+
572
+ ---
573
+
574
+ ## License
575
+
576
+ MIT
@@ -0,0 +1 @@
1
+ !function(){"use strict";function i(i){self.clients.matchAll({type:"window",includeUncontrolled:!0}).then(t=>{for(const n of t)n.postMessage(i)}).catch(()=>{})}self.addEventListener("push",t=>{if(!t.data)return;let n;try{n=t.data.json()}catch{n={title:t.data.text()||"Notification"}}const a=n.title||"Notification",e={body:n.body||"",icon:n.icon||void 0,badge:n.badge||void 0,image:n.image||void 0,tag:n.tag||n.campaign_id||void 0,data:{campaign_id:n.campaign_id,action_url:n.action_url||n.url,timestamp:Date.now()},actions:Array.isArray(n.actions)?n.actions.slice(0,2):[],requireInteraction:n.require_interaction??!1};t.waitUntil(self.registration.showNotification(a,e).then(()=>{i({type:"push.delivered",campaign_id:n.campaign_id})}))}),self.addEventListener("notificationclick",t=>{t.notification.close();const n=t.notification.data||{},a=n.action_url||"/";let e=a;if(t.action&&Array.isArray(t.notification.actions)){if(t.notification.actions.find(i=>i.action===t.action)){const i=n.action_urls||{};e=i[t.action]||a}}i({type:"push.clicked",campaign_id:n.campaign_id,action_url:e,action:t.action||"default"}),t.waitUntil(self.clients.matchAll({type:"window",includeUncontrolled:!0}).then(i=>{for(const t of i)if(new URL(t.url).origin===self.location.origin)return t.focus(),void t.navigate(e);return self.clients.openWindow(e)}))}),self.addEventListener("notificationclose",t=>{i({type:"push.dismissed",campaign_id:(t.notification.data||{}).campaign_id})}),self.addEventListener("pushsubscriptionchange",t=>{var n,a;t.waitUntil(self.registration.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:(null==(a=null==(n=t.oldSubscription)?void 0:n.options)?void 0:a.applicationServerKey)||void 0}).then(t=>{i({type:"push.resubscribed",subscription:t.toJSON()})}).catch(i=>{console.error("[aegis-sw] Failed to resubscribe:",i)}))})}();