Skip to content

Sesamy JS

The official Sesamy browser JavaScript library (@sesamy/sesamy-js) for handling authentication, analytics, content access, and communication with the Sesamy API.

Difference from Sesamy SDK

This is the browser-focused library for content access control and user experience features. For direct API access in Node.js or server environments, use the Sesamy SDK instead.

Installation

Easiest Setup: Scripts Host

For the simplest integration with automatic configuration and updates, use the Scripts Host service instead of manual installation.

bash
npm install @sesamy/sesamy-js
bash
yarn add @sesamy/sesamy-js
bash
pnpm add @sesamy/sesamy-js

Requirements

  • Modern browser with JavaScript enabled
  • TypeScript 4.5+ (for TypeScript projects)

Quick Start

Recommended: Scripts Host

For production use, we recommend using the Scripts Host for automatic configuration and CDN delivery. The examples below show manual integration.

Script Tag Initialization

The simplest way to use the SDK is via a script tag with JSON configuration:

html
<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdn.sesamy.com/sesamy-js/latest/sesamy-js.min.js"></script>
    <script type="application/json" id="sesamy-js">
      {
        "clientId": "your-client-id"
      }
    </script>
  </head>
  <body>
    <script>
      // Wait for the SDK to be ready
      window.addEventListener('sesamyJsReady', async () => {
        // Check if user is authenticated
        const isAuth = await window.sesamy.auth.isAuthenticated();
        console.log('User authenticated:', isAuth);

        // Get user profile
        if (isAuth) {
          const profile = await window.sesamy.profile.get();
          console.log('User profile:', profile);
        }
      });
    </script>
  </body>
</html>

Programmatic Initialization

You can also initialize the SDK programmatically:

typescript
import { init } from '@sesamy/sesamy-js';
import { createAuth0Plugin } from '@sesamy/sesamy-js/auth0-plugin';

const sesamy = await init(
  { clientId: 'your-client-id' },
  { authPlugin: createAuth0Plugin() }, // omit for BFF / cookie-based auth
);

// Check authentication
const isAuth = await sesamy.auth.isAuthenticated();

// Get user profile
if (isAuth) {
  const profile = await sesamy.profile.get();
}

Configuration

Basic Configuration

The only required configuration is the clientId:

javascript
{
  "clientId": "your-client-id"
}

Advanced Configuration

javascript
{
  clientId: "your-client-id",
  organization: "org_123",  // Optional: Auth0 organization ID

  // API configuration
  api: {
    namespace: "sesamy",  // Window object namespace (default: "sesamy")
    // Accepts an absolute URL or a relative path on the current origin:
    //   "https://api2.sesamy.com"   – direct / custom domain
    //   "/api"                      – proxied through your own backend
    endpoint: "https://api2.sesamy.com"
  },

  // Analytics configuration
  analytics: {
    enabled: true,
    endpoint: "https://logs.sesamy.com/events"
  },

  // Authentication configuration
  auth: {
    clientId: "your-client-id",
    organization: "org_123",
    enabled: true,
    domain: "auth.example.com",  // Optional: Custom Auth0 domain
    domains: []  // Optional: Array of auth domains for multi-domain setups
  },

  // Content configuration
  content: [
    {
      type: "article",
      path: "/articles",  // Optional: URL path filter
      queryParam: { key: "preview", value: "true" },  // Optional: Query parameter filter
      headers: { name: "User-Agent", contains: "mobile" },  // Optional: Header filter (case-insensitive)
      pass: "premium",    // Optional: Pass requirement
      price: {
        amount: 9.99,
        currency: "USD"
      },
      paywallUrl: "https://example.com/paywall",
      enablePaywallSettingsUrlFallback: false,  // Optional: Fallback to <sesamy-paywall settings-url>
      selectors: {
        article: { selector: "article" },
        title: { selector: "h1", attribute: "textContent" },
        image: { selector: "img", attribute: "src" },
        // ... other selectors
      }
    }
  ],

  // Transform configuration
  transforms: {
    enabled: false,
    rules: []
  }
}

Multi-Domain Authentication

For applications across multiple domains (white-label, multi-region):

