FastComments.com

Customizations and Configuration

Context

Here you will find in-depth documentation on each of the features and settings that the comment widget supports.

This documentation will cover core concepts, and will go deep into each area of functionality, with how-tos and common gotchas.

Code examples will be provided, with relevant lines highlighted. Screenshots of configuration pages will be provided where applicable.

The code examples will use our vanilla JavaScript library, however the configuration options use the exact same names for all versions of the comment widget (React, Vue, etc).

Most configuration and features outlined in this guide do not require writing any code.

Rendering The Same Comments on Different Pages Internal Link

Since the urlId parameter allows us to define which page, or id, the comments are tied to, we can simply set urlId to the same value on those pages.

The Same Comments on Multiple Pages
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "urlId": "https://example.com/source-page"
8});
9</script>
10

Custom Fonts Internal Link

FastComments is designed to be customized, and the font our widgets use is no exception.

By default, FastComments uses the system font stack to look as good as possible on a wide range of devices.

To define your own fonts, see the Custom CSS documentation.

There you will find a way to define custom CSS, which will allow you to define your desired fonts.

How to Define The Font

To override the font, we recommend you define your CSS using the .fast-comments, textarea selectors. For example:

Custom External Font Example
Copy CopyRun External Link
1
2@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap');
3.fast-comments, textarea {
4 font-family: 'Roboto', sans-serif;
5}
6

Supporting Dark Backgrounds (Dark Mode) Internal Link

By default, the FastComments comment widget will automatically detect dark mode on most sites.

When dark mode is detected, FastComments will switch from black text on white backgrounds to white text on a black background. Images will also change.

On page load, the widget will try to determine how dark the background of the page is behind the comment widget. This means that the page could have a white background, but if you put the comment widget inside a container with a black background, dark mode should still automatically be enabled to make the comments readable.

However, the detection mechanism, which relies on determining "luminance", may not enable dark-mode when you want to. To forcefully enable it, set the hasDarkBackground flag to true as follows:

Force Dark Background Mode
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "hasDarkBackground": true
8});
9</script>
10

Linking from Comments to Pages Internal Link

When sending notification emails, or rendering comments in user interfaces like the moderation page, it's helpful to be able to link from the comment to the page it's on.

If URL ID isn't always an ID, then we have to store the URL some place else. That's what the "url" property is for, defined as follows.

Defining a Custom URL
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "url": "https://example.com/article-5"
8});
9</script>
10

A common use case is tying the comment thread to an identifier, like an article, and then linking back to a particular page, for example:

Defining Custom URL and URL IDs together
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "url": "https://example.com/article-5",
8 "urlId": "article-5"
9});
10</script>
11

The URL does not get cleaned of common marketing parameters. By default, whatever the current page URL is, is the URL stored with the comment.

Determining Which Page to Render Internal Link

When fetching and rendering comments, the comment widget needs to know which page to start on. By default, it starts with the first page, only rendering that page.

If desired, the exact page to be rendered can be passed to the comment widget as the setting startingPage.

Specifying The Page to Render
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "startingPage": 1
8});
9</script>
10

Note that pages numbers start from zero, so the above example renders the second page.

Switching Comment Threads Without Reloading The Page Internal Link

We've covered how urlId is the page or article id the comments are tied to.

Also, to recap, if not defined the urlId will default to the current page URL.

What about SPAs, or Single-Page-Applications, where the page or content the comments are tied to changes dynamically without a fresh page reload?

Angular, React, Vue, etc

With our libraries such as Angular and React, simply updating the urlId property passed to the widget will cause the comment widget to refresh. You can see this in action for the React app, for example, here.

VanillaJS

If you're using the VanillaJS library it is slightly more complicated as there isn't a framework like Angular or React to handle the data binding or state propagation.

When you instantiate the VanillaJS widget, it returns some functions which can be called to update it.

Here's a functional example where we change the page hash and update the comment widget:

Switching Page Hash Example
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<button id="change-page"></button>
4<div id="fastcomments-widget"></div>
5<script>
6 (function fastCommentsMain() {
7 let config = {
8 tenantId: 'demo'
9 };
10 let instance = window.FastCommentsUI(document.getElementById('fastcomments-widget'), config);
11
12 let page = '#page-1';
13 function getNextPage() {
14 if (page === '#page-1') {
15 return '#page-2';
16 } else {
17 return '#page-1';
18 }
19 }
20
21 let button = document.getElementById('change-page');
22 function nextPage() {
23 page = getNextPage();
24 button.innerText = 'Go to ' + getNextPage();
25 window.location.hash = page;
26 let locationString = window.location.toString();
27
28 config.url = locationString; // We update url, too, so notifications can link back to the right page
29 config.urlId = locationString;
30
31 instance.update(config);
32 }
33 nextPage();
34 button.addEventListener('click', nextPage);
35 })();
36</script>
37

