Embedding Discourse Comments via Javascript


(Robin Ward) #1

Discourse has the ability to embed the comments from a topic in a remote site using a Javascript API that creates an IFRAME. For an example of this in action, check out Coding Horror’s blog. The blog is run via Ghost but the comments are embedded from his Discourse forum.

One important thing to note with this setup is that users have to navigate to your forum to post replies. This is intentional, as we feel that the posting interface on a Discourse forum is currently much richer than what we could embed via Javascript.

This guide will show how to set up comment embedding on your own blog or web site.

How it works

In Discourse, a topic is made up of many posts. When you are embedding Discourse on another site, you are linking a document (blog entry, HTML page, etc.) with a single topic. When people post in that topic, their comments will automatically show up on the page you embedded it in.

You have the choice to have Discourse create the topics automatically when a new embedding is found, or you can create the topics yourself in advance.

Configuring Discourse for Embedding (simple setup)

The following setup will embed a comment feed on a page on a fake blog URL of http://example.com/blog/entry-123.html, from a discourse forum running at http://discourse.example.com.

  1. Visit Admin > Customize > Embedding on your Discourse install.

  2. Create at least one embeddable host. This should be the hostname (domain) where you want to embed your comments. In this case the host is example.com – note the lack of http:// and path.

    • Class Name is a class name that will be attached every time your iframe is rendered. You can use it for styling purposes.

    • Path Whitelist allows you to specify the paths on the remote host that would accept your embed.

    • Post to Category - if you supply a category alongside the host you are entering, posts imported from that host will automatically end up in that category. Different hosts can post to different categories.

  3. Fill in the name of a user on your discourse who will create topics in the Embed by Username field. Let’s assume our discourse has a user called eviltrout, so the value is eviltrout.

  4. Insert the following HTML on the web page at http://example.com/blog/entry-123.html

<div id='discourse-comments'></div>

