Questions about Discourse Integration

I’ve been using WordPress for a long time and I am now considering moving some of those sites over to Ghost (yes, I’m sure this is a common story). As always, there’s a bit of a learning curve when switching from one software system to another. At present, I am attempting to integrate my Discourse-based forum with my Ghost-based test blog.

I admittedly do not (yet) have a firm grasp on all of the concepts in Ghost, which may explain (at least part of) why I am having trouble getting this embed to work. I would like to have Discourse-based comments available on all posts on my blog, but I would like to have posts on the blog appear in categories on Discourse based on the blog post’s tags (e.g., a post tagged “Philosophy” should appear in the “Philosophy” category on Discourse).

If I am not mistaken, this means that I will need a different embed/host configured for each category that will require comments. However, this raises additional questions. Here are my present questions/issues:

  1. How should posts with multiple categories, each of which allows comments, be handled? How would such a post be handled if multiple embeds/hosts apply to it?
  2. Will comments show on the main/home page or only when displayed via an endpoint (i.e., a whitelisted path in Discourse) for which comments are enabled (e.g., /philosophy/.* or /politics/.*)?
  3. Does a generic whitelist of /.* work? Would this effectively enable comment in all posts?
  4. I am currently using the following code on my blog in an attempt to enable Discourse-based comments:
<div id='discourse-comments'></div>

<script type="text/javascript">
	DiscourseEmbed = { discourseUrl: 'https://forum.coreyjmahler.com/',
		discourseEmbedUrl: '{{url absolute="true"}}' };

	(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);
	})();
</script>

However, as can be seen from this test post, the code is clearly not working. Why?

