DISQUS for Joomla

In the process of getting my new Joomla! based website up and running, I wanted to add a comment system [Note: My website no longer has a Joomla! backend]. As usual, every free option available had it's own quirks. Some had visual issues, some didn't support threaded replies, and some had conflicts with other Joomla extensions I was using. I ended up liking the DISQUS comment system for Joomla! v1.1 by JoomlaWorks. It integrates the free comment management system, DISQUS, into a site's articles. While I did have to tweak my site template a bit to prevent its JavaScript generated content from drawing over my footer, it covered the rest of my needs.

After testing out the plugin for a while, I started to notice a large issue. Anytime an article was viewed with a different URL, it ended up using a different comment thread. In Joomla!, articles can be seen under different URLs for a number of reasons including changing search engine friendly (SEF) URL settings, recategorizing an article, changing your menu, or viewing an article split into multiple pages. Dissapointed to find yet another problematic plugin, I decided to find the root of the problem and fix it.

Plugin Overview 

The plugin is based around a file called 'jw_discus.php'. After installing the extension, you can find it in the 'plugins/content/' folder of Joomla. The file's purpose is to provide the proper DISQUS code in the proper locations as Joomla! generates the site content. This results in two main tasks.

  1. During the  "blog view", it needs to generate a link to view the article comments. This view is what you normally see on the front of a Joomla website where a short introduction is displayed per article followed by a "Read more..." link to view the full content.
  2. During the "article view", it needs to generate a link to the article comments at the top, and needs to generate the actual article comments at the bottom.

Improving the code

The crux of the problem was in the comment generation code. In article view mode, the following code would return the HTML for displaying comments.

return '
<div id="disqus_thread"></div>
<script type="text/javascript"
<a href="http://'.$disqus_user.'.disqus.com/?url=ref">View the forum thread.</a>
<div class="disqus_credits"><a href="http://disqus.com" class="dsq-brlink">
blog comments powered by <span class="logo-disqus">Disqus</span>

This creates the default code block supplied by DISQUS to set up your website. It may also have been the only option available when the plugin was written. This tells DISQUS's 'embed.js' file to generate the comment display inside the HTML element with id 'disqus_thread'. You can see the 'disqus_thread' div tag on the second line.

By default, the 'embed.js' script will use the current URL as an internal identifier of the comment thread. If it has never seen this identifier (your article URL), it will create a new thread for it. Due to this logic, we will be accessing different comment threads for every different URL regardless of whether or not they show the same article.

A similar problem can occur with selecting a name for the comment thread (the name is used on the DISQUS community page when listing your threads). When creating a new thread, DISQUS will name it based on the title of the page it was created from. If we have a multi-page article set up and the first commenter posted from page 2, we would end up with the title of page 2 as our thread title instead of the title of the article itself. At the moment, this isn't our worst problem because DISQUS will end up giving the second page a new thread anyway due to its different URL!

Lets be optimistic and assume we will find a way to solve our first two issues. This still leaves one final problem to bite us. The DISQUS community page also needs a way to link back to the article a thread belongs to. As you might guess, it stores of the URL from which the article was first commented on. If the first comment occured on page 2 of a multi-page article, the DISQUS listing for that comment thread will always link back to page 2. This can get even worse if you were to recategorize your article or maybe shuffle around your menus which could then break all of the links from DISQUS back to your articles.

Fortunately, DISQUS has provided us with the means to solve all of our issues. The 'embed.js' script can actually be parameterized with a number of options including a user specified article identitfier, article title, and article URL. Unfortunately, these parameters are a bit hidden away and it takes some searching to find out that they exist. We need to declare our parameters as global variables before refrencing in the 'embed.js' script. The script will then read in our global settings to change how it behaves. This is a shady manner of parameter passing, but I suppose such is the nature of web programming.

