Skip to content

revealos/reveal-client

Repository files navigation

Reveal Logo

Reveal Client SDK

CI License: MIT

Detect when users get stuck — and respond in real time.

A lightweight SDK for understanding user behaviour and improving onboarding automatically.

Core Concepts

Lightweight & High-Performance

  • Minimal footprint: Zero runtime dependencies, ~20KB gzipped (ESM)
  • No heavy dependencies: Framework-agnostic core, optional React overlay
  • Fast initialization: Synchronous setup completes in ~10-15ms (config fetch adds network latency)
  • Efficient event batching: Automatic batching and debouncing of events

Security-First Architecture

  • No PII captured automatically: Only explicit event payloads are sent
  • Single audited transport: All outbound network calls flow through a single, auditable transport module
  • Structured JSON only: No HTML injection, no dynamic code execution
  • Passive rendering: Overlay renders text-only content from backend decisions

Contextual Activation Nudges

  • Friction detection: Automatically detects user hesitation (stall), rapid clicks (rage click), and backward navigation (backtrack)
  • Decision API: Backend determines when and which nudges to show
  • Safe overlay rendering: Templates render decisions through auditable, text-only components

Quick Start

1. Install

React applications:

npm install @reveal/client @reveal/overlay-react

Other frameworks (Vue, Svelte, Angular) or vanilla JavaScript:

npm install @reveal/client @reveal/overlay-wc

Note: @reveal/overlay-react is a thin React adapter over @reveal/overlay-wc Web Components. All UI logic lives in the framework-agnostic @reveal/overlay-wc package.

2. Initialize

React Applications

Create a RevealContextProvider component to handle SDK initialization and overlay rendering:

// components/RevealContextProvider.tsx (or app/reveal-context-provider.tsx)
'use client';

import React, { useEffect } from 'react';
import { Reveal, useNudgeDecision } from '@reveal/client';
import { OverlayManager } from '@reveal/overlay-react';

export function RevealContextProvider({ children }: { children: React.ReactNode }) {
  const { decision, handlers } = useNudgeDecision();

  useEffect(() => {
    (async () => {
      await Reveal.init('your-client-key');
    })();
  }, []);

  return (
    <>
      {children}
      <OverlayManager
        decision={decision}
        onDismiss={handlers.onDismiss}
        onActionClick={handlers.onActionClick}
        onTrack={handlers.onTrack}
      />
    </>
  );
}

Then wrap your app with the provider:

Next.js (App Router):

// app/layout.tsx
import { RevealContextProvider } from './reveal-context-provider';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <RevealContextProvider>{children}</RevealContextProvider>
      </body>
    </html>
  );
}

Next.js (Pages Router):

// pages/_app.tsx
import { RevealContextProvider } from '../components/RevealContextProvider';

export default function App({ Component, pageProps }) {
  return (
    <RevealContextProvider>
      <Component {...pageProps} />
    </RevealContextProvider>
  );
}

React (Create React App):

// src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { RevealContextProvider } from './components/RevealContextProvider';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <RevealContextProvider>
    <App />
  </RevealContextProvider>
);

Other Frameworks (Vue, Svelte, Angular) or Vanilla JavaScript

Use @reveal/overlay-wc Web Components directly:

import { Reveal } from '@reveal/client';
import '@reveal/overlay-wc';

// Initialize SDK
await Reveal.init('your-client-key');

// Create overlay manager
const manager = document.createElement('reveal-overlay-manager');
document.body.appendChild(manager);

// Subscribe to nudge decisions
Reveal.onNudgeDecision((decision) => {
  manager.decision = decision;
});

// Listen for user interactions
manager.addEventListener('reveal:dismiss', (e) => {
  Reveal.track('nudge', 'dismissed', { nudge_id: e.detail.id });
});

manager.addEventListener('reveal:action-click', (e) => {
  Reveal.track('nudge', 'clicked', { nudge_id: e.detail.id });
});

See overlay-wc/README.md for framework-specific examples (Vue, Svelte, etc.).

3. Track Events & Display Nudges

Track product events:

import { Reveal } from '@reveal/client';

// Track user actions with semantic IDs (recommended)
Reveal.track('product', 'button_clicked', {
  action_id: 'signup_button_click',
  flow_id: 'onboarding',
  buttonId: 'signup',
  page: '/onboarding',
});

The OverlayManager component automatically displays contextual nudges when the backend decides to show them. No additional setup required.

For complete event type documentation, see docs/EVENTS.md.

Security Guarantees

  • Structured payloads only: Only explicitly defined event payloads are sent. No automatic data collection.
  • No DOM scraping: The SDK does not read or transmit DOM content, form values, or page HTML.
  • Minimal storage usage: The SDK uses localStorage and sessionStorage only for SDK-internal state:
    • localStorage: Anonymous ID persistence, treatment assignment, sampling decisions (all scoped per project + user)
    • sessionStorage: Tab-level sequence counter for event ordering
    • All storage is SDK-internal state only (no user data stored)
    • Storage failures are handled gracefully (fail-open behavior)
  • Two documented transport modules: All network calls flow through two auditable modules:
    • packages/client/src/modules/transport.ts - JSON API calls (/ingest, /decide)
    • packages/client/src/modules/recordingUpload.ts - Recording upload flow (3-step direct-to-storage)
  • Text-only rendering: The overlay renders text content only. No HTML injection, no JavaScript execution, no dynamic code evaluation.
  • No automatic PII capture: PII cannot be captured automatically. Only data explicitly passed to Reveal.track() is sent.

Architecture

The SDK operates in three layers:

  1. Detection Layer: Passive observers detect friction patterns (stall, rage click, backtrack)
  2. Decision Layer: Backend API determines when and which nudges to show
  3. Rendering Layer: OverlayManager renders backend decisions through safe, auditable templates

All layers are designed to fail gracefully and never break the host application.

Documentation

License

MIT

Releases

No releases published

Packages

 
 
 

Contributors