javascript
{
  auth: {
    clientId: "your-client-id",
    domains: [
      "auth.brand1.com",
      "auth.brand2.com",
      "auth.example.co.uk"
    ],
    domain: "default-auth.example.com"  // Fallback domain
  }
}

The SDK automatically selects the appropriate auth domain based on the current page's top-level domain.

For publishers deploying on a custom domain, sesamy-js supports the Token Handler pattern where the Sesamy API proxy manages the OAuth flow and stores tokens in HttpOnly cookies. JavaScript never sees a raw access token.

When to use this

Use useHttpCookies: true when your site is served from a custom domain behind the Sesamy API proxy (configured via Scripts Host). It is the recommended option for paywalls and premium content sites.

How auth mode is selected

sesamy-js chooses its auth plugin at startup:

  1. If authPlugin is passed to init() as the second argument → use it (explicit and preferred).
  2. If auth.useHttpCookies: true is set → use the cookie-based BFF plugin regardless of what else is present.
  3. If the Auth0 plugin IIFE was loaded as a <script> before sesamy-js → detected automatically via the window.auth0Plugin global.
  4. Otherwise → fall back to the cookie-based BFF plugin.

Setting auth.useHttpCookies: true is the explicit, unambiguous way to opt in. It makes the cookie plugin redirect login() to /auth/{vendorId}/login (and logout() to /auth/logout) instead of opening the Auth0 Universal Login popup/redirect.