Disable Image Redirect Internal Link

By default, FastComments allows users to upload images. When a user clicks that image, FastComments will, by default, open a new tab to show that image in full. Setting this flag to true disables this behavior:

Disable Image Redirect
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "disableImageRedirect": true
8});
9</script>
10

If you don't plan to capture the image click yourself (see onImageClicked), we recommend this is combined with some styling to remove the appearance that the image can be clicked.

Highlighting New Comments Internal Link

FastComments provides several ways to highlight new comments.

First and foremost, by default comments that triggered an in-app notification (replies, replies in same thread, or comments on a page that you're subscribed to), will automatically be highlighted with the user's avatar glowing slightly. The color can be customized via CSS using the is-unread class.

Comments posted in the last 24 hours have a 24hr class applied that can be used for styling.

Finally, any new live comments that show up in the user's session will be highlighted for several seconds via an animation. This is done via the is-live CSS class and can be customized as well.

Email Templates Internal Link

Emails sent from FastComments to your customers can be customized. The template, logic, and translations can all be changed. Text can be customized per-locale, and styling can even be changed per-domain. Learn more about custom email templates here.

Enabling Infinite Scrolling Internal Link

By default, the FastComments widget will resize itself vertically to fit all visible comments. Pagination is achieved via a "View Next" button at the end of the current page, as we have found this to be the interaction that feels the nicest for most users.

However, there are some cases where infinite scrolling is preferred. For example, we use this feature in our Stream Chat product.

We can hide the "View Next" buttons and switch to infinite scrolling by setting the enableInfiniteScrolling flag to true:

Enabling Infinite Scrolling
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "enableInfiniteScrolling": true
8});
9</script>
10

This also requires the addition of custom CSS to be added. Add custom CSS for the .comments selector to enable scrolling, for example:

Enable Infinite Scrolling
Copy CopyRun External Link
1
2.comments {
3 max-height: 500px;
4 overflow-y: auto;
5}
6

A full working example would be:

Enabling Infinite Scrolling
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "enableInfiniteScrolling": true,
8 "customCSS": ".comments { max-height: 500px; overflow-y: auto; }"
9});
10</script>
11

In the above example we use the customCSS property, however it is suggested the Widget Configuration UI is used instead for performance reasons. See the Custom CSS documentation.

Rendering All Comments at Once - Disable Pagination Internal Link

To disable pagination, and just render all comments at once, set startingPage to -1.

Render All Comments
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "startingPage": -1
8});
9</script>
10

Prevent New Top-Level Comments Internal Link

Setting noNewRootComments to true will cause the widget to hide the root reply area, but still allow users to reply to child comments. You could, for example, set this conditionally on page load to only allow some users to leave top-level comments.

Prevent New Root Comments
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "noNewRootComments": true
8});
9</script>
10

Single Sign On (SSO) Overview Internal Link

SSO, or single-sign-on, is a set of conventions used to allow you or your users use FastComments without having to create another account.

Assuming you don't allow anonymous commenting, an account is required to comment with FastComments. We make this sign up process very easy - the user just leaves their email when they comment. However, we understand that even that is extra friction some sites want to avoid.

We can reduce that friction by only having one login flow for your entire site.

How do I get it?

All account types currently get access to SSO. However, the max number of SSO users will vary depending on your package. As with other features, the Pro plans and higher provide direct development support.

Let's compare the options, and then go into details of each.

User and Comment Migrations

When migrating from a platform with SSO like Disqus, you will already have users and their comments.

Comments are imported as part of your migration, either by the API, our Import UI, or customer support. The Import UI is preferred if it supports the platform you are migrating from, as it incorporates error handling, avatar and media extraction and uploads, and a batch job monitoring system.

The users themselves are added automatically when viewing comment threads for the first time. Alternatively, they can be pre-added via the API, but this work does not have many advantages.

If comments are imported, and SSO users are not added manually via the API, then comments will automatically be migrated to the user's account the first time it is created when they view any comment thread. They will then be able to manage, edit, and delete the comments they originally wrote.