Additional Information

  • I have already cleared all caches, and, in fact, had Cloudflare paused while I was working on this.
  • The following resource throws a 404 error in Safari:
    https://blog.coreyjmahler.com/assets/main/css/main.css.map/
    but there are no other errors reported.
  • The following error appears a number of times in the Ghost logs:
{"name":"Log","hostname":"blog-coreyjmahler-com","pid":2821,"level":50,"req":{"meta":{"requestId":"4cfbf860-0d7f-11e9-b0b9-a55cf68e3775","userId":null},"url":"/users/me/?include=roles","method":"GET","originalUrl":"/ghost/api/v2/admin/users/me/?include=roles","params":{},"headers":{"x-forwarded-for":"A.B.C.D","x-forwarded-proto":"https","x-real-ip":"A.B.C.D","host":"blog.coreyjmahler.com","connection":"close","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0","accept":"application/json, text/javascript, */*; q=0.01","accept-language":"en-US,en;q=0.5","accept-encoding":"gzip, deflate, br","referer":"https://blog.coreyjmahler.com/ghost/","content-type":"application/json; charset=UTF-8","x-ghost-version":"2.9","app-pragma":"no-cache","x-requested-with":"XMLHttpRequest"},"body":{},"query":{"include":"roles"}},"res":{"_headers":{"x-powered-by":"Express","cache-control":"no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0","content-type":"application/json; charset=utf-8","content-length":"73","etag":"W/\"49-Htz2g1hjAoUvJ874WUMiMG0d3Z0\"","vary":"Accept-Encoding"},"statusCode":401,"responseTime":"16ms"},"err":{"id":"4cfdcd20-0d7f-11e9-b0b9-a55cf68e3775","domain":"https://blog.coreyjmahler.com","code":null,"name":"UnauthorizedError","statusCode":401,"level":"normal","message":"Access denied.","context":"empty","help":"empty","stack":"UnauthorizedError: Access denied.\n    at new UnauthorizedError (/var/www/ghost/versions/2.9.1/node_modules/ghost-ignition/lib/errors/index.js:101:23)\n    at ensureUser (/var/www/ghost/versions/2.9.1/core/server/services/auth/session/middleware.js:98:10)\n    at Layer.handle [as handle_request] (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/layer.js:95:5)\n    at next (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/route.js:137:13)\n    at getUser (/var/www/ghost/versions/2.9.1/core/server/services/auth/session/middleware.js:82:16)\n    at Layer.handle [as handle_request] (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/layer.js:95:5)\n    at next (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/route.js:137:13)\n    at cookieCsrfProtection (/var/www/ghost/versions/2.9.1/core/server/services/auth/session/middleware.js:107:16)\n    at Layer.handle [as handle_request] (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/layer.js:95:5)\n    at next (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/route.js:137:13)\n    at session (/var/www/ghost/versions/2.9.1/node_modules/express-session/index.js:454:7)\n    at getSession (/var/www/ghost/versions/2.9.1/core/server/services/auth/session/middleware.js:48:12)\n    at Layer.handle [as handle_request] (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/layer.js:95:5)\n    at next (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/route.js:137:13)\n    at Route.dispatch (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/route.js:112:3)\n    at Layer.handle [as handle_request] (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/layer.js:95:5)\n    at /var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:281:22\n    at param (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:354:14)\n    at param (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:365:14)\n    at Function.process_params (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:410:3)\n    at next (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:275:10)\n    at Function.handle (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:174:3)\n    at router (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:47:12)\n    at Layer.handle [as handle_request] (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/layer.js:95:5)\n    at trim_prefix (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:317:13)\n    at /var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:284:7\n    at Function.process_params (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:335:12)\n    at next (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:275:10)\n    at cacheControlHeaders (/var/www/ghost/versions/2.9.1/core/server/web/shared/middlewares/cache-control.js:32:9)\n    at Layer.handle [as handle_request] (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/layer.js:95:5)\n    at trim_prefix (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:317:13)\n    at /var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:284:7\n    at Function.process_params (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:335:12)\n    at next (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:275:10)\n    at checkVersionMatch (/var/www/ghost/versions/2.9.1/core/server/web/shared/middlewares/api/version-match.js:23:5)\n    at Layer.handle [as handle_request] (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/layer.js:95:5)\n    at trim_prefix (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:317:13)\n    at /var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:284:7\n    at Function.process_params (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:335:12)\n    at next (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:275:10)\n    at maintenance (/var/www/ghost/versions/2.9.1/core/server/web/shared/middlewares/maintenance.js:18:5)\n    at Layer.handle [as handle_request] (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/layer.js:95:5)\n    at trim_prefix (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:317:13)\n    at /var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:284:7\n    at Function.process_params (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:335:12)\n    at next (/var/www/ghost/versions/2.9.1/node_modules/express/lib/router/index.js:275:10)","errorDetails":"empty"},"msg":"Access denied.","time":"2019-01-01T04:40:01.535Z","v":0}

(IP addresses masked to A.B.C.D.)


  • What’s your URL? https://blog.coreyjmahler.com/
  • What version of Ghost are you using? Current
  • What configuration? Ubuntu 18.04 and nginx
  • What browser? Firefox and Safari
  • What errors or information do you see in the console? None in the Discourse logs; one in Safari, supra; and one in the Ghost logs, supra.
  • What steps could someone else take to reproduce the issue you’re having? See above.

I have opened a ‘copy’ of this thread over on Discourse Meta as I am unsure if the primary issue I am encountering (i.e., the one that is making it so comments do not show at all) is (primarily) Ghost or Discourse related.

Hey - great to hear you’re thinking of migrating to Ghost :grinning:

To try and help answer a few of your questions:

  • The way to get comments with multiple categories to work is to use multiple embed hosts as you mentioned and match these up to a whitelisted path. This does mean that you’ll need to consider how to structure your content in Ghost. One way to do this would be to use a content collection for each category (e.g. /philosophy/.* and /politics/.*), or you could include the primary tag in your blog permalink structure.
  • It is also possible to enable comments using a generic whitelist but in that case you’d need to use a single category in Discourse.
  • Are your Discourse topics public? I’m not 100% sure but I think they need to be public/not hidden for this implementation to work on your test blog posts. The code you shared here does look correct as per our Integrations guide.