The api.endpoint field controls where sesamy-js sends data API requests (/entitlements, /contracts, etc.) and accepts either a relative path or a full URL. It does not affect the /auth/* routes — those are always relative to the current origin:

Relative path (proxy on same origin)

Set api.endpoint to a path such as "/api" when your backend proxies Sesamy API routes under that prefix:

javascript
{
  "clientId": "your-vendor-id",
  "vendorId": "your-vendor-id",
  "auth": {
    "useHttpCookies": true
  },
  "api": {
    "endpoint": "/api"
  }
}

All API calls (/api/entitlements, /api/contracts, etc.) are made to the same origin as the page, so HttpOnly cookies are sent automatically.

Custom domain

Set api.endpoint to a fully-qualified URL when your Sesamy API proxy lives on a dedicated subdomain:

javascript
{
  "clientId": "your-vendor-id",
  "vendorId": "your-vendor-id",
  "auth": {
    "useHttpCookies": true
  },
  "api": {
    "endpoint": "https://api.yoursite.com"
  }
}

The @auth0/auth0-spa-js script is not required in either mode.

Login & Logout

In BFF mode the SDK's login() method navigates to /auth/{vendorId}/login (vendor ID comes from your vendorId / clientId config). The logout() method navigates to /auth/logout:

javascript
// Trigger login (redirects to token.sesamy.com via /auth/<vendorId>/login, then back)
await window.sesamy.auth.login();

// Trigger logout
await window.sesamy.auth.logout();

Auth Status

The SDK automatically checks auth status on load by calling /auth/userinfo. You can also check it manually:

javascript
const isAuth = await window.sesamy.auth.isAuthenticated();

Local Development with Vite

When developing locally, you need a reverse proxy so browser cookies are scoped to localhost. Configure Vite to forward /auth and API routes to the Sesamy API proxy:

typescript
// vite.config.ts
import { defineConfig } from 'vite';

const API_TARGET = process.env.VITE_API_TARGET ?? 'https://api2.sesamy.dev';
const FORWARDED_HOST = process.env.VITE_FORWARDED_HOST ?? 'localhost:5173';

function apiProxy() {
  return {
    target: API_TARGET,
    changeOrigin: true,
    headers: {
      // Tells the Worker which hostname to use for cookie scoping
      // and token-handler lookup. Must match the entry in your
      // token-handler config (auth_hostname).
      'x-forwarded-host': FORWARDED_HOST,
    },
  };
}

export default defineConfig({
  server: {
    proxy: {
      // Forward /auth/* for the BFF token-handler flow
      '/auth': apiProxy(),
      // If using a prefix like api.endpoint = "/api", a single rule covers
      // all Sesamy API routes. Otherwise list each route individually.
      '/api':  apiProxy(),

      // Example: individual routes when not using a prefix
      // '/contracts':    apiProxy(),
      // '/entitlements': apiProxy(),
      // '/products':     apiProxy(),
      // '/profile':      apiProxy(),
    },
  },
});

Using a local API Worker instead

To run the API Worker locally (e.g. wrangler dev --remote on port 8787) instead of forwarding to the deployed dev API:

bash
VITE_API_TARGET=http://localhost:8787 pnpm dev

Because login and callback URLs now include the vendor ID in the path (/auth/<vendorId>/login), cookie scoping no longer depends on x-forwarded-host. You can navigate directly to http://localhost:8787/auth/<vendorId>/login and the full BFF flow will work. Remember to add http://localhost:8787/auth/<vendorId>/callback to the Allowed Callback URLs in your Auth0 application settings.

Deployed API target and localhost cookies

When VITE_API_TARGET points to the deployed api2.sesamy.dev Worker (the default), cookies set by that Worker will be scoped to .sesamy.dev — not localhost — and won't be sent back by your browser. For a fully working BFF flow in local development, use a local wrangler dev instance (VITE_API_TARGET=http://localhost:8787) or navigate directly to http://localhost:8787/auth/<vendorId>/login without the Vite proxy.

Core API

Safely Accessing the API

When building components or modules that need to access Sesamy JS, use this helper function to safely wait for the SDK to be ready:

typescript
export async function getApi(): Promise<SesamyAPI> {
  // If already ready, return immediately
  if (window.sesamy?.isReady()) {
    return window.sesamy;
  }

  // Wait for the ready event with timeout
  return new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      window.removeEventListener('sesamyJsReady', onSesamyJsReady);
      if (window.sesamy) {
        resolve(window.sesamy);
      } else {
        reject(new Error('sesamyJsReady event did not occur within the expected time.'));
      }
    }, 5000);

    function onSesamyJsReady() {
      if (!window.sesamy) {
        reject(new Error('Sesamy API is not available'));
      } else {
        clearTimeout(timeout);
        window.removeEventListener('sesamyJsReady', onSesamyJsReady);
        resolve(window.sesamy);
      }
    }

    window.addEventListener('sesamyJsReady', onSesamyJsReady);
  });
}

Usage:

typescript
// In your component or module
async function initComponent() {
  try {
    const sesamy = await getApi();

    // Now safely use the API
    const isAuth = await sesamy.auth.isAuthenticated();
    if (isAuth) {
      const profile = await sesamy.profile.get();
      console.log('User profile:', profile);
    }
  } catch (error) {
    console.error('Failed to initialize Sesamy:', error);
  }
}

initComponent();

This approach:

  • Returns immediately if the SDK is already ready
  • Waits for the sesamyJsReady event if not ready yet
  • Includes a 5-second timeout to prevent hanging
  • Properly cleans up event listeners

Checking SDK Readiness

For simple synchronous checks:

javascript
// Check if SDK is ready
if (window.sesamy?.isReady()) {
  console.log('SDK is ready');
}

// Or listen for the ready event
window.addEventListener('sesamyJsReady', () => {
  console.log('SDK is ready');
});

API Documentation

Sesamy JS provides a comprehensive set of APIs organized by functionality:

Authentication

User login, logout, session management, and profile operations. Authentication is separate because it's fundamental to all other operations.

Content

Content discovery, access control, paywalls, and content unlocking. This is a distinct browser-specific feature for managing locked content.

API Reference

Complete API reference for all SDK wrapper methods:

  • Entitlements - Check and manage user access to content
  • Subscriptions (Contracts) - Manage user subscriptions
  • Checkouts - Create and manage purchase flows
  • Products - Retrieve product information
  • Bills & Transactions - Access billing history
  • Attribution - Manage tracking attribution

These are grouped together as they're all SDK wrapper methods providing similar functionality.

Analytics

Event tracking and analytics. Separate because it's an optional feature that can be enabled/disabled independently.

TypeScript Support

The library includes comprehensive TypeScript definitions:

typescript
import { init, SesamyAPI } from '@sesamy/sesamy-js';

const sesamy: SesamyAPI = await init({
  clientId: 'your-client-id',
});

// Full type safety
const profile: Profile | null = await sesamy.profile.get();
const entitlements: Entitlement[] = await sesamy.entitlements.list();

Next Steps

Released under the MIT License.