Embedding Discourse in Static Sites


Do the blog host and the forum host require the same URL? For example, I want to use foo.com for my middlemanapp blog posts, and foo.net for the forum (embedding comments into the posts at foo.com)… I don’t see any reason why this shouldn’t work – embeddable_host taking care of it – but it seems worth asking. Thank you.


Sorry to hear that. The embedding feature of Discourse works, but can be challenging to configure. We’re going to be adding specific guides to our initial install post. When you set up your Discourse forum we provide you with documentation then and it should be included.

Regarding allowing people to post inline for embedding, we have no plans to add that feature right now, although it’s conceivable we’ll add it in the future. If that feature is make or break for you, maybe consider another piece of software for your needs.

Finally, you don’t have to use RSS to create the topics if you don’t want. You can have them be created when embedded.


Nope we use iframes to get around this restriction. You can use a different host if you like!


Thanks @eviltrout for this guide – the instructions were great and the setup was very simple.


@elektromin Just wondering what else you are looking at? Discourse is certainly an amazing solution for the discussion boards, but we need ‘Comments’ as well. Inline creation and editing of comments is so natural for users, that I’m not sure they’ll get what’s happening if we shunt them over to a discussion topic on a different page (as you’ve described).

We tried Disqus, but their SSO solution was a shambles. It’s fine for blogs, but not if you want to integrate it into an app.

Anyway, if the Discourse gods are listening, ‘inline’ commenting on a page, rather than linking, would pretty much make Discourse the perfect storm!!

Thank you,


@eviltrout I’ve got the embedding comments working great although it assigns the same name to each topic. How can I set the name of the topic in the javascript that I’m embedding in the page?


hi everyone, @eviltrout

I have this set up in an interesting way, and i have one blocker you all might help with:

  1. i setup a basic discourse instant on a server i already had a website on
  2. both discourse and the blog are behind nginx, e. g. blog.mydomain.com and discourse.mydomain.com
  3. i have the embed code from this article on the blog pages so i can display the right comments on the blog page from the discourse instance.

this all works; you can see the blog embed here
and the raw forum here

also, and this is cool:

  1. i added a few python wsgi libraries and wrote a small script which sends comments to my discourse site via the discourse api; you can try it on the blog embed link above. just enter a subject and a comment, and click the button. there’s no auto refresh yet.

BUT, how do i theme that embedded code??

i tried injecting css, i tried changing colors and adding css on the discourse site itself, i tried hijacking the embed.js, i’m looking into Access-Control-Allow-Origin headers, but figured i’d check here first.

How best to add css to the embedded discourse posts in a blog?

What’s incomplete with my setup:

  1. Auto refresh of new comments
  2. better theming of embedded discourse pages
  3. better messaging to user about completed action
  4. spam control
  5. a clear invitation to participate at the main site.

Anyway, it works end to end, so that’s good.

Any help w/ the theming is much appreciated,


This is really cool, and I’ve added it to my blog and forum, but I’m having some trouble.

As you can see from the link above, it’s imported five posts from the RSS feed, and the posts which have been imported. But on the other posts, the comments are not working It just says ‘loading comments’, but doesn’t get any further.

Have I done something wrong? Thank you.

UPDATE: I don’t know if this has anything to do with it, but my logs are full of messages like this:

Job exception: Wrapped Encoding::CompatibilityError: incompatible character encodings: ASCII-8BIT and UTF-8

Job exception: incompatible character encodings: ASCII-8BIT and UTF-8

UPDATE 2: I’ve just changed the titles of a couple of my posts (replacing the £ symbol with the word ‘pound’ for example) and now they’ve all imported.


I hope you don’t mind my double posting, but this message is about something different to the prior one - specifically that of what gets imported into the forum from the blog.

Maybe I’m wrong to think this way, but to my mind, I think it would be good if there was an option to NOT have the entire post import, but instead just have the content of the first post in the topic on the blog be

"This is a companion discussion topic for the original entry at http://blahblahblah"

I think this would offer good separation, as the blog is the blog, and the forum is the forum, and if I just wanted the blog content on the forum, I would have posted it there in the first place.

Just an idea, maybe I’m wrong - I’d love to hear your thoughts on such a feature.

Thanks - and keep up the good work with Discourse, I love it!


Hi my website is generated with Hexo.io. I’m not using feed poll since it’s a documentation site with only pages not posts. After set up the embedding in discourse forum I can see some of the topics are generated but when I visit other pages I always got the following error in discourse logs:

