Website comments: public and private
The embeddable comments block is published separately from the floating support widget. In Chat, open Projects → the project → the site → Comments on your site and turn on public comments. They're off by default. Copy the code and place it where the block should appear:
<script src="https://chat.sensever.com/comments/loader.js?v=1"
data-site="PUBLIC_SITE_KEY"
data-entity-type="article"
data-entity-id="123"
data-lang="ru" async></script>data-site is the same public site key as the support widget's. data-entity-type is the entity type (for example, article, product, task): a Latin letter first, followed by Latin letters, digits, dots, underscores or hyphens, up to 64 characters. data-entity-id is a persistent ID in your system, a string of up to 255 characters, including 0, a UUID or a SKU. Escape the values when writing them into HTML attributes. The ID and type are case-sensitive; spaces in the ID aren't normalized.
The combination site_id + context_type + context_external_id uniquely identifies a Thread. The same parameters on different pages of one site open a shared discussion; a different entity or a different site gets a separate one. Don't change the ID when editing an article if you want to keep the existing conversation. Several blocks are allowed on one page. No separate div is required: the iframe appears in place of the script.
The language is set by code: en, ru, de, fr, es, it, tr; English by default. User names and messages aren't translated.
Features and access
Public reading without signing in; newest comments first, pages of 30, a button to load earlier ones.
Text up to 8000 characters, replies with a quote; the author can delete their own comment.
Posting as a guest with a given name or by signing in to Sensever in a separate window. The name and text are public. A guest name doesn't verify identity.
A posting session is limited to a specific site, origin and discussion, and lasts up to 8 hours. The
cm1token is stored in the iframe's own sessionStorage. Signing out of or revoking the Accounts session ends access; a regular Chat token doesn't replace the comments token.reCAPTCHA for guests uses the site's existing setting; request and posting limits apply independently of it.
The owner and administrators see discussions and delete comments in the project settings. Turning comments off closes public reading and writing but keeps the history and moderator access.
The visible block updates by polling every 10 seconds. It isn't WebSocket. Attachments, reactions, pre-moderation and notifications to comment followers aren't included in this block yet.
API and a single storage
The block uses the existing threads(kind=context) and messages(thread_id,seq), standard sequence allocation, idempotency, replies, soft delete, projections and the outbox. There's no separate copy of messages. Resending with the same client_message_id doesn't create a duplicate.
Visitors get a narrow permission through comment_sessions rather than being added to thread_members: there's no mass unread recount for every reader and no 50-visitor limit. The persistent side of the discussion is the project. Existing private/context Threads don't become public automatically: a match with a discussion without embedded_comments=true returns 409.
Reading doesn't create a Thread. It's created when a guest or Accounts posting session is obtained. Throughput guarantees for millions of concurrent readers require a separate load test; this implementation doesn't claim them.
Public endpoints under /api/comments:
GET /messages:key,origin,context_type,context_external_id, optionallybefore(a seq string). Returnsmessages,has_more,next_before,name. Bearercm1is optional for reading; with it, flags for your own comments are added.POST /guest: the same four fields,name,captcha_token; returnstoken.POST /messages: Bearercm1; the same fields plustext,client_message_id(UUID), optionallyreply_to_seq.DELETE /messages/{seq}: Bearercm1; the same entity fields in the JSON; you can delete only your own comment.
The owner/administrator uses regular personal Chat authorization:
PUT /api/v1/projects/{tenant}/sites/{site}/comments, JSON{"enabled":true}.GET /api/v1/projects/{tenant}/comments, optionallybefore(a discussion ID).GET /api/v1/projects/{tenant}/comments/{thread}, optionallybefore(seq).DELETE /api/v1/projects/{tenant}/comments/{thread}/{seq}.
chat:comments-cleanup deletes up to 10,000 expired tokens per run; a timer runs the cleanup once a minute. This cleanup doesn't delete history or authors.
Commentaires