The automatic migration is done via email or username. Some platforms do not provide emails on export, like Disqus, so we fall back to username in this case.

  • As long as you pass a matching username, and an email in the SSO payload, we will add the email to the individual comment objects so that notifications and mentions work.

If it is desired to import your comments and users at once, work with support to migrate the comments over to the users' respective accounts after users are imported via the API.

So to summarize the easiest path to take for the migration is:

  1. Import comments.
    1. Avatars and other media is migrated automatically if using the Import UI in Manage Data -> Imports.
  2. Setup Secure or Simple SSO.
  3. Let the migration happen per-user automatically when they log in for the first time.
    1. This usually adds less than a second to the page load time if the user has less than 50k comments.

WordPress Users

If you're using our WordPress plugin then there is no code to write! Simply go to the plugin's Admin page, click SSO Settings, and then Enable.

This will take you to a single-button click wizard which will create your API key, send it over to your WordPress install and turn SSO on. We've consolidated this into a single button click for you.

Note that if you are installing the plugin for the first time you will have to follow up the setup process before you see the admin page with the SSO Settings button.

WordPress SSO - Moderators

Note that currently for the "Moderator" badge to show next to your moderators when they comment with the FastComments WordPress plugin, they must also be added as a Moderator in the FastComments dashboard, and have their email verified.

Custom Integrations

For Custom integrations, there are two options.

Option One - Secure SSO

With Secure SSO, FastComments knows that the user commenting, voting, and reading comments is a real user on your site.

As long as you create a valid payload, the user will always have a seamless commenting experience.

With Secure SSO, the SSO payload is created server-side using HMAC authentication and then passed to the widget on the client.

With Secure SSO, the user's account is completely separate from the rest of the FastComments user-base. This means if we have two partners Company A and Company B, each can have an SSO user with the username "Bob".

Requirements

  • Some basic knowledge around backend development.
  • Some basic knowledge around dealing with secret API keys.
  • Some basic knowledge around API development or server-side rendering.

Pros

  • Secure.
  • Seamless commenting experience.

Cons

  • Requires backend development.

Updating User Data

With Secure SSO, each time you pass the sso user payload, we will update their user with the latest information. For example, if the user has a username X, and you pass Y in the SSO payload, their username will become Y.

If you want to remove values using this approach then set them to null (not undefined).

Secure SSO API

We also provide an API for interacting with the SSO users. See the docs.

Note that when using Secure SSO, users are automatically created behind the scenes on page load. You do not have to bulk import your users.

Option Two - Simple SSO

The alternative to Secure SSO is to simply pass the user information to the commenting widget.

Providing an email with Simple SSO is not required, however without this their comments will show as "Unverified".

Note! As of early 2022 usernames with Simple SSO do not need to be unique across all of FastComments.com.

Ideally, Simple SSO should only be picked when developing on a platform that doesn't provide backend access.

Requirements

  • Some basic knowledge around client-side development.
  • Have to know at least the user's email.

Pros

  • Simple.
  • All activity still gets verified.
  • The user never enters their username or email.

Cons

  • Less secure than Secure SSO as the client side payload could be crafted to become any user.

Simple SSO API

Users automatically created via the Simple SSO flow are stored as SSOUser objects. They can be accessed and managed via the SSOUser API. See the docs.

Custom Integrations - Simple Single Sign On (SSO) Internal Link

With Simple SSO, we can provide the commenting widget with information about the user so that they don't have to enter their username or email to comment.

We can configure Simple SSO as follows:

Simple SSO
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "simpleSSO": {
8 "username": "Bob",
9 "email": "bob@example.com",
10 "avatar": "https://example.com/bob.png",
11 "websiteUrl": "https://example.com/profiles/bob",
12 "displayName": "Bob's Name",
13 "displayLabel": "VIP User",
14 "loginURL": "https://example.com/login",
15 "logoutURL": "https://example.com/logout"
16 }
17});
18</script>
19

The user will be logged in, and will create an SSO User behind the scenes. The user will have createdFromSimpleSSO set to true if fetched from the API.

Notes:

  • Email is the unique identifier for Simple SSO.
  • Providing an email with Simple SSO is not required, however by default their comments will show as "Unverified". If no email is provided, the user cannot be fully authenticated.
  • NEW Since Jan 2022: Usernames do not have to be unique across all of fastcomments.com
  • Simple SSO can automatically create and update SSO users, if an email is provided, and the user was not originally created from Secure SSO.

