@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.
- package/README.md +576 -0
- package/dist/aegis-sw.js +1 -0
- package/dist/aegis.min.js +2 -0
- package/dist/aegis.min.js.map +1 -0
- package/dist/analytics-B11keZ55.mjs +1854 -0
- package/dist/analytics-B11keZ55.mjs.map +1 -0
- package/dist/cdn.d.ts +18 -0
- package/dist/cdn.d.ts.map +1 -0
- package/dist/core/analytics.d.ts +47 -0
- package/dist/core/analytics.d.ts.map +1 -0
- package/dist/core/queue.d.ts +35 -0
- package/dist/core/queue.d.ts.map +1 -0
- package/dist/core/sdk-config-poller.d.ts +59 -0
- package/dist/core/sdk-config-poller.d.ts.map +1 -0
- package/dist/core/session.d.ts +41 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/transport.d.ts +50 -0
- package/dist/core/transport.d.ts.map +1 -0
- package/dist/inapp/AegisInAppManager.d.ts +126 -0
- package/dist/inapp/AegisInAppManager.d.ts.map +1 -0
- package/dist/inapp/index.d.ts +4 -0
- package/dist/inapp/index.d.ts.map +1 -0
- package/dist/inapp/renderPreview.d.ts +25 -0
- package/dist/inapp/renderPreview.d.ts.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4296 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/react.d.ts +19 -0
- package/dist/integrations/react.d.ts.map +1 -0
- package/dist/placements/AegisPlacementManager.d.ts +88 -0
- package/dist/placements/AegisPlacementManager.d.ts.map +1 -0
- package/dist/plugins/registry.d.ts +13 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/push/AegisWebPush.d.ts +51 -0
- package/dist/push/AegisWebPush.d.ts.map +1 -0
- package/dist/push/AegisWebPush.js +203 -0
- package/dist/push/AegisWebPush.js.map +1 -0
- package/dist/react.js +70 -0
- package/dist/react.js.map +1 -0
- package/dist/snippet.min.js +1 -0
- package/dist/triggers/TriggerEngine.d.ts +114 -0
- package/dist/triggers/TriggerEngine.d.ts.map +1 -0
- package/dist/triggers/index.d.ts +3 -0
- package/dist/triggers/index.d.ts.map +1 -0
- package/dist/types/config.d.ts +73 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/events.d.ts +127 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/plugin.d.ts +21 -0
- package/dist/types/plugin.d.ts.map +1 -0
- package/dist/types/type-safe-events.d.ts +14 -0
- package/dist/types/type-safe-events.d.ts.map +1 -0
- package/dist/utils/canonical-identity.d.ts +29 -0
- package/dist/utils/canonical-identity.d.ts.map +1 -0
- package/dist/utils/consent.d.ts +40 -0
- package/dist/utils/consent.d.ts.map +1 -0
- package/dist/utils/debounce.d.ts +3 -0
- package/dist/utils/debounce.d.ts.map +1 -0
- package/dist/utils/device.d.ts +6 -0
- package/dist/utils/device.d.ts.map +1 -0
- package/dist/utils/identity.d.ts +27 -0
- package/dist/utils/identity.d.ts.map +1 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +15 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/storage.d.ts +20 -0
- package/dist/utils/storage.d.ts.map +1 -0
- package/dist/utils/url-parser.d.ts +23 -0
- package/dist/utils/url-parser.d.ts.map +1 -0
- package/dist/utils/uuid.d.ts +4 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/widgets/AegisWidgetManager.d.ts +194 -0
- package/dist/widgets/AegisWidgetManager.d.ts.map +1 -0
- package/dist/widgets/index.d.ts +3 -0
- package/dist/widgets/index.d.ts.map +1 -0
- 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
|
package/dist/aegis-sw.js
ADDED
|
@@ -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)}))})}();
|