Job exception: undefined method `empty?' for nil:NilClass

/var/www/discourse/app/models/topic_embed.rb:83:in `block in find_remote'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/nokogiri- `block in each'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/nokogiri- `upto'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/nokogiri- `each'
/var/www/discourse/app/models/topic_embed.rb:80:in `find_remote'
/var/www/discourse/app/models/topic_embed.rb:102:in `import_remote'
/var/www/discourse/lib/topic_retriever.rb:59:in `fetch_http'
/var/www/discourse/lib/topic_retriever.rb:46:in `perform_retrieve'
/var/www/discourse/lib/topic_retriever.rb:10:in `retrieve'
/var/www/discourse/app/jobs/regular/retrieve_topic.rb:16:in `execute'
/var/www/discourse/app/jobs/base.rb:153:in `block (2 levels) in perform'
current_db: default
current_hostname: forum-test.fireball-x.com
job: Jobs::RetrieveTopic
problem_db: default

  user_id: 4
  embed_url: http://docs.fireball-x.com/zh/scripting/module/
  current_site_id: default

I did quite some search but couldn’t find anything.
I’m not coming from a ruby background, could you point me to some directions that can help me find the cause of the issue? @eviltrout


Does your markup have <img>, <script> or <a> tags without src or href attributes? That’s the only thing I can think of that would cause this.


i used this code snippet and pull the discourse content to my wordpress site. But i am facing one problem here. I need to remove the target="_blank" from the “Start Discussion” and “Continue Discussion” links.

Is it possible change the anchor tag target attribute from the discourse?? or any other solution for this??



I got this error in my discourse log:

Job exception: incompatible encoding regexp match (UTF-8 regexp with ASCII-8BIT string)


/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/stringex-2.5.2/lib/stringex/localization/converter.rb:35:in `gsub!'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/stringex-2.5.2/lib/stringex/localization/converter.rb:35:in `block in cleanup_smart_punctuation!'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/stringex-2.5.2/lib/stringex/localization/converter.rb:34:in `each'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/stringex-2.5.2/lib/stringex/localization/converter.rb:34:in `cleanup_smart_punctuation!'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/stringex-2.5.2/lib/stringex/string_extensions.rb:85:in `block in convert_smart_punctuation'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/stringex-2.5.2/lib/stringex/localization.rb:86:in `instance_exec'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/stringex-2.5.2/lib/stringex/localization.rb:86:in `convert'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/stringex-2.5.2/lib/stringex/string_extensions.rb:199:in `stringex_convert'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/stringex-2.5.2/lib/stringex/string_extensions.rb:84:in `convert_smart_punctuation'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/stringex-2.5.2/lib/stringex/string_extensions.rb:126:in `remove_formatting'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/stringex-2.5.2/lib/stringex/string_extensions.rb:188:in `to_url'
/var/www/discourse/lib/slug.rb:13:in `for'
/var/www/discourse/app/models/topic.rb:662:in `title='
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/attribute_assignment.rb:45:in `public_send'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/attribute_assignment.rb:45:in `_assign_attribute'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/attribute_assignment.rb:32:in `block in assign_attributes'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/attribute_assignment.rb:26:in `each'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/attribute_assignment.rb:26:in `assign_attributes'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/core.rb:452:in `init_attributes'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/core.rb:195:in `initialize'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/inheritance.rb:30:in `new'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/inheritance.rb:30:in `new'
/var/www/discourse/lib/topic_creator.rb:17:in `create'
/var/www/discourse/lib/post_creator.rb:198:in `setup_topic'
/var/www/discourse/lib/post_creator.rb:79:in `block in create'
/var/www/discourse/lib/post_creator.rb:142:in `call'
/var/www/discourse/lib/post_creator.rb:142:in `block in transaction'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/connection_adapters/abstract/database_statements.rb:199:in `transaction'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/transactions.rb:208:in `transaction'
/var/www/discourse/lib/post_creator.rb:140:in `transaction'
/var/www/discourse/lib/post_creator.rb:78:in `create'
/var/www/discourse/app/models/topic_embed.rb:40:in `block in import'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `block in transaction'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/connection_adapters/abstract/database_statements.rb:209:in `within_new_transaction'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `transaction'
/var/www/discourse/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.9/lib/active_record/transactions.rb:208:in `transaction'
/var/www/discourse/app/models/topic_embed.rb:33:in `import'
/var/www/discourse/app/jobs/scheduled/poll_feed.rb:39:in `import_topic'
/var/www/discourse/app/jobs/scheduled/poll_feed.rb:33:in `block in import_topics'
/var/www/discourse/app/jobs/scheduled/poll_feed.rb:32:in `each'
/var/www/discourse/app/jobs/scheduled/poll_feed.rb:32:in `import_topics'
/var/www/discourse/app/jobs/scheduled/poll_feed.rb:26:in `poll_feed'
/var/www/discourse/app/jobs/scheduled/poll_feed.rb:16:in `execute'
/var/www/discourse/lib/topic_retriever.rb:42:in `perform_retrieve'
/var/www/discourse/lib/topic_retriever.rb:10:in `retrieve'
/var/www/discourse/app/jobs/regular/retrieve_topic.rb:16:in `execute'
/var/www/discourse/app/jobs/base.rb:153:in `block (2 levels) in perform'

My blog is mainly in Chinese, I’m always using utf-8 encoding, but there are other collaborators who may use some windows editor to produce non-utf8 characters. But I’m not sure how to find out.

Could you please show me how to investigate on this matter?


I have installed discourse at: http://discuss.btranslator.org and I would like to use it for comments on each item on my site, like this one:
https:// btranslator.org/translations/sq/a1fffaaafb7cc996685bceb829c053cc4f7de43d
There are a huge number of items like this, so I would prefer a “lazy” approach for creating discussion threads: it should be created only when somebody tries to submit the first comment. Only authenticated users are allowed to post comments (and I have managed to install SSO login) so the risk of spams should be low.

Is this possible somehow?

I have made a simple test like this: https:// github.com/dashohoxha/vocabulary-test/commit/74f520bbcc5176f886d253052e84cfb8162c2b0c

<script type="text/javascript">
  var discourseUrl = "http://discuss.btranslator.org/",
      discourseEmbedUrl = 'https://btranslator.org/translations/sq/a1fffaaafb7cc996685bceb829c053cc4f7de43d';

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

But when I open the page (at http://test.fjalori.fs.al/) I get a console error like this:

Refused to display 'http://discuss.btranslator.org/embed/comments?embed_url=https%3A%2F%2Fbtranslator.org%2Ftranslations%2Fsq%2Fa1fffaaafb7cc996685bceb829c053cc4f7de43d' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.

Any idea on how to make it work properly?


I solved the problem of X-Frame-Options, see:
https:// github.com/B-Translator/discourse-allow-same-origin/blob/master/README.md


I find the embedding approach described here a bit complicated, and having many assumptions and restrictions that don’t fit many users.

Here is a simpler approach that looks less like a black magic to me:

<div id="discourse-comments"></div>
<script type="text/javascript">
var discourseUrl = "http://discuss.btranslator.org/";
function showDiscourseTopic(topic) {
  var comments = document.getElementById('discourse-comments');
  var iframe = document.getElementById('discourse-embed-frame');
  if (iframe) { iframe.remove(); }
  iframe = document.createElement('iframe');
  iframe.src = discourseUrl + '/t/' + topic + '/';
  iframe.id = 'discourse-embed-frame';
  iframe.width = '100%';
  iframe.height = '500px';
  iframe.frameBorder = '0';
  iframe.scrolling = 'yes';

The problems with the code above are these:

  1. It does not set the height of the iFrame to match the height of the content, avoiding thus scrolling. I think that this can be fixed, however I am not a JavaScript expert.

  2. It displays extra content that are useful in a full page display but are useless in an embedded display. This can be solved if the server somehow is aware that this is an embedded display and includes an extra CSS that hides the extra parts of the page. As an example see the difference between https://btranslator.org/vocabulary/ICT_sq and https://btranslator.org/vocabulary/ICT_sq?display=iframe
    Maybe this can be solved by a Discourse plugin, but I am not a Discourse or RoR expert.

  3. If the current page has no comments the discourse topic should not exist and should not be created. The script above should detect automatically that the topic for the current page does not exist and should just display a Reply/Comment input box. When the first comment is submitted, the topic should be created automatically. Maybe this can be solved by JavaScript magic, or maybe by a Discourse plugin.


This is currently impossible as comments are created in topics. If the topic didn’t exist, they couldn’t make a comment in the first place.

I respect your opinion but the embed code we provide is much simpler and handles a lot of the cases like the height that your proposal does not. The current embedding code does have some limitations (styling/customization is a big one) and I’d prefer suggestions to improving those to handle other people’s use cases.


I have started to build a plugin for implementing this, see: https://meta.discourse.org/t/plugin-for-seamlessly-embedding-discourse-in-a-page-as-comments/28452
By the way, limitations that you have imposed on the forum are crippling the discussion, and I hate it. If you don’t know me, you cannot start by the assumption that I am evil. This is wrong.

I think that “lazy” topics can be implemented like this:

  1. If a topic does not exist, instead of displaying the message that topic does not exist, pretend that the topic does exist but is empty (it has no content, no comments, etc.)

  2. When a comment is submitted, check first whether the corresponding topic does exist, and if not, create it.

Which of these is impossible? Things like these can be implemented even on PHP, and I guess that Ruby and Rails are more flexible and powerful than PHP.

Of course, I can try to learn Rails, and try to implement this myself, or convince myself that this is indeed impossible. But this would take me a long time.


I replied on meta. There is no reason to post the same comment twice on both sites.


I am using code in my website. its working perfectly. But when i click in “Continue Discussion” its opening in new window. Is it possible continue my discussion in my site without going to the discourse forum?