Custom Integrations - Migrating from Disqus SSO Internal Link

The biggest differences between Disqus and FastComments Secure SSO is that Disqus uses SHA1 for encryption while we use SHA256. This means migrating from Disqus is easy - change the hashing algorithm used from SHA1 to SHA256 and update the property names passed to the UI.

Custom Integrations - Migrating from Commento SSO Internal Link

Commento uses a drastically different SSO approach - they require you to have an endpoint that they invoke to authenticate the user. FastComments is the other way around - simply encode and hash the user's information using your secret key and pass it along.

Callbacks Internal Link

All libraries for the comment widget (currently Angular, React, Vue) support callbacks.

The callbacks are specified in the configuration object, with the same signature for each library.

The callbacks supported are:

  • onInit
  • onAuthenticationChange
  • onRender
  • commentCountUpdated
  • onReplySuccess
  • onVoteSuccess
  • onImageClicked
  • onOpenProfile
  • onCommentSubmitStart
  • onCommentsRendered

The exact signatures can be found in the TypeScript definitions.

Here's an example with all callbacks used:

Callbacks Examples
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5 window.FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 tenantId: 'demo',
7 onInit: function () {
8 console.log('Library started to fetch comments!');
9 },
10 onAuthenticationChange: function (eventName, userObj) {
11 console.log('User authenticated!', eventName, userObj);
12 },
13 onRender: function () {
14 console.log('Render event happened!');
15 },
16 commentCountUpdated: function (newCount) {
17 console.log('New comment count:', newCount);
18 },
19 onReplySuccess: function (comment) {
20 console.log('New comment saved!', comment);
21 },
22 onVoteSuccess: function (comment, voteId, direction, status) {
23 console.log('New vote saved!', comment, voteId, direction, status);
24 },
25 onImageClicked: function (src) {
26 console.log('Image clicked!', src);
27 },
28 onOpenProfile: function (userId) {
29 console.log('User tried to open profile', userId);
30 // return true; // return true to prevent default behavior (opening fastcomments.com user profile).
31 },
32 onCommentSubmitStart: function(comment, continueSubmitFn, cancelFn) {
33 console.log('Trying to submit comment', comment);
34 setTimeout(function() { // emulating async behavior (calling API etc).
35 if(confirm('Should submit?')) {
36 continueSubmitFn();
37 } else {
38 cancelFn('Some optional error message');
39 }
40 }, 1000);
41 },
42 onCommentsRendered: function(comments) {
43 // comments is sorted by the default sort on the page which may be Most Relevant (ex: most upvoted, etc), or Newest First
44 const topCommentInList = comments[0];
45 console.log('First Comment Rendered:', topCommentInList.avatarSrc, topCommentInList.commenterName, topCommentInList.commentHTML);
46 }
47 });
48</script>
49

Page Titles Internal Link

The current page title is associated with the specified urlId and saved for use in moderation tools.

By default, this is retrieved from document.title.

If desired, your own page title can be specified as follows:

Specifying The Page Title
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "pageTitle": "Article 42"
8});
9</script>
10

The Comment Count & Counting All Nested Replies Internal Link

The comment count displayed at the top of the comment widget can either show all "top-level" comments, meaning those replies that are replies directly to the page or article itself, or it can be a count of all nested comments.

By default, this is true - it is a count of the latter - all comments. In older versions of the comment widget the default value is false.

We can change the behavior, so that it is a count of all nested comments by setting the countAll flag to true.

Counting All Comments
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "countAll": true
8});
9</script>
10

If we wanted the count to reflect only the top level comments, we set the flag to false.

Counting Top Level Comments
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "countAll": false
8});
9</script>
10

This currently cannot be customized without code changes.

Mention Group Ids Internal Link

A list of ids to use for @mentions autocomplete. Useful when you want to prevent tagging users when they do not have intersecting groups.

When specified, only users in other groups will be provided in the autocomplete after typing the @ character.

Limit Groups for Mentions
Copy CopyRun External Link
1
2<script src="https://cdn.fastcomments.com/js/embed-v2.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5FastCommentsUI(document.getElementById('fastcomments-widget'), {
6 "tenantId": "demo",
7 "mentionGroupIds": [
8 "yxZAhjzda",
9 "QT19nXbqB"
10 ]
11});
12</script>
13