In Joomla!, every article you create gets its own unique number (it won't even reuse numbers from articles that you deleted in the past). This becomes a prime canditate for our DISQUS comment thread identifier. Rather than using just the number itself, we will prefix it with 'JoomlaArticleId_'. This will help prevent confusion with other non Joomla! article pages that you might be using DISQUS for. We can use the disqus_identifier parameter to set the value.

To generate the correct thread title, we can ussually just assign the article title. The only exception to this rule is when we are in a multi-page article. In this case, Joomla! will have appended ' - Your_Page_Title' to the article title. After removing the appended text, we can use the disqus_title parameter to set the value.

For the URL, we are going to do something a bit sneaky for the time being (see the end of this article for future improvements). We want to make sure our URL links to the first page of a multi-page article, and that it doesn't break when we change our site's menus or recategorize the article. To do this, we can tell Joomla! to load up an article by its id number through some URL based parameters (this will even work if SEF is enabled on your Joomla! site). The view parameter can be set to article so that we load up a single article (rather than a category or section) and the id parameter can be set the the article number. For example, if we had Joomla! set up at 'http://www.example.com/Joomla/', we could open article number 34 with 'http://www.example.com/Joomla/?view=article&id=34'. We can now set the disqus_url parameter to our generated URL.

Below you will see the updated code with all of our changes along with the license it is released under.

  Copyright (c) 2009 Ryan Juckett
  GNU General Public License, version 2
// this will be prefixed to the article id to create the unique DISQUS thread
// identifier
$identifier_prefix = "JoomlaArticleId_";
// build a string of parameters for the DISQUS script	
$disqus_params = "";
// The short name is used to identify your forum within disqus
$disqus_params .= 'var disqus_shortname = "' . $disqus_user . '";';
// Use the unique article id to create a DISQUS identiefier. This lets us keep
// the same comment thread for each page of a multi-page article, for when SEF
// is enabled, or for when a pages section/category changes.
$disqus_params .= 'var disqus_identifier = "' . $identifier_prefix
                                              . $row->id . '";';
// Make sure the article title is used as the discus title. This prevents odd
// titles from being created when commenting from a multipage article after
// the first page. To extract the base title, we need to remove any existing
// page title suffix.
$articleTitle = $row->title;
if( !empty($row->page_title) )
	// The article title has been extended with ' - ThePageTitle'.
	// Find the suffix at the end of the full title and remove it.
	$realTitleLen = strrpos( $row->title, ' - '.$row->page_title );
	if( $realTitleLen != FALSE )
		$articleTitle = substr( $row->title, 0, $realTitleLen );
$disqus_params .= 'var disqus_title = "' . $articleTitle . '";';
// The disqus_url parameter determines the URL that the DISQUS community page
// uses to link back to the article. We will grab the article directly by its
// ID rather than using
// JRoute::_(ContentHelperRoute::getArticleRoute( $article->slug,
//                                                $article->catslug,
//                                                $article->sectionid))
// which would process SEF URLs. If we shuffle our site organization around,
// old SEF based might no longer work. Doing it this way will make sure the
// link remains valid due to the Joomla article id remaining unique.
$disqus_params .= ' var disqus_url ="' . JURI::base() . '?view=article&id='
                                       . $row->id . '";';
// Declare disqus parameters and embed the disqus logic
return '
<div id="disqus_thread"></div>
<script type="text/javascript">'.$disqus_params.'</script>
<script type="text/javascript">
  (function() {
    var dsq = document.createElement("script"); dsq.type = "text/javascript"; dsq.async = true;
    dsq.src = "http://" + disqus_shortname + ".disqus.com/embed.js";
    (document.getElementsByTagName("head")[0] || document.getElementsByTagName("body")[0]).appendChild(dsq);
<a href="http://'.$disqus_user.'.disqus.com/?url=ref">View the forum thread.</a>
<div class="disqus_credits"><a href="http://disqus.com" class="dsq-brlink">
blog comments powered by <span class="logo-disqus">Disqus</span>

Future improvements

While our fixes solve enough problems to make DISQUS a solid option for your Joomla! comments, we still have a few kinks to work out. For starters, if you were to rename an article on your site, its listing on the DISQUS community page would be stuck at the original name. While it would be fantastic if we detected the rename in Joomla! and then automatically renamed the DISQUS data, we need to take one step at a time. Currently, we can't even use the DISQUS administration page to rename a comment thread. We actually can't do much of anything in the DISQUS admin when it comes to modifying the parameters of a thread after creation, but all hope is not lost.

The DISQUS API supplies us with with plenty of control over our threads. We could use it to write an interface to rename a thread's title, change its identifier, change the URL, or even permanently delete it. Granted, all of these features should be part of the standard DISQUS administration page and I can only hope that they will be at some point. Presently, I don't know of any available substitutes to the standard admin page but the API is available if anyone wants to take a shot at it.