The Discourse topics for these posts will be public. I think a generic whitelist may be the way to go (that is what I initially tried). However, it seems like the code is not working. Interestingly, if I paste the code into an HTML block in the editor, then the comments attempt to load on the frontend, but, as the Discourse topic is still not being created, the attempt, of course, fails.

Given the way Discourse works, I don’t see a reason that moving a topic into a new category in Discourse should break anything. So, a possible ‘workaround’ would be to use the generic whitelist (once I can figure out how to get it working) and have it place all topics created for Ghost posts into a Staging category and then manually move them to a more appropriate category.

Here are 1) the settings I have in Discourse for the embed and 2) the contents of my post.hbs (I am using the Editorial theme):

Discourse Settings

37

post.hbs

{{!< default}}
{{!-- The tag above means: insert everything in this file
into the {body} of the default.hbs template --}}

{{#post}}
{{!-- Everything inside the #post tags pulls data from the post --}}
<section>

    <header class="main content">
        <span class="date">{{date format="MMMM D, YYYY"}}</span>
        <h1>{{title}}</h1>
        {{#if custom_excerpt}}
            <p class="content">{{custom_excerpt}}</p>
        {{/if}}
    </header>

    {{#if feature_image}}
    <div class="image main"><img src="{{img_url feature_image}}" alt="{{title}}" /></div>
    {{/if}}

    <div class="content">
        {{content}}
    </div>

    {{!-- Email subscribe form at the bottom of the page --}}
    {{#if @labs.subscribers}}
    <section class="subscribe-form">
        <h3 class="subscribe-form-title">Subscribe to {{@blog.title}}</h3>
        <p>Get the latest posts delivered right to your inbox</p>
        {{subscribe_form placeholder="youremail@example.com"}}
    </section>
    {{/if}}

    <footer class="post-footer">

        <div class="authors">
            {{#foreach authors}}
            <a class="author-box" href="{{url}}">
                {{#if profile_image}}
                <img class="author-profile-image" src="{{profile_image}}" alt="{{name}}" />
                {{/if}}
                <section class="author-box-content">
                    <div class="author-box-label">Author</div>
                    <h5 class="author-box-name">{{name}}</h5>
                    {{#if bio}}
                    <p>{{bio}}</p>
                    {{else}}
                    <p>Read more posts by this author.</p>
                    {{/if}}
                </section>
            </a>
            {{/foreach}}
        </div>

    </footer>

    {{!--
    <section class="post-full-comments">
        <div id='discourse-comments'></div>

        <script type="text/javascript">
        	DiscourseEmbed = { discourseUrl: 'https://forum.coreyjmahler.com/',
        		discourseEmbedUrl: '{{url absolute="true"}}' };

        	(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);
        	})();
        </script>
    </section>
    --}}

</section>
{{/post}}

<script>
    var images = document.querySelectorAll('.kg-gallery-image img');
    images.forEach(function (image) {
        var container = image.closest('.kg-gallery-image');
        var width = image.attributes.width.value;
        var height = image.attributes.height.value;
        var ratio = width / height;
        container.style.flex = ratio + ' 1 0%';
    })
</script>

For some reason, the integration is not creating topics in Discourse.

Hey there!

I’m not sure if using a generic whitelist and then moving topics around would work - but certainly worth testing if that would be a suitable approach. Would be interested to hear the results if you do try it out.

Couple of notes:

  1. It looks like your “Post to Category” of Staging has a padlock on it, which means it’s locked and not public. This is what I meant in my last comment - I ran into the same issue when embedding Discourse comments on my site, and found that I had to test it on a public Discourse category.

  2. Your Discourse embed code is commented out with {{!--, --}} – remove these tags and re-upload your active theme in Ghost Admin and then it should work.

Hope that helps! :slight_smile:

1 Like

I originally had the category set to Posts, which is public. I changed it over to staging for some testing before taking the screenshot (which I should have mentioned). It would appear I should have taken a look at the code in an editor that color codes *.hbs files; I had it open in BBEdit and the fact that that section was commented out did not show. Thank you for the help. Always good to get a second pair of eyes on these things.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.