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

No packages published

Contributors 2

  •  
  •