@active-reach/web-sdk
@active-reach/web-sdk
Web SDK for Active Reach Intelligence — lightweight event tracking, identity resolution, in-app messaging (overlays, embedded cards, interactive widgets), and web push.
12KB gzipped | <1KB async loader | Zero impact on page load
Prerequisites
Before integrating, you need:
- Write Key — Retrieve from your Active Reach Intelligence dashboard under Settings > Developer > API Keys.
- API Host — Your cell endpoint URL (provided during onboarding).
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.
Installation
NPM (Recommended)
npm install @active-reach/web-sdk
CDN (Async Loader)
Add this snippet to your <head> tag. The async loader queues all calls until the full SDK loads — zero blocking.
<script>
!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"}}();
aegis.load('YOUR_WRITE_KEY');
aegis.init('YOUR_WRITE_KEY', {
api_host: 'https://YOUR_CELL.activereach.ai'
});
</script>
Quick Start
NPM / ES Modules
import aegis from '@active-reach/web-sdk';
await aegis.init('YOUR_WRITE_KEY', {
api_host: 'https://YOUR_CELL.activereach.ai',
auto_page_view: true,
});
// Track an event
aegis.track('Purchase Completed', {
order_id: 'ORD-123',
revenue: 99.99,
currency: 'INR',
});
// Identify a user
aegis.identify('user_123', {
email: 'user@example.com',
name: 'Priya Sharma',
plan: 'premium',
});
React
import { AegisProvider, useAegis, useTrackEvent } from '@active-reach/web-sdk/react';
function App() {
return (
<AegisProvider
writeKey="YOUR_WRITE_KEY"
config={{ api_host: 'https://YOUR_CELL.activereach.ai', auto_page_view: true }}
>
<Dashboard />
</AegisProvider>
);
}
function Dashboard() {
const { isReady } = useAegis();
const trackEvent = useTrackEvent();
return (
<button onClick={() => trackEvent('Button Clicked', { button: 'CTA' })}>
Track Event
</button>
);
}
Next.js
// app/providers.tsx
'use client';
import { AegisProvider } from '@active-reach/web-sdk/react';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<AegisProvider
writeKey={process.env.NEXT_PUBLIC_AEGIS_WRITE_KEY!}
config={{ api_host: process.env.NEXT_PUBLIC_AEGIS_API_HOST! }}
>
{children}
</AegisProvider>
);
}
Configuration
await aegis.init('YOUR_WRITE_KEY', {
// Required
api_host: string;
// Batching & Performance
batch_size?: number; // default: 10
batch_interval?: number; // default: 1000ms
// Data Capture
capture_utm?: boolean; // default: true
capture_referrer?: boolean; // default: true
auto_page_view?: boolean; // default: false
// Session
session_timeout?: number; // default: 1800000 (30 min)
// Privacy & Consent
respect_dnt?: boolean; // default: true
enable_consent_mode?: boolean; // default: false
wait_for_consent?: boolean; // default: false
default_consent?: {
analytics?: boolean; // default: false
marketing?: boolean; // default: false
functional?: boolean; // default: true
};
integrate_onetrust?: boolean;
integrate_cookiebot?: boolean;
integrate_google_consent_mode?: boolean;
// Cookie
cross_domain_tracking?: boolean; // default: false
cookie_domain?: string;
secure_cookie?: boolean; // default: true
// Offline & Retry
enable_offline_mode?: boolean; // default: true
max_offline_events?: number; // default: 100
retry_failed_requests?: boolean; // default: true
max_retries?: number; // default: 3
// Regional Cell Selection
cell_endpoints?: CellEndpoint[];
preferred_region?: string;
auto_region_detection?: boolean; // default: true
// Debug
debug?: boolean; // default: false
});
Core API
aegis.track(eventName, properties?)
Track a custom event.
aegis.track('Product Viewed', {
product_id: 'SKU-12345',
product_name: 'Leather Jacket',
price: 199.99,
category: 'Outerwear',
});
aegis.identify(userId, traits?)
Identify a user and associate traits.
aegis.identify('user_123', {
email: 'user@example.com',
name: 'John Doe',
plan: 'premium',
});
aegis.page(name?, properties?)
Track a page view.
aegis.page('Product Page', { product_id: 'SKU-12345' });
aegis.group(groupId, traits?)
Associate a user with a group (company, organization).
aegis.group('company_789', {
name: 'Acme Corp',
industry: 'Technology',
employees: 500,
});
aegis.alias(newUserId)
Merge two user identities.
aegis.alias('permanent_user_id');
aegis.reset()
Clear user identity on logout. Generates a new anonymous ID.
aegis.reset();
aegis.flush()
Force-send all queued events immediately.
await aegis.flush();
E-Commerce Tracking
Built-in helpers for standardized e-commerce events via aegis.ecommerce:
import aegis from '@active-reach/web-sdk';
// Product discovery
aegis.ecommerce.productViewed({
product_id: 'SKU-123',
name: 'Leather Jacket',
price: 4999,
currency: 'INR',
category: 'Outerwear',
brand: 'Acme',
variant_id: 'black_xl',
variant_label: 'Black XL',
});
aegis.ecommerce.productListViewed({
list_name: 'New Arrivals',
category: 'Outerwear',
products: [{ product_id: 'SKU-123', name: 'Leather Jacket', price: 4999 }],
});
aegis.ecommerce.searchPerformed({ query: 'leather jacket', results_count: 12 });
// Cart
aegis.ecommerce.addToCart({
product_id: 'SKU-123',
name: 'Leather Jacket',
price: 4999,
quantity: 1,
});
aegis.ecommerce.removeFromCart({ product_id: 'SKU-123', name: 'Leather Jacket', price: 4999 });
aegis.ecommerce.cartViewed({
cart_id: 'cart_456',
value: 4999,
products: [{ product_id: 'SKU-123', name: 'Leather Jacket', price: 4999, quantity: 1 }],
});
// Checkout
aegis.ecommerce.checkoutStarted({
value: 4999,
products: [{ product_id: 'SKU-123', name: 'Leather Jacket', price: 4999, quantity: 1 }],
coupon: 'WELCOME10',
shipping: 99,
tax: 450,
});
aegis.ecommerce.checkoutStep(2, { payment_method: 'UPI' });
// Order
aegis.ecommerce.orderCompleted({
order_id: 'ORD-789',
value: 5548,
revenue: 4999,
shipping: 99,
tax: 450,
payment_method: 'UPI',
products: [{ product_id: 'SKU-123', name: 'Leather Jacket', price: 4999, quantity: 1 }],
});
aegis.ecommerce.orderRefunded('ORD-789', 4999);
// Coupons
aegis.ecommerce.couponApplied({ coupon_code: 'WELCOME10', discount_value: 500, discount_type: 'fixed' });
aegis.ecommerce.couponRemoved({ coupon_code: 'WELCOME10' });
// Wishlist
aegis.ecommerce.wishlistItemAdded({
product: { product_id: 'SKU-123', name: 'Leather Jacket', price: 4999 },
});
// Promotions
aegis.ecommerce.promotionViewed({ name: 'Summer Sale', promotion_id: 'promo_1', creative: 'banner_hero' });
aegis.ecommerce.promotionClicked({ name: 'Summer Sale', promotion_id: 'promo_1' });
All E-Commerce Methods
| Method | Event Name | Description |
|---|---|---|
productViewed(product) |
product_viewed |
User views a product page |
productListViewed(list) |
product_list_viewed |
User views a category/collection |
searchPerformed(search) |
search_performed |
User searches the catalog |
addToCart(product) |
cart_item_added |
Item added to cart |
removeFromCart(product) |
cart_item_removed |
Item removed from cart |
cartViewed(cart) |
cart_viewed |
User views their cart |
checkoutStarted(checkout) |
checkout_started |
Checkout flow begins |
checkoutStep(step, options?) |
checkout_step |
Checkout step completed |
orderCompleted(order) |
order_completed |
Purchase completed |
orderRefunded(orderId, value?, products?) |
order_refunded |
Order refunded |
couponApplied(coupon) |
coupon_applied |
Coupon/discount applied |
couponRemoved(coupon) |
coupon_removed |
Coupon removed |
wishlistItemAdded(wishlist) |
wishlist_item_added |
Item added to wishlist |
promotionViewed(promo) |
promotion_viewed |
Promotion impression |
promotionClicked(promo) |
promotion_clicked |
Promotion clicked |
React Hooks
Import from @active-reach/web-sdk/react:
| Hook | Returns | Description |
|---|---|---|
useAegis() |
{ aegis, isReady } |
Access SDK instance and readiness state |
useTrackEvent() |
(name, props?) => void |
Memoized event tracking callback |
usePageView(name?, props?, deps?) |
— | Track page views on mount/dependency change |
useIdentifyUser() |
(userId, traits?) => void |
Memoized identify callback |
Consent Management
Built-in support for GDPR/CCPA compliance.
// Set preferences
aegis.setConsent({ analytics: true, marketing: false, functional: true });
// Grant / deny
aegis.grantConsent(); // all categories
aegis.grantConsent('analytics'); // specific category
aegis.denyConsent();
aegis.denyConsent('marketing');
// Query
aegis.hasConsent('analytics'); // boolean
aegis.getConsentPreferences(); // full object
// Listen for changes
const unsubscribe = aegis.onConsentChange((prefs) => {
console.log('Consent updated:', prefs);
});
Third-Party Integrations
// OneTrust
aegis.init('KEY', { enable_consent_mode: true, integrate_onetrust: true });
// Cookiebot
aegis.init('KEY', { enable_consent_mode: true, integrate_cookiebot: true });
// Google Consent Mode v2
aegis.init('KEY', { enable_consent_mode: true, integrate_google_consent_mode: true });
Web Push Notifications
Import from @active-reach/web-sdk/push:
import { AegisWebPush } from '@active-reach/web-sdk/push';
const push = new AegisWebPush({
writeKey: 'YOUR_WRITE_KEY',
apiHost: 'https://YOUR_CELL.activereach.ai',
vapidPublicKey: 'YOUR_VAPID_PUBLIC_KEY',
contactId: 'user_123',
organizationId: 'org_456',
serviceWorkerPath: '/aegis-sw.js',
});
await push.initialize();
Copy dist/aegis-sw.js to your public/ directory so the service worker is served at the root.
In-App Messaging & Widgets
Every in-app format — modals, banners, tooltips, full-screen takeovers, bottom sheets, and interactive widgets (spin-the-wheel, scratch cards, NPS/CSAT surveys, quizzes, countdown offers, star ratings, polls, multi-step forms) — is delivered through a single entry point: AegisMessageRuntime.
import { AegisMessageRuntime } from '@active-reach/web-sdk';
const runtime = new AegisMessageRuntime({
writeKey: 'YOUR_WRITE_KEY',
apiHost: 'https://YOUR_CELL.activereach.ai',
contactId: 'user_123', // optional — set once the visitor is known
organizationId: 'org_456',
propertyId: 'prop_789', // the SDK install (website/app) this page is
});
await runtime.initialize();
Migrating from an older version?
AegisInAppManager,AegisWidgetManager, andAegisPlacementManagerare no longer part of the public API —AegisMessageRuntimeis the one supported entry point and renders all formats. The standalone "placement" system has been removed; inline content is now delivered as embedded cards (see below).
Campaign content, audience, schedule, and frequency caps are configured server-side in the dashboard (In-App Personalization). The SDK evaluates client-side triggers (scroll depth, time on page, exit intent, inactivity, custom events) and renders the matching campaign automatically.
Drive triggers & identity from your app
runtime.track('added_to_cart'); // fire event-based display triggers
runtime.notifyConversion('purchase'); // suppress a campaign after it converts
await runtime.updateContactId('contact_42'); // re-evaluate once the visitor signs in
Placement — how a campaign reaches the customer
Each campaign picks one or more delivery modes in the dashboard's Placement tab. They are not mutually exclusive:
| Delivery mode | What it is | What you do on your site |
|---|---|---|
| Pop up (overlay) | A modal / banner / etc. the SDK renders over the page at runtime | Nothing — runtime.initialize() shows it when the trigger matches |
| Embedded card | The campaign renders inline, inside a slot you place on the page | Add an empty <div data-aegis-slot="…"> where you want it |
| Standalone page | The campaign gets its own tokenized URL (great for SMS / email / QR) | Link to the URL shown in the dashboard |
Embedded cards (inline placement)
Drop an empty element wherever you want the card to appear. Its data-aegis-slot value must equal the campaign's category (widget_category in the dashboard). On load, the SDK fills the first eligible campaign for that category:
<!-- Renders the active "promo" campaign here, inline in your page -->
<div data-aegis-slot="promo"></div>
No per-slot script and no manual registration — runtime.initialize() scans for every [data-aegis-slot] element and fills it. It re-scans on each SSE/poll refresh and skips slots it has already filled.
Cart state — one store, fed the CEP-standard way
Every cart-reactive surface — the free-delivery progress card, the standalone progress bar, cart-value targeting rules, and cart-recovery widgets — reads ONE cart store. You feed it the same way you'd feed WebEngage/CleverTap: by firing the ecommerce events you already fire. The SDK derives the live cart from them; no separate cart call.
// 1) Wire the ecommerce tracker into the cart store, once at boot:
runtime.bindEcommerce(aegis.ecommerce);
// 2) Fire ecommerce events as the shopper shops — the cart is derived from these:
aegis.ecommerce.addToCart({ product_id: 'p1', name: 'Cap', price: 499, quantity: 1 });
aegis.ecommerce.cartViewed({ value: 998, currency: 'INR', products: [/* … */] }); // authoritative snapshot
Platform installs need no event wiring — the plugin does it for you. Carts are detected and fed into the same store automatically:
| Platform | Detection method | Setup |
|---|---|---|
| Shopify | /cart.js poll + cart:updated (plugin) |
Install the Shopify app |
| WooCommerce | aegis_cart + WC Store API on cart events (plugin) |
Install the WP plugin |
| Magento 2 | localStorage['mage-cache-storage'] |
Install the extension |
| Custom / headless / mobile | Fire aegis.ecommerce.* (above) |
runtime.bindEcommerce(...) |
Escape hatch — a headless host that doesn't emit ecommerce events can push the cart directly; this writes the same one store:
runtime.setCartState({ total: 149.99, itemCount: 2, currency: 'INR' });
Plugin System
Extend the SDK with custom plugins:
import type { Plugin } from '@active-reach/web-sdk';
const myPlugin: Plugin = {
name: 'my-plugin',
version: '1.0.0',
async init(config) { /* called on SDK init */ },
async beforeEventCapture(event) {
// Modify or enrich events before capture
event.properties = { ...event.properties, enriched: true };
return event;
},
async afterEventCapture(event) {
// Post-capture logic (external forwarding, logging, etc.)
},
};
aegis.use(myPlugin);
TypeScript Support
Full type definitions included. Extend for type-safe event tracking:
// types/aegis.d.ts
import '@active-reach/web-sdk';
declare module '@active-reach/web-sdk' {
interface TrackEventProperties {
'Purchase Completed': {
order_id: string;
revenue: number;
currency: string;
};
'Product Viewed': {
product_id: string;
product_name: string;
price: number;
};
}
}
Cookies & Storage
| Name | Type | Purpose | Duration |
|---|---|---|---|
aegis_anon_id |
Cookie | Anonymous user identifier | 365 days |
aegis_user_id |
Cookie | Identified user ID | 365 days |
aegis_session_id |
Cookie | Current session ID | Session |
aegis_session_time |
Cookie | Last activity timestamp | Session |
aegis_consent |
Cookie | Consent preferences | 365 days |
aegis_offline_queue |
localStorage | Offline event queue | Persistent |
aegis_active_cell |
localStorage | Active regional cell | 7 days |
All cookies: SameSite=Lax, Secure (HTTPS only), domain-scoped (optional).
Content Security Policy (CSP)
If your site uses a Content Security Policy, add these directives:
script-src: 'self' https://cdn.activereach.ai;
connect-src: 'self' https://*.activereach.ai;
style-src: 'self' 'unsafe-inline';
img-src: 'self' https://*.activereach.ai data:;
If using DOMPurify via CDN, also add:
script-src: https://cdnjs.cloudflare.com;
Common error when CSP is missing: Refused to connect to 'https://...activereach.ai' — add the domain to connect-src.
Security
- Write Key: Publishable client-side identifier. Cannot read data or modify server state. Safe to embed in source code.
- HTML Sanitization: Uses DOMPurify when available with a strict allowlist. Falls back to text-only rendering.
- URL Validation: All URLs validated —
javascript:anddata:protocols blocked. - Consent: Events are dropped (not queued) when consent is denied and
wait_for_consentis enabled. - Transport: All API calls use HTTPS with bearer token authentication.
What NOT to track
Never pass sensitive data as event properties:
// Never do this
aegis.track('Login', { password: '...' });
aegis.identify('user_123', { ssn: '...', credit_card: '...' });
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.
Debugging
aegis.debug(true);
// Or via init
aegis.init('KEY', { debug: true });
Console output:
[Aegis] Initializing SDK...
[Aegis] Event queued: track { button_name: 'Sign Up' }
[Aegis] Flushing 5 events
[Aegis] Batch sent successfully
Subpath Exports
| Import Path | Description |
|---|---|
@active-reach/web-sdk |
Core SDK (track, identify, page, group, alias) |
@active-reach/web-sdk/react |
React Provider + hooks |
@active-reach/web-sdk/push |
Web Push notification manager |
@active-reach/web-sdk/cdn |
IIFE bundle for <script> tag (window.aegis) |
@active-reach/web-sdk/snippet |
Minified async loader snippet |
@active-reach/web-sdk/service-worker |
Push notification service worker |
Browser Support
Chrome 80+, Firefox 78+, Safari 14+, Edge 80+.
License
MIT