← Back to Docs
Events and Callbacks
The widget dispatches custom DOM events on document. Listen for analytics, moderation alerts, or custom UI logic.
Listening to Events
document.addEventListener('threadline:comment:posted', (e) => {
const detail = (e as CustomEvent).detail;
console.log('New comment:', detail.commentId, 'by', detail.authorName);
// Push to your analytics
if (typeof gtag === 'function') {
gtag('event', 'comment_posted', { page_id: detail.pageId });
}
});
document.addEventListener('threadline:error', (e) => {
const { code, message } = (e as CustomEvent).detail;
console.error(`Threadline error [${code}]: ${message}`);
});Event Reference
threadline:readyPayload:
{ widgetVersion: string }Fired when the widget has finished loading and is ready to interact with.
threadline:comment:postedPayload:
{ commentId: string, authorName: string, pageId: string }Fired after a comment is successfully submitted. Does not fire for blocked comments.
threadline:comment:deletedPayload:
{ commentId: string, pageId: string }Fired when a comment is deleted by the author or a moderator.
threadline:comment:flaggedPayload:
{ commentId: string, reason: string, pageId: string }Fired when a visitor flags a comment. Reason: "spam", "offensive", or "other".
threadline:errorPayload:
{ code: string, message: string }Fired on error. Codes: "SITE_NOT_FOUND", "RATE_LIMITED", "NETWORK_ERROR", "AUTH_FAILED".
Example use cases
Common patterns using the DOM events above. For live updates inside the open widget, socket events also exist (new_comment, reaction_updated, and related) - those power real-time UI and are separate from the document CustomEvents listed here.
Analytics on comment posted
document.addEventListener('threadline:comment:posted', (e) => {
const { commentId, authorName, pageId } = (e as CustomEvent).detail;
analytics.track('Comment Posted', { commentId, authorName, pageId });
});Toast on error
document.addEventListener('threadline:error', (e) => {
const { code, message } = (e as CustomEvent).detail;
showToast(`${code}: ${message}`, { type: 'error' });
});Open login on AUTH_FAILED
document.addEventListener('threadline:error', (e) => {
const { code } = (e as CustomEvent).detail;
if (code === 'AUTH_FAILED') {
window.location.href = '/login?next=' + encodeURIComponent(location.pathname);
}
});Sync comment count to page header
const el = document.querySelector('#comment-count');
let count = Number(el?.textContent || 0);
document.addEventListener('threadline:comment:posted', () => {
count += 1;
if (el) el.textContent = String(count);
});
document.addEventListener('threadline:comment:deleted', () => {
count = Math.max(0, count - 1);
if (el) el.textContent = String(count);
});