JavaScript SDK

Lightweight SDK for web and Node.js. Auto-tracks page views, identifies users, and tracks custom events.

Installation

NPM / Yarn

npm install @retenshun/js
# or
yarn add @retenshun/js

CDN

<script src="https://cdn.retenshun.com/sdk/v1.js"></script>

Initialization

import { Retenshun } from '@retenshun/js'

Retenshun.init({
  projectId: 'YOUR_PROJECT_ID',
  apiKey: 'pk_live_YOUR_PUBLIC_KEY',

  // Optional
  apiUrl: 'https://your-domain.com',   // Custom API base URL
  debug: false,                         // Enable console logging
  autoTrack: {
    pageViews: true,                    // Auto-track page views
    sessions: true,                     // Auto-track session start/end
  },
})

Call init() once when your app loads. The SDK is a singleton — calling init again overwrites the previous config.

Identify Users

Call identify() when a user signs up or logs in. This links all subsequent events to that user.

Retenshun.identify('user_123', {
  email: 'john@example.com',
  name: 'John Doe',
  plan: 'pro',
  createdAt: '2026-01-15',
})

Tip: Properties are merged — if you call identify again with different properties, old properties are preserved and new ones are added or updated.

Track Events

Track meaningful user actions:

// Basic event
Retenshun.track('button_clicked', { button: 'signup_cta' })

// With more context
Retenshun.track('purchase', {
  amount: 49.99,
  currency: 'USD',
  product_id: 'prod_1',
  product_name: 'Pro Plan',
})

// Feature usage
Retenshun.track('feature_used', { feature: 'csv_export' })

Page Views

If autoTrack.pageViews is enabled, pages are tracked automatically. You can also track manually:

// Auto-detected page name from document.title
Retenshun.page()

// Custom page name
Retenshun.page('Pricing Page', { referrer: 'google' })

Update User Properties

Update user properties without re-identifying:

Retenshun.setUserProperties({
  plan: 'enterprise',
  company: 'Acme Inc',
  teamSize: 25,
})

E-commerce Tracking

Built-in e-commerce helpers with standardized event names:

// Product viewed
Retenshun.ecommerce.productViewed({
  product_id: 'prod_1',
  name: 'Wireless Headphones',
  price: 79.99,
  category: 'Electronics',
})

// Added to cart
Retenshun.ecommerce.addedToCart({
  product_id: 'prod_1',
  name: 'Wireless Headphones',
  price: 79.99,
  quantity: 1,
})

// Removed from cart
Retenshun.ecommerce.removedFromCart({
  product_id: 'prod_1',
})

// Checkout started
Retenshun.ecommerce.checkoutStarted({
  cart_id: 'cart_abc',
  total: 159.98,
  item_count: 2,
})

// Order completed
Retenshun.ecommerce.orderCompleted({
  order_id: 'ord_123',
  total: 159.98,
  currency: 'USD',
  products: [
    { product_id: 'prod_1', quantity: 2, price: 79.99 },
  ],
})

Push Notifications (Web Push)

Built-in Web Push support via FCM and VAPID. No third-party services needed.

Enable Push in Config

Retenshun.init({
  projectId: 'YOUR_PROJECT_ID',
  apiKey: 'pk_live_YOUR_PUBLIC_KEY',
  push: {
    enabled: true,
    autoRegister: true,          // Auto-subscribe after identify() if permission granted
    serviceWorkerPath: '/sw.js', // Path to your service worker (default: /sw.js)
  },
})

Request Permission & Subscribe

// Check if push is supported in this browser
if (Retenshun.push.isSupported()) {
  // Request notification permission
  const permission = await Retenshun.push.requestPermission()

  if (permission === 'granted') {
    // Subscribe to push notifications
    await Retenshun.push.subscribe()
  }
}

// Check current permission state
const state = Retenshun.push.getPermission() // 'granted' | 'denied' | 'default'

// Get subscription state
const pushState = Retenshun.push.getState() // 'subscribed' | 'unsubscribed' | 'unsupported'

Unsubscribe

await Retenshun.push.unsubscribe()

Service Worker

Create a public/sw.js file to handle incoming push notifications:

// public/sw.js
self.addEventListener('push', (event) => {
  const data = event.data?.json() ?? {}
  event.waitUntil(
    self.registration.showNotification(data.title || 'Notification', {
      body: data.body,
      icon: '/icon-192.png',
      data: { url: data.url },
    })
  )
})

self.addEventListener('notificationclick', (event) => {
  event.notification.close()
  const url = event.notification.data?.url
  if (url) {
    event.waitUntil(clients.openWindow(url))
  }
})

Note: If autoRegister is enabled, the SDK will automatically subscribe the user after identify() is called, provided the browser already has notification permission.

Reset / Logout

Call reset() when a user logs out. This clears the user identity and generates a new anonymous ID.

Retenshun.reset()

Utility Methods

// Get current user ID (null if not identified)
const userId = Retenshun.getUserId()

// Get anonymous ID (always set)
const anonId = Retenshun.getAnonymousId()

Complete Example

import { Retenshun } from '@retenshun/js'

// 1. Initialize (once, on app load)
Retenshun.init({
  projectId: 'proj_abc123',
  apiKey: 'pk_live_your_key',
})

// 2. Identify on login
function onLogin(user) {
  Retenshun.identify(user.id, {
    email: user.email,
    name: user.name,
    plan: user.plan,
  })
}

// 3. Track actions
document.getElementById('export-btn')
  .addEventListener('click', () => {
    Retenshun.track('feature_used', { feature: 'export' })
  })

// 4. Reset on logout
function onLogout() {
  Retenshun.reset()
}