<script type="text/javascript">
  DiscourseEmbed = { discourseUrl: 'http://discourse.example.com/',
                     discourseEmbedUrl: 'http://example.com/blog/entry-123.html' };

  (function() {
    var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;
    d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(d);

The configurable parts of the snippet are in the DiscourseEmbed object. discourseUrl is the full path to the base of your discourse, including the trailing slash. The discourseEmbedUrl is the document that is currently embedding a comment feed.

If you set this up correctly, the first time you visit http://example.com/blog/entry-123.html it will try to load comments for the blog post. Since there are none, it will tell the Discourse forum to create a new topic in the background. A new topic will be created by eviltrout and the contents of the first post will be crawled from your blog and the text will be extracted automatically.

Once the new topic is created, users can post on it, and their comments will automatically be displayed the next time http://example.com/blog/entry-123.html is visited.

Embedding on more than one page

In the above example we hard coded our http://example.com/blog/entry-123.html URL when embedding the snippet of Javascript. This usually won’t be enough as many sites have many pages that are generated automatically. For example on a blog each entry typically gets its own page. To support this, put the same snippet on each page you want to display comments on, but replace the value passed to discourseEmbedUrl with the current page’s URL. On my blog, I use the following value for discourseEmbedUrl: 'http://eviltrout.com<%= current_page.url %>' – as new blog pages are created, new topics will be created for them automatically on Discourse.

Styling your Embedded content

If you are running the latest build of Discourse (or 1.4.0beta9 or 1.4.0 stable once it is released) you have the ability to add a stylesheet for your embedded comments. Visit Admin > Customize > CSS/HTML > Embedded CSS and you can add a custom stylesheet that will be served up with your embedded comments. By default we think the layout looks nice on a white background, but if your site has a unique layout you’ll want to style it yourself.

(Optional) Adding a Feed for Polling

As mentioned above, Discourse will automatically crawl any site it is embedded on. However, sometimes HTML can be hard to parse and it might not extract the contents of your posts correctly. Many blogs and web sites support RSS/Atom feeds for syndication, and Discourse can use this to extract the content of your blog posts more accurately.

If you have a RSS or Atom feed set up on the site you are embedding Discourse into, you can configure Discourse to extract the content of posts from there by enabling the setting feed polling enabled and then providing the full URL to the feed in the feed polling url setting.

(Alternate Configuration) Linking to existing topics

Some people prefer to not have Discourse create topics for them automatically on their forums. They’d like to create the topics themselves, then simply tell their embedding code what topic they want to associate with. You can do this by slightly changing your embedding code:

<div id='discourse-comments'></div>

<script type="text/javascript">
  DiscourseEmbed = { discourseUrl: 'http://discourse.example.com/',
                     topicId: 12345 };

  (function() {
    var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;
    d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(d);

The only difference here is we’ve replaced discourseEmbedUrl with the id of a topic from Discourse. If you do this, no topic will be created and the comments from that topic will automatically be displayed.


The most common issue users have when embedding Discourse is setting the correct value for the embeddable hosts you added. Make sure to double check that it is only the domain of your site, and contains no extra slashes or invalid characters.

Discourse Embedding
Embedding forum on custom site
Discourse 1.4 Released!
Is it possible to test Discourse Embed comment on localhost?
Trouble connecting drupal and discourse
Deeply integrating Discourse into website
Using Discourse for Comments on Legacy Site
Embedded Comments iframe Height
What software you use for blog.discourse.org?
Discourse blog comments like your blog comments
Create topic when a link is clicked
Use Discourse as the comments section of a Jekyll site?
Using Discourse in a web app
Adding some parameters to topics created as blog comments
Is it possible to use Discourse as a "commenting system"?
Can be integrated with liquid templates?
WP Discourse Embed Plugin
WP Discourse Embed Plugin
Synchronising log out of discourse when logging out of WordPress
Topic as widget
New topics are not created in embedded discourse
Discourse a a comment system with React Native and Meteor
A post's TopicEmbed isn't destroyed when the post is deleted
Pages from Google search are not rendering
Controlling amount of embedded text
Embedded comments: can I troubleshoot «View full post»?
Discourse + Wordpress or GhostCMS?
Feedback needed regarding Discourse embedded versus Disqus
Flood of new topics from Embedded Discourse
Discourse topics as Dokuwiki talk pages
How do I set up Ghost to use Discourse for comments?
Multiple cors origins on hosted discourse?
WordPress / Discourse API Strategy: Get Reply Count via API Efficiently
Comment Reply Threading / Linking on the WordPress Side
Embedded comments not displayed due to X-Frame-Options DENY
What is Discourse Blog built with?
Embedding Discourse сomments with GitBook
Zendesk Article Comment in Discourse Integration
Learning Management Systems
Looking for Ruby-based CMS recommendations as a compliment to Discourse
[paid] Preference to create & embed a topic via JavaScript only when a user clicks the "Start Discussion" link
Auto-post To Discourse Forum When Post On Another Blog?
Embedding: Discussion not showing up for new posts
Failed to execute postMessage on DOMWindow: The target origin provided does not match
Imported topic via embedding will not render normally
Trying to do embedding. Hit with “The referer did not match any of the following hosts:” issue
Threaded comments when using Discourse for website comments?
Emoji are huge when embedding
The CSS for embedding Discourse does not respect the color scheme
Embedding Discourse Profile via Javascript
Embedding Topics inside Google Sites Pages
WP-discourse: comments are not pulled over
Integrating Discourse with a larger social network app?
discourseEmbed, does not match recipient window origin
Possible to add comment count (to a Ghost blog)?
How 2 websites can use one forum?
Embedding doesnt work when URL contains persian character
How can I delete or undelete topics?
Link existing forum topic to new WordPress post
Discourse WordPress plugin version 0.6.6
How to enable Discourse comments via JavaScript in Wordpress?
How to link the existing discourse comments to wordpress posts?
Force https for login URL
Editor in embedded comments
(Ben Porter) #10

Great feature! I just hooked it up and styled it for my blog. Thanks discourse team. :smiley:

(Steve) #11

Is it possible to use this method if the Discourse category is hidden from public view?

(Kane York) #12

Probably not, but it might work if all of your viewers are logged in.


I have been playing around with this functionality this on my SquareSpace company blog. I think I have found the best approach now after experimenting for a couple days, but…

A topic was created for the EmbedURL on my forum. While experimenting, I deleted this topic. Now, after setting the script up again (for a second time) on the same SquareSpace URL it directs to that deleted post. All fine and dandy, but I cannot UNDELETE this post? Any suggestions so the comments are not broken here?

(Robin Ward) #21

You should be able to undelete it on your Discourse forum if you are an admin.

(David Payette) #22

Quick question before I take the entire plunge. First of all, thanks for the great guide. I’m going to be migrating the comments and forum on my site, payetteforward.com, in the not-too-distant future. My question is: How would you suggest dealing with paginated posts? For instance, I’ll have an article at Why Does My iPhone Battery Die So Fast? Here’s The Real Fix! and then Why Does My iPhone Battery Die So Fast? Here’s The Real Fix! for page 2, /3/ for page 3 and so on. We don’t want different comments for each page in a paginated post - is there a way, using your javascript code, to avoid this?

Thanks so much for your help. Awesome stuff, guys. Keep it up.

(Robin Ward) #23

I’m not sure how you are constructing your discourseEmbedUrl but as long as it is the same for all the pages in your post you will receive the same comments.

(David Payette) #24

Thanks for following up, Robin. I’ll follow up once I’m farther along in
the transition with any subsequent questions I may have. I appreciate your
reassurances - and Discourse is amazing, so thank you.

(Damien Radtke) #25

I’m getting a “401 Unauthorized” error, but when the embeddable host is set incorrectly, it’s a 403 Forbidden. Any ideas what could be causing this?

EDIT: Dumb me. I have HTTP authentication set up on that page, which is causing the request to fail. Please ignore. :grinning:

(John ) #26

I’d like to use this functionality to direct blog visitors to a unique topic dedicated to discussing a blog post, without actually displaying comments on the blog page.

I believe this would be pretty much what BoingBoing is doing with the Wordpress plugin.

Could this be done simply by setting Maximum number of posts to embed = 0? Or would some other modifications be needed?

edit: actually, I just tried it via the console. It looks like I need Maximum number of posts to embed > 0, but it seems to have the right outcome. Anything else I might need to consider?

(Robin Ward) #27

If that works for you it sounds correct!

(Barry Parr) #28

My CMS automatically turns some characters into HTML entities. Any of the HTML entities show up in my forum headline, rather than the characters. so this headline:

First annual Half Moon Bay Fish & Fleet Festival, Sunday, Sept 27 

Shows up as:

First annual Half Moon Bay Fish &amp; Fleet Festival, Sunday, Sept 27 

… as a topic title. This is not a problem with the text of the of the body, in which the entities are translated in the the correct characters, only with the topic titles.

(John ) #30


Can I also apply styling to the embedded content from the custom CSS/HTML settings at /admin/customize/css_html?

(Jeff Atwood) #31

It’s under Admin, Customize, CSS/Html, Embedded CSS

(Jeff Atwood) #32

24 posts were split to a new topic: Embedding, but not automatically create a topic until a user chooses to comment

Embedding, but don't automatically create a topic until a user chooses to comment
Embedding, but don't automatically create a topic until a user chooses to comment
(Puneet Goel) #46

I am trying to embed comments into my middleman based blog. My discourse installation is on SSL and uses subfolder. After going through all the installation steps, I get the following error in the logs when I visit the blog page. And nothing shows up in the comments part of the blog.

Uncaught TypeError: Cannot read property 'forEach' of undefined Url: https://example.com/forum/embed/comments?embed_url=http%3A%2F%2Fmyblog.com%2Finitial-commit%2F

What could be wrong? Are embedded comments supported for a subfolder Discourse installation?

Subfolder support with Docker
(Robin Ward) #49

I just tested out embedding with a subfolder and it worked. Make sure your discourseUrl variable includes the path. For example:

discourseUrl: 'http://your-site.com/folder/'

(Guillaume Lapierre) #57

Is it possible to add the category in the DiscourseEmbed object? Something like:

  DiscourseEmbed = { discourseUrl: 'http://discourse.example.com/',
                     discourseEmbedUrl: 'http://example.com/blog/entry-123.html' 
                     discourseCategory: ['blog'] };

The category could be already existing ou created on the fly as a sub-category of the category specified in the embed configuration.

Why would this be great?
Many blogs have a category system for blog posts and this could map blog entrie’s category (categories!) to discourse ones. If automatic creation of sub-categories is not possible I still wish to have a way to specify a category as I have 3 main sections on my website (blog entries, DVD database, other media database) and this would be great to categorize them automatically.


Embedding: How to post to different categories from one site?
(Felix Freiberger) #58

I might be mistaken, but this sounds terribly insecure: Every visitor of the site could manipulate this data and miscategorize your posts or create new categories.