Content Management
Content management allows you to discover, analyze, and control access to content on your pages. The SDK automatically finds content based on configured selectors and provides methods to check access and unlock premium content.
📘 See Also: Content Metadata & Fallback Mechanism for detailed information about meta tags, element attributes, and best practices.
How It Works
- Configuration - Define content selectors in your config or via Scripts Host
- Discovery - SDK scans the page for matching content elements
- Metadata Extraction - Extracts metadata using a multi-layered fallback approach (configured selectors → element attributes → meta tags)
- Access Control - Integrates with entitlements to control access
- Content Unlocking - Fetches and decrypts premium content when authorized
Methods
content.list()
Discover all content items on the current page.
Returns: ContentItem[]
const articles = window.sesamy.content.list();
articles.forEach((article) => {
console.log('Found:', article.title);
console.log('Price:', article.price);
console.log('Requires:', article.pass);
});content.get()
Get a specific content item by selector or element.
Parameters: elementOrSelector (HTMLElement | string)
Returns: ContentItem | null
const article = window.sesamy.content.get('article.featured');
if (article) {
console.log('Article:', article.title);
}content.hasAccess()
Check if user has access to content.
Parameters: elementOrSelector (HTMLElement | string)
Returns: Promise<Entitlement | boolean | null>
const result = await window.sesamy.content.hasAccess('.premium-article');
if (result) {
if (typeof result === 'boolean') {
// User has access (public or logged-in content)
console.log('Access granted');
} else {
// User has access via entitlement
console.log('Access granted via:', result.type);
}
} else {
// User doesn't have access - show paywall
const article = window.sesamy.content.get('.premium-article');
showPaywall(article.paywallUrl);
}The function returns:
- An
Entitlementobject if the user has entitlement-based access trueif the user has access (public content or authenticated for login-only content)nullif the user doesn't have access
content.unlock()
Unlock and retrieve premium content.
Parameters: elementOrSelector (HTMLElement | string)
Returns: Promise<string | null>
const unlockedHTML = await window.sesamy.content.unlock('#article');
if (unlockedHTML) {
document.querySelector('#content').innerHTML = unlockedHTML;
} else {
// User doesn't have access
showPaywall();
}Configuration
Configure content selectors to define how the SDK discovers and extracts metadata:
{
content: [
{
type: 'article',
path: '/articles', // Optional: only match on this path
pass: 'premium', // Optional: required pass
price: {
amount: 9.99,
currency: 'USD',
},
enablePaywallSettingsUrlFallback: false, // Optional: Fallback to <sesamy-paywall settings-url>
selectors: {
article: { selector: 'article.content' },
title: { selector: 'h1', attribute: 'textContent' },
image: { selector: 'img', attribute: 'src' },
author: { selector: '.author', attribute: 'textContent' },
paywallUrl: { selector: 'a.paywall-link', attribute: 'href' },
// ... more selectors
},
},
];
}Pass Collection
The pass attribute is collected from the article element and all its ancestor elements up to the document root. This allows for flexible, hierarchical access control:
<body pass="https://example.com/site-wide">
<main pass="https://example.com/members">
<section pass="https://example.com/premium">
<sesamy-article pass="https://example.com/article-123">
<!-- All four passes are collected and checked -->
</sesamy-article>
</section>
</main>
</body>How It Works
When retrieving content with content.get() or content.list(), the SDK:
- Starts at the article element
- Collects any
passattributes - Traverses up through parent elements
- Collects all
passattributes from ancestors - Splits comma-separated values
- Removes duplicates
- Combines into a single comma-separated string
Use Cases
Section-based access:
<section class="members-only" pass="https://example.com/members">
<sesamy-article>Article 1</sesamy-article>
<sesamy-article>Article 2</sesamy-article>
<!-- Both articles inherit the members pass -->
</section>Dynamic passes from CMS:
<!-- Lab plugin adds passes dynamically based on tags -->
<section class="article" pass="https://example.com/tag1,https://example.com/tag2">
<sesamy-article>
<!-- Inherits tag-based passes -->
</sesamy-article>
</section>Multiple access levels:
<article pass="https://example.com/basic">
<div pass="https://example.com/premium">
<sesamy-article>
<!-- Requires either basic OR premium pass -->
</sesamy-article>
</div>
</article>Best Practices
- Place site-wide passes on
<body>or high-level containers - Use section/category passes on section elements
- Use article-specific passes on
<sesamy-article>elements - Let plugins like Labrador Tags handle dynamic passes
Common Patterns
Content List with Access Check
window.addEventListener('sesamyJsReady', async () => {
const articles = window.sesamy.content.list();
for (const article of articles) {
const entitlement = await window.sesamy.content.hasAccess(article.element);
if (!entitlement) {
// Add paywall overlay
const overlay = document.createElement('div');
overlay.className = 'paywall-overlay';
overlay.innerHTML = `
<h3>Premium Content</h3>
<p>Subscribe to read this article</p>
<button onclick="location.href='${article.paywallUrl}'">
Subscribe Now
</button>
`;
article.element.appendChild(overlay);
}
}
});Dynamic Content Unlocking
async function unlockArticle(selector) {
const entitlement = await window.sesamy.content.hasAccess(selector);
if (entitlement) {
const content = await window.sesamy.content.unlock(selector);
if (content) {
document.querySelector('.article-body').innerHTML = content;
document.querySelector('.paywall').remove();
// Track unlock event
await window.sesamy.analytics.track('content_unlocked', {
contentId: entitlement.publisherContentId,
});
}
} else {
// Show paywall with article info
const article = window.sesamy.content.get(selector);
showPaywall({
title: article.title,
price: article.price,
paywallUrl: article.paywallUrl,
});
}
}Paywall with Purchase Flow
window.addEventListener('sesamyJsReady', async () => {
const article = window.sesamy.content.get('article.main');
const access = await window.sesamy.content.hasAccess(article.element);
if (!access) {
document.querySelector('#purchase-btn').addEventListener('click', async () => {
const checkout = await window.sesamy.checkouts.create({
items: [
{
url: article.url,
price: article.price.amount,
currency: article.price.currency,
},
],
redirectUrl: window.location.href,
});
window.location.href = checkout.checkoutUrl;
});
}
});Next Steps
- Content Metadata & Fallback Mechanism - Learn about meta tags, attributes, and best practices
- API Reference - Use entitlements with content
- Authentication - Manage user sessions
- Scripts Host - Automatic configuration