Skip to main content

Events

The SDK emits typed events throughout the reader's lifecycle. Subscribe to them to trigger analytics, update your UI, or integrate with third-party tools.


Subscribing to events

const cc = ContentCredits.init({ apiKey: 'pub_YOUR_KEY', ... });

// Subscribe — returns an unsubscribe function
const unsubscribe = cc.on('ready', ({ state }) => {
console.log('SDK ready, state:', state);
});

// Unsubscribe
unsubscribe();

// Or unsubscribe by handler reference
const handler = ({ user }) => console.log('Logged in:', user.email);
cc.on('auth:login', handler);
cc.off('auth:login', handler);

All events

ready

Fired once when the SDK has finished initialising (access check complete, UI rendered).

cc.on('ready', ({ state }) => {
// state: SDKState — the full current state snapshot
console.log('Has access:', state.hasAccess);
console.log('User:', state.user);
});

auth:login

Fired when the reader successfully authenticates.

cc.on('auth:login', ({ user }) => {
// user.firstName, user.lastName, user.email, user.credits
console.log(`Welcome, ${user.firstName}!`);
analytics.identify(user._id, { email: user.email });
});

auth:logout

Fired when the reader's session ends (token expiry or explicit sign-out).

cc.on('auth:logout', () => {
console.log('Reader logged out');
});

paywall:shown

Fired when the paywall overlay appears (reader doesn't have access).

cc.on('paywall:shown', () => {
analytics.track('paywall_shown', { url: window.location.href });
});

paywall:hidden

Fired when the paywall overlay is removed and content is revealed. This is effectively the "article unlocked" event.

cc.on('paywall:hidden', () => {
analytics.track('article_unlocked');
// Same as the onAccessGranted callback in config
});

article:purchased

Fired when the reader successfully purchases access to the current article.

cc.on('article:purchased', ({ creditsSpent, remainingBalance }) => {
console.log(`Spent ${creditsSpent} credits. Balance: ${remainingBalance}`);
analytics.track('article_purchased', { creditsSpent });
});

credits:insufficient

Fired when the reader tries to purchase but doesn't have enough credits.

cc.on('credits:insufficient', ({ required, available }) => {
console.log(`Need ${required} credits, only have ${available}`);
// The SDK shows a "Top up" button automatically
});

comment:posted

Fired when the reader successfully posts a comment.

cc.on('comment:posted', ({ comment }) => {
console.log('New comment:', comment.content, 'by', comment.author?.firstName);
});

comment:liked

Fired when the reader likes or unlikes a comment.

cc.on('comment:liked', ({ commentId, hasLiked }) => {
console.log(commentId, hasLiked ? '→ liked' : '→ unliked');
});

comment:deleted

Fired when the reader deletes one of their comments.

cc.on('comment:deleted', ({ commentId }) => {
console.log('Deleted:', commentId);
});

error

Fired when the SDK encounters a non-fatal error (e.g. network failure, API error).

cc.on('error', ({ message, error }) => {
console.error('SDK error:', message, error);
Sentry.captureException(error);
});

Native CustomEvents

In addition to the typed event emitter, the SDK also dispatches native browser CustomEvents on document. This lets you listen without a reference to the SDK instance — useful for analytics libraries, tag managers, or iframe integrations.

Event names are prefixed with contentcredits::

document.addEventListener('contentcredits:auth:login', (e) => {
console.log('Reader logged in:', e.detail);
});

document.addEventListener('contentcredits:paywall:hidden', () => {
dataLayer.push({ event: 'article_unlocked' });
});

All events listed above are available as both SDK emitter events and native CustomEvents.


Analytics integration example

const cc = ContentCredits.init({
apiKey: 'pub_YOUR_KEY',
contentSelector: '#premium-content',
});

cc.on('ready', ({ state }) => {
if (state.hasAccess) {
analytics.track('article_viewed_with_access');
} else {
analytics.track('article_viewed_paywalled');
}
});

cc.on('article:purchased', ({ creditsSpent }) => {
analytics.track('purchase', { value: creditsSpent, currency: 'credits' });
});

cc.on('auth:login', ({ user }) => {
analytics.identify(user._id);
});