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.
npm install @sesamy/sesamy-jsyarn add @sesamy/sesamy-jspnpm add @sesamy/sesamy-jsRequirements
- 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:
<!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:
import { init } from '@sesamy/sesamy-js';
const sesamy = await init({
clientId: 'your-client-id',
});
// 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:
{
"clientId": "your-client-id"
}Advanced Configuration
{
clientId: "your-client-id",
organization: "org_123", // Optional: Auth0 organization ID
// API configuration
api: {
namespace: "sesamy", // Window object namespace (default: "sesamy")
endpoint: "https://api2.sesamy.com" // API endpoint
},
// 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
pass: "premium", // Optional: Pass requirement
price: {
amount: 9.99,
currency: "USD"
},
paywallUrl: "https://example.com/paywall",
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):
{
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.
Core API
Checking SDK Readiness
// 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');
});Authentication
The SDK provides comprehensive authentication methods with support for both redirect and popup-based flows.
login()
Smart login that automatically chooses the best authentication method based on browser context.
Parameters:
options(optional):appState: State to preserve during redirectauthorizationParams:audience: API audiencescope: OAuth scopeslogin_hint: Pre-fill emailorganization: Auth0 organizationredirect_uri: Post-login redirect URL
Returns: Promise<void>
Example:
await window.sesamy.auth.login({
authorizationParams: {
login_hint: 'user@example.com',
},
});loginWithRedirect()
Redirects user to Auth0 hosted login page. Best for desktop browsers.
Parameters:
- Same as
login()
Returns: Promise<void>
Example:
await window.sesamy.auth.loginWithRedirect({
authorizationParams: {
redirect_uri: window.location.origin + '/callback',
},
});loginWithPopup()
Opens login in a popup window. Better for maintaining page state and works better in incognito mode.
Note: To prevent automatic page refresh after authentication, listen for sesamyJsAuthenticated event and call preventDefault().
Parameters:
- Same as
login()
Returns: Promise<void>
Example:
// Prevent auto-refresh after login
window.addEventListener('sesamyJsAuthenticated', (event) => {
event.preventDefault();
console.log('User authenticated!');
});
await window.sesamy.auth.loginWithPopup({
authorizationParams: {
login_hint: 'user@example.com',
},
});logout()
Logs out the user and optionally redirects.
Parameters:
options(optional):returnTo: URL to redirect after logout
Returns: Promise<void>
Example:
await window.sesamy.auth.logout({
returnTo: 'https://yoursite.com',
});isAuthenticated()
Checks if user is currently authenticated.
Returns: Promise<boolean>
Example:
const isAuth = await window.sesamy.auth.isAuthenticated();
if (isAuth) {
console.log('User is logged in');
}getTokenSilently()
Retrieves access token without user interaction.
Parameters:
throwOnUnauthorized(boolean, default: true): Throw error if not authenticatedforceRefresh(boolean, default: false): Force token refresh
Returns: Promise<string | null>
Example:
const token = await window.sesamy.auth.getTokenSilently();
// Use token for API callssetToken()
Manually set an access token.
Parameters:
accessToken(string): The access tokenexpiresIn(number, optional): Token expiration in seconds
Returns: Promise<void>
Example:
await window.sesamy.auth.setToken('your.jwt.token', 3600);Profile Management
profile.get()
Fetches the user's profile information.
Returns: Promise<Profile | null>
Profile Type:
type Profile = {
userId: string;
firstName?: string;
lastName?: string;
emailVerified: boolean;
email: string;
name?: string;
locale?: string;
picture?: string;
createdAt: string;
updatedAt: string;
mobilePhone?: string;
tags: string[];
user_metadata?: { [id: string]: string | number };
billingAddress?: Address;
deliveryAddress?: Address;
};Example:
const profile = await window.sesamy.profile.get();
if (profile) {
console.log(profile.email);
}profile.update()
Updates the user's profile information.
Parameters:
profile(Partial<Profile>): Fields to update
Returns: Promise<boolean>
Example:
const success = await window.sesamy.profile.update({
firstName: 'John',
lastName: 'Doe',
mobilePhone: '+1234567890',
billingAddress: {
street: '123 Main St',
city: 'New York',
state: 'NY',
postalCode: '10001',
country: 'US',
},
});profile.openHostedAccountPage()
Opens the Sesamy hosted account management page.
Example:
window.sesamy.profile.openHostedAccountPage();profile.isSpotifyLinked()
Checks if user has linked their Spotify account.
Returns: Promise<boolean>
Example:
const isLinked = await window.sesamy.profile.isSpotifyLinked();profile.unlinkSpotify()
Unlinks the user's Spotify account.
Returns: Promise<void>
Entitlements
entitlements.list()
Fetches the list of user's entitlements.
Parameters:
params(optional):includeSignedLinks(boolean, default: true)waitForEntitlementAfter(Date, optional)
Returns: Promise<Entitlement[]>
Example:
const entitlements = await window.sesamy.entitlements.list({
includeSignedLinks: true,
});
entitlements.forEach((ent) => {
console.log(`${ent.id}: ${ent.type}`);
});entitlements.get()
Fetches a specific entitlement by ID.
Parameters:
entitlementId(string)
Returns: Promise<Entitlement | undefined>
Example:
const entitlement = await window.sesamy.entitlements.get('ent_123');
if (entitlement) {
console.log('Access granted:', entitlement);
}entitlements.hasAccess()
Checks if user has access to specific content.
Parameters:
itemSrc(string): Content identifier
Returns: Promise<boolean>
Example:
const hasAccess = await window.sesamy.entitlements.hasAccess('article_123');
if (hasAccess) {
// Show premium content
} else {
// Show paywall
}entitlements.access()
Fetches access details for a specific entitlement.
Parameters:
entitlementId(string)
Returns: Promise<Access>
Example:
const access = await window.sesamy.entitlements.access('ent_123');
console.log('Access URL:', access.url);entitlements.signedLinks()
Returns signed links from the current session.
Returns: SignedLink[]
Example:
const signedLinks = window.sesamy.entitlements.signedLinks();
console.log('Signed links:', signedLinks);Contracts (Subscriptions)
contracts.list()
Lists all user's contracts (subscriptions).
Returns: Promise<Contract[]>
Example:
const contracts = await window.sesamy.contracts.list();
contracts.forEach((contract) => {
console.log(`${contract.id}: ${contract.status}`);
});contracts.get()
Gets a specific contract by ID.
Parameters:
contractId(string)
Returns: Promise<Contract>
Example:
const contract = await window.sesamy.contracts.get('con_123');
console.log('Contract status:', contract.status);contracts.cancel()
Cancels a contract by ID.
Parameters:
contractId(string)
Returns: Promise<void>
Example:
await window.sesamy.contracts.cancel('con_123');
console.log('Contract cancelled');Checkouts
The checkouts API allows you to create and manage checkout sessions for purchasing products or subscriptions.
checkouts.create()
Creates a new checkout session.
Parameters:
{
// Required
items: Item[], // Array of items to purchase
redirectUrl: string, // URL to redirect after checkout completion
// Customer information (optional)
email?: string,
givenName?: string,
familyName?: string,
phoneNumber?: string,
birthDate?: string,
country?: string,
// Gift mode settings (optional)
giftMode?: boolean, // When true, enables gift purchase mode where payer differs from recipient
payerEmail?: string, // Email of the person paying (used when giftMode is true)
// Billing address (optional)
address?: {
street?: string,
city?: string,
zip?: string,
country?: string,
},
// Business information (optional)
isBusiness?: boolean,
businessAddress?: Address,
// Pricing (optional - overrides item pricing)
price?: number,
currency?: string,
// Payment options (optional)
paymentMethodsFilter?: Array<{
provider: string,
methods?: string[]
}>,
// Discount codes
requestedDiscountCodes?: string[],
// Language
language?: string,
// Attribution/Tracking (optional)
attribution?: {
utmSource?: string,
utmMedium?: string,
utmCampaign?: string,
utmTerm?: string,
utmContent?: string,
ref?: string,
referrer?: string,
itemSrc?: string,
publisherContentId?: string,
// Tracking cookies
_ga?: string,
_gid?: string,
_fbp?: string,
_fbc?: string,
},
referralEmail?: string,
}Where Item is:
{
sku?: string, // Product SKU
url?: string, // Item URL
purchaseOptionId?: string, // Purchase option ID
price?: number, // Item price
currency?: string, // Currency code (e.g., 'USD')
geoRestrictions?: {
type: 'ALLOW' | 'BLOCK',
countries: string[]
}
}Returns: Promise<Checkout>
The Checkout response includes:
{
id: string, // Checkout session ID
checkoutUrl: string, // URL to redirect user to for checkout
status: 'PENDING' | 'PAID',
type: 'RECURRING' | 'SINGLE',
giftMode?: boolean, // Whether this is a gift purchase
itemsOwned: Array<{
sku: string,
purchaseOptionId: string,
title: string,
}>,
appliedDiscountCodes: Array<{
name: string,
description: string,
id: string,
code: string,
status: 'APPLIED' | 'UNAPPLICABLE',
}>,
availablePaymentMethods: Array<{
provider: string,
methods?: string[]
}>,
createdAt: string,
updatedAt: string,
// ... plus all the submitted parameters (including email and payerEmail if provided)
}Example - Simple purchase:
const checkout = await window.sesamy.checkouts.create({
items: [
{
sku: 'premium_monthly',
purchaseOptionId: 'po_123',
price: 9.99,
currency: 'USD',
},
],
email: 'user@example.com',
redirectUrl: 'https://yoursite.com/checkout-complete',
});
// Redirect user to checkout page
window.location.href = checkout.checkoutUrl;Example - Multiple items with attribution:
const checkout = await window.sesamy.checkouts.create({
items: [
{
sku: 'premium_annual',
purchaseOptionId: 'po_456',
price: 99.99,
currency: 'USD',
},
{
sku: 'addon_feature',
price: 9.99,
currency: 'USD',
},
],
email: 'user@example.com',
givenName: 'John',
familyName: 'Doe',
phoneNumber: '+1234567890',
address: {
street: '123 Main St',
city: 'San Francisco',
zip: '94102',
country: 'US',
},
redirectUrl: 'https://yoursite.com/checkout-complete',
language: 'en',
attribution: {
utmSource: 'email',
utmMedium: 'newsletter',
utmCampaign: 'black_friday_2024',
},
requestedDiscountCodes: ['WELCOME10', 'EARLYBIRD'],
});
window.location.href = checkout.checkoutUrl;Example - Gift mode purchase:
// When someone wants to buy a subscription as a gift for someone else
const checkout = await window.sesamy.checkouts.create({
items: [
{
sku: 'premium_annual',
purchaseOptionId: 'po_456',
price: 99.99,
currency: 'USD',
},
],
giftMode: true,
payerEmail: 'buyer@example.com', // Person making the purchase
email: 'recipient@example.com', // Person receiving the subscription
givenName: 'Jane',
familyName: 'Doe',
redirectUrl: 'https://yoursite.com/gift-complete',
language: 'en',
});
window.location.href = checkout.checkoutUrl;Gift Mode
When giftMode is enabled, the checkout treats the email field as the recipient's email address, and the payerEmail field as the purchaser's email. This is useful for gift subscriptions where the person paying is different from the person who will receive access to the content.
checkouts.get()
Gets an existing checkout session by ID.
Parameters:
checkoutId(string): The ID of the checkout session
Returns: Promise<Checkout>
Example:
const checkout = await window.sesamy.checkouts.get('checkout_123');
console.log('Status:', checkout.status);
console.log('Checkout URL:', checkout.checkoutUrl);
console.log('Applied discounts:', checkout.appliedDiscountCodes);checkouts.update()
Updates an existing checkout session. You can update customer information, items, or other checkout details.
Parameters:
checkoutId(string): The ID of the checkout sessionparams(object): Partial checkout parameters to update
Returns: Promise<Checkout>
Example:
const updated = await window.sesamy.checkouts.update('checkout_123', {
email: 'newemail@example.com',
givenName: 'Jane',
requestedDiscountCodes: ['NEWCODE'],
});
console.log('Updated checkout:', updated);Example - Update with gift mode:
// Update a checkout to add payer information for a gift purchase
const updated = await window.sesamy.checkouts.update('checkout_123', {
email: 'recipient@example.com', // Recipient of the gift
payerEmail: 'buyer@example.com', // Person paying for the gift
givenName: 'Jane',
familyName: 'Doe',
});
console.log('Updated checkout for gift:', updated);Content Management
The content management API provides methods to discover, analyze, and unlock content on your page. It works by analyzing DOM elements based on configured selectors and extracting metadata through intelligent DOM traversal with fallback mechanisms.
Configuration
Content configuration can be provided in two ways:
- Manual initialization - Via the
init()config - Script Host injection - Automatically injected when using the Scripts Host
Example Configuration
{
content: [
{
type: 'article',
path: '/articles', // Optional: Only match articles on this path
pass: 'premium', // Optional: Required pass for access
price: {
amount: 9.99,
currency: 'USD',
},
paywallUrl: 'https://example.com/paywall',
selectors: {
// Container selector - identifies content on page
article: {
selector: 'article.content',
},
// Content metadata selectors
title: {
selector: 'h1.article-title',
attribute: 'textContent',
},
description: {
selector: "meta[name='description']",
attribute: 'content',
},
image: {
selector: "meta[property='og:image']",
attribute: 'content',
},
author: {
selector: '.author-name',
attribute: 'textContent',
},
publishedTime: {
selector: "meta[property='article:published_time']",
attribute: 'content',
},
paywallUrl: {
selector: 'a.paywall-link',
attribute: 'href',
},
// Custom metadata
category: {
selector: '.article-category',
attribute: 'textContent',
},
tags: {
selector: '.article-tags .tag',
attribute: 'textContent',
multiple: true, // Extract multiple values
},
},
},
];
}Selector Resolution Strategy
When extracting metadata, the SDK uses a hierarchical resolution strategy:
- Element-level selectors - Search within the content container
- DOM traversal upwards - Walk up the DOM tree to find parent elements
- Page-level meta tags - Fallback to
<head>meta tags - Configuration defaults - Use values from init config or script host settings
Example DOM traversal:
<article class="content" data-item-id="article_123">
<div class="article-header">
<h1 class="article-title">Breaking News</h1>
<span class="author-name">John Doe</span>
</div>
<div class="article-body">
<!-- Content here -->
</div>
<a class="paywall-link" href="https://example.com/paywall?item=article_123">Read Full Article</a>
</article>
<head>
<meta property="og:image" content="https://example.com/image.jpg" />
<meta name="description" content="Article description" />
</head>With this structure:
titleis found within the article containerauthoris found by traversing up from contentimagefalls back to page-level meta tagdescriptionuses the meta tag fallbackpaywallUrlis extracted from the paywall link, with fallback to config
PaywallUrl Resolution
The paywallUrl property is resolved using the same hierarchical strategy as other metadata properties:
- Element-level selector - Look for a link element with the configured selector (e.g.,
a.paywall-link) and extract itshrefattribute - DOM traversal - Walk up the DOM tree if not found in the container
- Content configuration - Use the
paywallUrldefined in the content node configuration if not found in HTML
Example:
// In configuration
{
type: 'article',
paywallUrl: 'https://example.com/paywall', // Fallback URL from config
selectors: {
paywallUrl: {
selector: 'a.paywall-link',
attribute: 'href'
},
// ... other selectors
}
}
// In HTML - this will be used first
<article class="content">
<h1>Article Title</h1>
<a class="paywall-link" href="https://example.com/paywall?item=article_123">
Read Full Article
</a>
</article>
// Result: paywallUrl = 'https://example.com/paywall?item=article_123'
// If HTML link was missing, result would be: 'https://example.com/paywall'content.list()
Lists all content items discovered on the current page based on configured selectors.
Returns: Array<ContentItem>
ContentItem Type:
type ContentItem = {
// Core identifiers
id: string; // Unique content identifier
type: string; // Content type (e.g., "article", "video")
url: string; // Content URL
// Metadata
title?: string; // Content title
description?: string; // Content description
image?: string; // Featured image URL
author?: string; // Content author
publishedTime?: string; // ISO 8601 timestamp
modifiedTime?: string; // ISO 8601 timestamp
// Access control
pass?: string; // Required pass/subscription
price?: {
amount: number;
currency: string;
};
paywallUrl?: string; // Custom paywall URL
// Custom properties
[key: string]: any; // Additional configured properties
// DOM reference
element: HTMLElement; // The DOM element
};Example:
// Wait for SDK ready
window.addEventListener('sesamyJsReady', () => {
const contentItems = window.sesamy.content.list();
console.log(`Found ${contentItems.length} content items`);
contentItems.forEach((item) => {
console.log('Content:', {
id: item.id,
title: item.title,
author: item.author,
requiresPass: item.pass,
price: item.price,
});
});
});Example Response:
[
{
id: 'article_123',
type: 'article',
url: 'https://example.com/articles/breaking-news',
title: 'Breaking News: Major Development',
description: "A detailed look at today's major development...",
image: 'https://example.com/images/breaking-news.jpg',
author: 'John Doe',
publishedTime: '2024-11-07T10:30:00Z',
pass: 'premium',
price: {
amount: 4.99,
currency: 'USD',
},
paywallUrl: 'https://example.com/paywall?item=article_123',
category: 'News',
tags: ['breaking', 'politics', 'international'],
element: HTMLElement, // DOM reference
},
{
id: 'article_456',
type: 'article',
url: 'https://example.com/articles/tech-review',
title: 'Tech Review: Latest Gadgets',
description: 'Our comprehensive review of the latest tech...',
image: 'https://example.com/images/tech-review.jpg',
author: 'Jane Smith',
publishedTime: '2024-11-06T14:20:00Z',
pass: 'premium',
category: 'Technology',
tags: ['review', 'gadgets', 'tech'],
element: HTMLElement,
},
];content.get()
Gets a specific content item by DOM element or CSS selector.
Parameters:
elementOrSelector(HTMLElement | string): DOM element or CSS selector
Returns: ContentItem | null
Example:
// Get by selector
const article = window.sesamy.content.get('article.featured');
if (article) {
console.log('Featured article:', article.title);
console.log('Requires:', article.pass);
console.log('Price:', article.price);
}
// Get by element
const element = document.querySelector('.main-article');
const content = window.sesamy.content.get(element);Example Response:
{
id: "article_789",
type: "article",
url: "https://example.com/articles/featured",
title: "Featured: The Future of Technology",
description: "An in-depth analysis of emerging technologies...",
image: "https://example.com/images/future-tech.jpg",
author: "Sarah Johnson",
publishedTime: "2024-11-07T08:00:00Z",
pass: "premium",
price: {
amount: 9.99,
currency: "USD"
},
paywallUrl: "https://example.com/paywall?item=article_789",
category: "Technology",
tags: ["featured", "analysis", "future"],
element: HTMLElement
}content.unlock()
Unlocks and retrieves locked content. This method integrates with the Content Proxy to fetch and decrypt premium content.
Parameters:
elementOrSelector(HTMLElement | string): DOM element or CSS selector
Returns: Promise<string | null>
How it works:
- Identifies the content item
- Checks user's entitlements via
entitlements.hasAccess() - If authorized, fetches content via Content Proxy
- Decrypts and returns the content HTML
- Returns
nullif unauthorized or content not found
Example:
// Unlock specific article
const unlockedContent = await window.sesamy.content.unlock('#premium-article');
if (unlockedContent) {
// User has access - display content
const contentDiv = document.querySelector('#article-body');
contentDiv.innerHTML = unlockedContent;
console.log('Content unlocked successfully');
} else {
// User doesn't have access - show paywall
window.location.href = '/paywall?item=article_123';
}Example with error handling:
try {
const content = await window.sesamy.content.unlock('.locked-content');
if (content) {
// Replace locked content with unlocked version
document.querySelector('.content-container').innerHTML = content;
// Track unlock event
await window.sesamy.analytics.track('content_unlocked', {
contentId: 'article_123',
contentType: 'article',
});
} else {
// Show paywall
showPaywall();
}
} catch (error) {
console.error('Failed to unlock content:', error);
showErrorMessage();
}Integration with Content Proxy:
The unlock() method uses the Content Proxy endpoint to fetch encrypted content. See the Scripts Host documentation for more details on content encryption and delivery.
content.getLanguage()
Gets the current page language from the HTML element's lang attribute.
Returns: string
Example:
const language = window.sesamy.content.getLanguage();
console.log('Current language:', language); // "en", "sv", etc.
// Use language for localized content
const checkoutLanguage = language === 'sv' ? 'sv' : 'en';content.getPropertyFromHTML()
Extracts a property from HTML content using a selector and attribute.
Parameters:
html(string): HTML content to parseselector(string): CSS selectorattribute(string): Attribute to extract (e.g., "textContent", "src", "href")
Returns: string | null
Example:
const htmlContent = `
<article>
<h1 class="title">Article Title</h1>
<img src="https://example.com/image.jpg" alt="Article Image">
<p class="description">Article description here...</p>
</article>
`;
// Extract title
const title = window.sesamy.content.getPropertyFromHTML(htmlContent, 'h1.title', 'textContent');
console.log('Title:', title); // "Article Title"
// Extract image URL
const imageUrl = window.sesamy.content.getPropertyFromHTML(htmlContent, 'img', 'src');
console.log('Image:', imageUrl); // "https://example.com/image.jpg"
// Extract description
const description = window.sesamy.content.getPropertyFromHTML(
htmlContent,
'.description',
'textContent'
);
console.log('Description:', description); // "Article description here..."Use case - Processing unlocked content:
const unlockedHtml = await window.sesamy.content.unlock('#article');
if (unlockedHtml) {
// Extract specific elements from unlocked content
const headline = window.sesamy.content.getPropertyFromHTML(unlockedHtml, 'h1', 'textContent');
const authorByline = window.sesamy.content.getPropertyFromHTML(
unlockedHtml,
'.author',
'textContent'
);
console.log(`"${headline}" by ${authorByline}`);
// Insert into page
document.querySelector('#content').innerHTML = unlockedHtml;
}Integration Examples
Using with Scripts Host
The Scripts Host automatically injects content configuration based on your publisher settings:
<script src="https://scripts.sesamy.com/loader.js?clientId=your-client-id"></script>The Scripts Host will:
- Load the Sesamy JS SDK
- Inject content selectors from your publisher configuration
- Initialize the SDK with optimal settings
- Enable automatic content discovery
Example with Scripts Host:
// SDK is automatically configured via Scripts Host
window.addEventListener('sesamyJsReady', async () => {
// Content selectors already configured
const articles = window.sesamy.content.list();
// Check access for each article
for (const article of articles) {
const hasAccess = await window.sesamy.entitlements.hasAccess(article.id);
if (!hasAccess) {
// Show paywall overlay
showPaywallOverlay(article);
}
}
});Dynamic Content Loading
// Handle dynamically loaded content
const observer = new MutationObserver(() => {
const newContent = window.sesamy.content.list();
console.log('Content updated, found:', newContent.length);
// Process new content items
processContentItems(newContent);
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
async function processContentItems(items) {
for (const item of items) {
const hasAccess = await window.sesamy.entitlements.hasAccess(item.id);
if (hasAccess) {
// Unlock and display
const content = await window.sesamy.content.unlock(item.element);
if (content) {
item.element.innerHTML = content;
}
} else {
// Show paywall
showPaywallButton(item);
}
}
}Content with Paywall Integration
window.addEventListener('sesamyJsReady', async () => {
const articles = window.sesamy.content.list();
for (const article of articles) {
const hasAccess = await window.sesamy.entitlements.hasAccess(article.id);
if (!hasAccess && article.paywallUrl) {
// Create paywall overlay
const paywall = document.createElement('div');
paywall.className = 'paywall-overlay';
paywall.innerHTML = `
<div class="paywall-content">
<h3>Premium Content</h3>
<p>${article.title}</p>
<p>Price: ${article.price.amount} ${article.price.currency}</p>
<button onclick="location.href='${article.paywallUrl}'">
Subscribe to Read
</button>
</div>
`;
article.element.appendChild(paywall);
} else if (hasAccess) {
// Unlock premium content
const content = await window.sesamy.content.unlock(article.element);
if (content) {
article.element.querySelector('.locked-content').innerHTML = content;
}
}
}
});Products
products.get()
Gets a product by SKU.
Parameters:
sku(string)
Returns: Promise<Product>
Example:
const product = await window.sesamy.products.get('premium-pass');
console.log(product.name, product.price);products.autoOnboard()
Triggers auto-onboarding for a product.
Parameters:
sku(string)
Returns: Promise<void>
Example:
await window.sesamy.products.autoOnboard('premium-pass');products.linkSpotify()
Links a Spotify account to a product.
Parameters:
sku(string)
Returns: Promise<void>
Utility Methods
generateLink()
Generates a link to Sesamy hosted services with optional authentication.
Parameters:
params: Link generation parameterstarget: 'account' | 'change-payment' | 'change-plan' | 'consume' | 'checkout'shorten: (boolean, optional) Shorten the URLttl: (number, optional) Time-to-live in secondsredirectUrl: (string, optional) Post-action redirectlanguage: (string, optional) Language code
Returns: Promise<string>
Example:
// Generate link to account page
const accountLink = await window.sesamy.generateLink({
target: 'account',
shorten: true,
});
// Generate consume link
const consumeLink = await window.sesamy.generateLink({
target: 'consume',
sku: 'premium-article',
redirectUrl: 'https://yoursite.com/article',
});getPaymentIssues()
Returns failed payments and expiring cards.
Returns: Promise<PaymentIssue[]>
Example:
const issues = await window.sesamy.getPaymentIssues();
if (issues.length > 0) {
console.log('Payment attention required:', issues);
}getVersion()
Returns the SDK version.
Returns: string
Example:
const version = window.sesamy.getVersion();
console.log('SDK version:', version);clearCache()
Clears the SDK cache.
Example:
window.sesamy.clearCache();log()
Logs messages to console (only when debug mode is enabled).
Parameters:
message(string)
Example:
window.sesamy.log('Testing checkout process');Debug mode can be enabled via:
- URL parameter:
?sesamy-debug=true - Local storage:
localStorage.debug = true
Analytics
analytics.track()
Tracks custom events.
Parameters:
eventName(string)properties(object, optional)
Returns: Promise<void>
Example:
await window.sesamy.analytics.track('article_read', {
articleId: 'article_123',
category: 'technology',
readTime: 120,
});Browser Detection
browser.detectAdblock()
Detects if an ad blocker is enabled.
Returns: Promise<boolean>
Example:
const hasAdblock = await window.sesamy.browser.detectAdblock();
if (hasAdblock) {
console.log('Ad blocker detected');
}browser.isInAppBrowser()
Detects if running in an in-app browser.
Returns: boolean
Example:
const isInApp = window.sesamy.browser.isInAppBrowser();browser.isIncognito()
Detects if browser is in incognito/private mode.
Returns: Promise<boolean>
Example:
const isIncognito = await window.sesamy.browser.isIncognito();Events
The SDK emits several events that you can listen to:
sesamyJsReady
Emitted when the SDK is initialized and ready.
window.addEventListener('sesamyJsReady', () => {
console.log('Sesamy SDK is ready');
});sesamyJsAuthenticated
Emitted when user authenticates. Call preventDefault() to prevent auto-refresh.
window.addEventListener('sesamyJsAuthenticated', (event) => {
event.preventDefault();
console.log('User authenticated');
});sesamyJsLogout
Emitted when user logs out.
window.addEventListener('sesamyJsLogout', () => {
console.log('User logged out');
});sesamyJsClearCache
Emitted when cache is cleared.
window.addEventListener('sesamyJsClearCache', () => {
console.log('Cache cleared');
});sesamyJsPurchase
Emitted after a purchase is completed.
window.addEventListener('sesamyJsPurchase', (event) => {
console.log('Purchase completed:', event.detail.itemSrc);
});URL Triggers
The SDK can respond to query parameters:
?sesamy-refresh
Clears cache and emits sesamyJsClearCache event.
?sesamy-user=email@example.com
Validates user email, logs out and re-authenticates if mismatch.
?sesamy-login
Validates user is authenticated, initiates login if not.
?sesamy-purchase
Triggers sesamyJsPurchase event.
?sesamy-token=<token>
Parses token and adds content permissions.
?sesamy-debug=true
Enables debug logging.
Custom HTML Attributes
sesamy-visibility
Controls element visibility based on authentication state.
<div sesamy-visibility="logged-in">Welcome back!</div>
<div sesamy-visibility="not-logged-in">Please log in</div>sesamy-link
Attaches click handlers for common actions.
<button sesamy-link="login">Log In</button>
<button sesamy-link="logout">Log Out</button>
<button sesamy-link="account">My Account</button>TypeScript Support
The SDK includes comprehensive TypeScript definitions:
import type {
SesamyAPI,
Config,
Profile,
Entitlement,
Contract,
Checkout,
} from '@sesamy/sesamy-js';
// Type-safe API access
const sesamy: SesamyAPI = window.sesamy;
const profile: Profile = await sesamy.profile.get();Cross-Domain Authentication
When your app domain differs from the auth domain's top-level domain:
- Mobile browsers (Safari/iOS/Android): Automatically uses popup login
- Desktop browsers: Uses redirect login
Example:
- App:
app.example.com, Auth:auth.different.com- Mobile: Popup login
- Desktop: Redirect login
Best Practices
- Wait for Ready Event: Always wait for
sesamyJsReadybefore using the API - Error Handling: Wrap API calls in try-catch blocks
- Token Management: Use
getTokenSilently()for API calls - Smart Login: Use
login()for best UX across browsers - Event Listeners: Listen to SDK events for reactive UI updates
- Debug Mode: Enable during development for detailed logging
- Cache Management: Clear cache when needed with URL trigger or API
Resources
- API Reference - Explore all available endpoints
- Authentication - Learn about authentication methods
- Package Documentation - Full README
- API Documentation - REST API reference
- Examples - View code examples
Advanced Features
Request Interceptors
client.interceptors.request.use((config) => {
console.log('Making request:', config.url);
return config;
});Response Interceptors
client.interceptors.response.use(
(response) => {
console.log('Response received:', response.status);
return response;
},
(error) => {
console.error('Request failed:', error);
throw error;
}
);Token Management
// Set access token
client.setAccessToken('new_access_token');
// Get current token
const token = client.getAccessToken();
// Clear token
client.clearAccessToken();Testing
Mocking
import { SesamyClient } from '@sesamy/client';
import { jest } from '@jest/globals';
jest.mock('@sesamy/client');
const mockClient = new SesamyClient({ ... }) as jest.Mocked<SesamyClient>;
mockClient.getProfile.mockResolvedValue({
id: 'user_123',
email: 'test@example.com'
});Next Steps
- API Reference - Explore all available endpoints
- Authentication - Learn about authentication methods
- Package Documentation - Full README
- API Documentation - REST API reference
- Examples - View code examples