Gregory's Blog
long meetins stink

Incorporating the optional Disqus library into Galaxie Blog


In order to incorporate the optional Disqus library, Galaxie Blog requires three keys- the Disqus Blog Identifier (or Short Name), and optionally, the Disqus API Key and API Secret. Setting up a Disqus account and obtaining these keys are free. I will walk you through the steps to register with Disqus and enter the Disqus keys into Galaxie Blog.

To incorporate the Disqus comment system into your own blog, you first need to create a Disqus account to obtain your Disqus Blog Identifier, otherwise known as your blog's short name. You should also create a free developer account in order to acquire a Disqus API key. I will briefly walk you through the required steps to obtain both keys. If you already have a Disqus blog identifier and API key, you can skip the first two sections and read Entering your Disqus Keys.

Register your site and obtain your Disqus Blog Identifier

  1. First, sign up for a free Disqus account at www.disqus.com
  2. Click on the get started button
  3. Enter your name and email, and create a password. You will need to verify your email with Disqus before you continue.
  4. Once you're done creating your profile, click on I want to install Disqus on my site.
  
  1. Register your site by including the name of your site, and choose an appropriate category.
  2. Prior to clicking on the Create Site button, you'll notice the short name of your site. I highlighted the short name with a circle. If you didn't notice this before registering, don't worry- you will be able to look it up later.
  3. Click on Create site.
  4. For a personal blog, I recommend selecting the Basic plan. The basic plan does have a Disqus label at the bottom of the comments interface, but it is free. You're welcome to choose a paid plan if you want, but it is not necessary.
  5. You don't need to do anything on the Select Platform interface. I have integrated Disqus into Galaxie Blog. We need to move on to the configuration settings.
  6. In the configuration settings, enter the website name, URL, category, and description. You don't need to enter pages for your own policies right now, you can come back to this later.
  7. Click on the Complete setup button
 
  1. On the next Setup Complete page, scroll to the bottom of the page and click on the Configure your site's community settings link.
  2. Take note of your blog's Short Name in the 2nd setting. Copy this string. You will need it later to paste into Galaxie Blogs disqusBlogIdentifier setting.
  3. Make sure that the color scheme is set to automatic. This is needed to have Disqus adjust the comment interface with Galaxie Blog's multiple themes.
  4. Click on the Save button
 
 

Getting your Disqus API Keys

After you register your Disqus account, you should also consider signing up for a free Disqus API Key. A Disqus API Key allows you to build your own widgets, such as a recent comments interface. For Galaxie Blog owners, the optional API Key allows Galaxie Blog to display my own custom recent comments interface that blends in with the Galaxie Blog themes. It also allows Galaxie Blog to have an accurate comment count in the administrative interface. The API key is free, and the free version generously allows for 10,000 calls per hour at the time of writing. The limit is sufficient on immensely popular blogs, such as Raymond Camdens blog. The free API key should suffice.

  1. Don't look for the API key after registering your site with Disqus. It is not available using the default Disqus interface. You will have to go to the Disqus API page.
  2. Navigate to https://disqus.com/api/applications/ and click on Applications
  3. Enter your site information and register your application
  4. On the next page, leave the default settings as they are. You don't need to add or change anything, just click Save changes
 
  1. The next screen is a little confusing. At the time of the writing, it seems as if you have just refreshed the page. Here, just click on the Details link at the top of the page. I am attaching a screenshot.
  2. Your new Disqus API Key is found underneath the OAuth settings on the Details screen.
  3. If you are here just to obtain your Disqus Blog Identifier (aka short name) and API key for Galaxie Blog, continue to the next page. If you're a developer looking into incorporating Disqus into your own site, you may want to take a look at the Common Libraries page.
 

Entering the Disqus Keys into the Galaxie Blog Administration Site

  1. Once you have your own Disqus Blog Identifier, you can immediately incorporate Disqus using Galaxie Blog by entering the three keys into the Galaxie Blog Administration site 
  2. Log in to the Galaxie Blog Administration site
  3. Open the Blog Options Interface
  4. Click on the Disqus Library Ribbon
  5. Finally, enter the Disqus Blog Identifier (also known as the Disqus Short Name), the Disqus API Key and the Disqus API Secret into the form fields.

That's it! Refresh the page and your Disqus commenting system should be in place.

Happy Blogging! 

Note: this article has been rewritten for Galaxie Blog 3

This entry was posted on April 28, 2022 at 9:08 PM and has received 1134 views.

Building your own Disqus Recent Comments Widget


This article will show you a way to use the Disqus API key to build your own custom recent comments Disqus widget. Do you really need your own custom Disqus Recent Comments Widget?A recent comments widget is a tool that allows blog owners to show the most recent comments on a page. If you're just using Disqus on a static site that does not contain all of the blog entries, you might not need to roll your own custom recent comment widget. And, even if you do have a page that contains all of the blog entries, you may not need a custom widget- Disqus already provides one. To incorporate it, all that you need to do is replace the 'gregorys-blog' string with your own Disqus Blog Identifier (also known as the blog short name) like so:

<script type="text/javascript" src="https://gregorys-blog.disqus.com/recent_comments_widget.js?num_items=10&hide_avatars=0&avatar_size=40&excerpt_length=100"></script >

This is a basic widget, and it contains nearly everything that you may need. My code falls back to this approach in Galaxie Blog when the blog owner does not paste in his own API Key. However, it is not flexible. It is what you see is what you get, and I wanted to blend the recent comment widget with Galaxie Blogs themes, and needed other things, such as having to use the Disqus API to have my own statistical reporting. I'm a stickler for design- I personally determined from the outset that I need roll my own Disqus recent comments widget, and I'll share my approach... Building your own Disqus Recent Comments Widget

  1. First, you will need to obtain a Disqus Blog Identifier (aka Blog Short Name) and a Disqus API Key. If you don't already have these keys, the following articles should help you in getting these:
  2. The code below is the style sheets that I developed for Galaxie Blogs recent comments. There is nothing interesting to note here but I am sharing to give you a starting point:
<!-- Styles for disqus -->
<style>
	.userProfile {
		margin: 15px 0;	 
		list-style-type: none;	 
		clear: both;
	}

	img.disqusAvatar {
		width: 64px;
		height: 64px;
		float: left;
		position: relative;
		z-index: 99;
		border: 0px;
		margin: 0px;
		/* The padding needs to be uniform, otherwise the avatar circle will be elongated */
		padding: <cfoutput>#avatarPadding#</cfoutput>;
		-moz-border-radius: 50%;
		-webkit-border-radius: 50%;
		-webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.2);
		-moz-box-shadow: 0 1px 2px rgba(0,0,0,0.2);
		box-shadow: 0 1px 2px rgba(0,0,0,0.2);
		overflow: hidden;
	}

	#disqusCommentDiv a {
		overflow: hidden; /* Prevent wrapping */
	}

	#disqusCommentDiv p {
		display: inline; /* Prevent wrapping */
	}

	#disqusCommentPanel a {
		overflow: hidden; /* Prevent wrapping */
	}

	#disqusCommentPanel p {
		display: inline; /* Prevent wrapping */
	}

	.comment-avatar img {
		width: 100%;
		height: 100%;
	}
</style>
  1. The real magic happens in the javascript below. I'll try to walk you through some of the more interesting tidbits
    1. The getRecentDisqusComments function makes a call to the Disqus API invoking the listsPosts method
    2. Additionally, the related=thread argument is appended to the URL string. This argument allows us to get the URL and Title of the post. Without this argument, we would need to make another call the threads list method, which is frankly a nightmare1.
    3. We are passing our Disqus keys in the Ajax post
    4. The getDisqusCommentsResponse callback method retrieves the data and writes out our custom HTML. Here, I am using my own custom class definitions to make the widget blend in with my own themes.
    5. The isOdd method assists in creating alternate colors of each row.
    6. The timeSince method is used to append a string to tell the viewer when the comment was made (ie '20 seconds ago').
    7. Finally, the truncateString method is used to truncate the comment string.
function getRecentDisqusComments(){

	// Submit form via AJAX.
	$.ajax(
		{
			type: "get",
			url: "https://disqus.com/api/3.0/forums/listPosts.json?related=thread",
			data: {
				// Passing my own keys.
				api_key: "<cfoutput>#application.disqusApiKey#</cfoutput>",
				forum:  "<cfoutput>#application.disqusBlogIdentifier#</cfoutput>",

				limit: "<cfoutput>#numComments#</cfoutput>"
			},
			// jsponp is supported as well. 
			dataType: "json",
			cache: false,
			success: function(data) {
				setTimeout(function () {
					// Callback function
					getDisqusCommentsResponse(data);
				// The timeout ensures that the data will be available to the callback function.
				}, 250);
			}
		}
	);
}//..function getRecentDisqusComments(){

function getDisqusCommentsResponse(data){
	var html = "";
	// Loop through the json structure.
	for (var i = 0, len = data.response.length; i < len; i++) {
		// Isolate our post (or entry).
		var post = data.response[i];
		// Set a current row value from our index. I need a whole number to determine the alternating row color. I could just use [i]+1, but I am setting this for readability.
		var row = parseInt([i]);
		// Get the data for the post.
		var authorName = post.author.name;
		var authorProfileUrl = post.author.profileUrl;
		var authorAvatarUrl = post.author.avatar.cache;
		// We need to strip the HTML out of the comment. It has links that are not useful and will take up our space.
		var comment = stripHtml(post.message);
		var commentPromoted = post.isHighlighted;
		var approved = post.isApproved;
		// Get the timestamp and convert it into a proper js date object.
		var created = new Date(post.createdAt);
		// Find the link to the actual article. Note: for this to work, you must have related=thread appended to the ajax link (ie https://disqus.com/api/3.0/forums/listPosts.json?related=thread).
		var pageLink = post.thread.link;
		var pageTitle = post.thread.title;

		// Create the HTML. We will try to keep this nearly identical to the recent comment widget, but put in our own kendo classes here.
		// Crete the table on the first row.
		if (row == 0){
			html += '<table id="disqusComment" align="center" class="k-content fixedPodTableWithWrap" width="100%" cellpadding="0" cellspacing="0">';
		}
		// Create the row and alternate the k-content and k-alt class.
		if (isOdd(row)){
			html += '<tr class="k-alt" height="50px;">';
		} else {
			html += '<tr class="k-content" height="50px;">';
		}
		// After the first iteration, create a row with a border. Javascript arrays (which is our 'row') start at 0.
		if (row == 0){
			html += '<td align="left" valign="top" class="userProfile">';
		} else {
			html += '<td align="left" valign="top" class="border userProfile">';
		}
		// Wrap the avatar with the authors profile link
		html += '<br/><a href="' + authorProfileUrl + '" aria-label="Profile for ' + authorName + '" rel="nofollow noopener">' + authorName;
		// Place the avatar into the cell and close the anchor link.
		html += '<img class="disqusAvatar" src="' + authorAvatarUrl + '" aria-label="Profile for ' + authorName + '"></a><br/>';
		// Add the comment. The comment is already wrapped with a paragraph tag.
		html += truncateString(comment, <cfoutput>#lenComment#</cfoutput>) + '<br/>';
		// Create the HTML to insert into the page title.
		html += '<a href="' + pageLink + '" aria-label="' + pageLink + '">' + pageTitle + '</a> - ';
		// Add the timestamp to quickly identify how recent the post is.
		html += timeSince(new Date(created)) + ' ago<br/>';
		// Close the cell and the row.
		html += '</td></tr>';
		// Close the table on the last row
		if (row == <cfoutput>#round(numComments-1)#</cfoutput>){
			html += '</table>'
		}
		// Append the html to the page.
		$(document).ready(function() {
			$("#recentCommentsDiv").html(html);
			$("#recentCommentsPanel").html(html);
		});

	}//..for (var i = 0, len = data.response.length; i < len; i++) {

}

// Helper function to determine if the number is even or odd. This is used to create alternating row colors.
function isOdd(num) {
	return num % 2;
}

function stripHtml(html){
	html.replace(/<[^>]*>?/gm, '');
	return html;
}

// Function to write out the time since the post.
// Source: https://stackoverflow.com/questions/3177836/how-to-format-time-since-xxx-e-g-4-minutes-ago-similar-to-stack-exchange-site	
function timeSince(date) {
  var seconds = Math.floor((new Date() - date) / 1000);
  var interval = Math.floor(seconds / 31536000);

  if (interval > 1) {
	return interval + " years";
  }
  interval = Math.floor(seconds / 2592000);
  if (interval > 1) {
	return interval + " months";
  }
  interval = Math.floor(seconds / 86400);
  if (interval > 1) {
	return interval + " days";
  }
  interval = Math.floor(seconds / 3600);
  if (interval > 1) {
	return interval + " hours";
  }
  interval = Math.floor(seconds / 60);
  //alert(interval + ' minutes date: ' + date);
  if (interval > 1) {
	return interval + " minutes";
  }
  return Math.floor(seconds) + " seconds";
}

truncateString = function(str, length, ending) {
	if (length == null) {
		length = 100;
	}
	if (ending == null) {
		ending = '...';
	}
	if (str.length > length) {
		return str.substring(0, length - ending.length) + ending;
	} else {
		return str;
	}
};

// Call the method to populate the recent comments.
getRecentDisqusComments();

If you have any questions, don't hesitate to ask. Happy commenting! Further Reading: 1Raymond Camden has an excellent article at https://www.raymondcamden.com/2014/03/21/Example-of-a-JavaScript-Disqus-Recent-Comment-Widget. I wished that I had read this earlier before going down my own rabbit hole. To get the related post, I initially tried to call the thread list method (at https://disqus.com/api/3.0/threads/list.json) within a nested ajax post. My initial code was just... ugly. Finally, I stumbled upon this article and found out that I could simply use the related=thread argument to attach the comment to a thread.

This entry was posted on October 7, 2019 at 11:06 PM and has received 1286 views.

Adding multiple Disqus comments on one page


While incorporating comments into my main blog page, I found out that Disqus does not provide a native way to place multiple comments on a single page. The Disqus commenting system includes an embedded javascript at the end of an article. The javascript writes out the commenting interface using global variables and it can't be included twice. This poses a problem as my main blog page contains all of my blog posts, and I wanted the readers to be able to comment without having to go to each individual entry page. After research, I figured out way. I'll share my approach and give the reader other resources so they can do the same.

Background

While researching, I found a promising lead... Most of the folks that have skinned this cat referred to an article written by mystrdat that is now long since dead. I dug it up using the wayback machine at https://web.archive.org/web/20170606070513/http://mystrd.at/articles/multiple-disqus-threads-on-one-page/. It is an excellent article, and if you're trying to do the same thing, it is worth a read. There were other helpful resources that I found. Shawn Zhouprovides a list of articles that solved this issue. Shawn uses iframes to encapsulate the Disqus comments. Tsachi Shlidor shared his approach using inline comments. His demonstration and code is on github at http://tsi.github.io/inlineDisqussions/. Since I already built my own commenting system using the open sourced Kendo Core UIwindow widgets, I chose a different approach. I am encapsulating Disqus logic into various Kendo windows. You can use the same approach that I used with a different windowing library, such as jQuery UI. Using multiple Disqus comments using a Kendo window widget

  1. First, I took the Disqus universal code script and saved it as a new ColdFusion template. Note that the this.page.url and this.page.identifier are dynamic variables. These will be passed to the window via the URL.
<!--- Note: the disqus_shortname, URL and identifier are passed to this page via the URL. --->
<div id="disqus_thread"></div>
<script type="text/javascript">
	/**
	*  RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
	*  LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#chr(35)#configuration-variables*/
	
	var disqus_config = function () {
	var disqus_shortname = '<cfoutput>#URL.alias#</cfoutput>';
	this.page.url = '<cfoutput>#URL.url#</cfoutput>';  // Replace PAGE_URL with your page's canonical URL variable
	this.page.identifier = '<cfoutput>#URL.Id#</cfoutput>'; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
	};
	
	(function() { // DON'T EDIT BELOW THIS LINE */
		var d = document, s = d.createElement('script');
		s.src = 'https://gregorys-blog.disqus.com/embed.js';
		s.setAttribute('data-timestamp', +new Date());
		(d.head || d.body).appendChild(s);
	})();
</script>
  1. Second, I created the scripts to create a new Kendo window. The only thing of interest in the code below is that I am passing the URL and Identifier variables that the universal code script needs (this.page.url and this.page.identifier in the code above):
// Disqus comment window ---------------------------------------------------------------------------------------------------------------------------------
function createDisqusWindow(Id, alias, url) {

	// Remove the window if it already exists
	if ($("#disqusWindow").length > 0) {
		$("#disqusWindow").parent().remove();
	}

	// Typically we would use a div outside of the script to attach the window to, however, since this is inside of a function call, we are going to dynamically create a div via the append js method. If we were to use a div outside of this script, lets say underneath the 'mainBlog' container, it would cause weird problems, such as the page disappearing behind the window.
	$(document.body).append('<div id="disqusWindow"></div>');
	$('#disqusWindow').kendoWindow({
		title: "Comments",
		actions: ["Minimize", "Refresh", "Close"],
		modal: false,
		resizable: true,
		draggable: true,
		// For desktop, we are subtracting 5% off of the content width setting found near the top of this template.
		width: (getContentWidthPercentAsInt()-5 + '%'),
		height: "60%",
		iframe: false, // Don't use iframes unless it is content derived outside of your own site. 
		content: "/blog/disqus.cfm?id=" + Id + '&alias=' + alias + '&url=' + url,// Make sure to create an absolute path here. I had problems with a cached index.cfm page being inserted into the Kendo window probably due to the blogCfc caching logic. 

		close: function() {
			$('#disqusWindow').kendoWindow('destroy');
		}

	}).data('kendoWindow').center();
}//..function createDisqusWindow(Id, alias, url) {

// The mobile app has a dedicated button to close the window as the x at the top of the window is small and hard to see 
function closeDisqusWindow(){
	$("#disqusWindow").kendoWindow();
	var disqusWindow = $("#disqusWindow").data("kendoWindow");
	setTimeout(function() {
	  disqusWindow.destroy();
	}, 500);
}
  1. Then, on the web page itself, I am showing the following button that calls the createDisqusWindow function above. I am adding this button for every single blog entry on the page. In the button, I am adding the entry ID as the first argument (the this.page.identifier), the 2nd argument, the entries 'alias' (disqus_shortname), and the entry URL is passed to the this.page.url.
<button id="disqusCommentButton" class="k-button" style="width:125px; font-size:0.70em;" onClick="createDisqusWindow('6C04DC8C-FF58-C02F-8C38E2BEEBCA282B', 'Incorporate-Disqus-into-Galaxy-Blog--Part-3', 'https://gregoryalexander.com/blog/index.cfm/2019/10/6/Incorporate-Disqus-into-Galaxy-Blog--Part-3')">
	<i class="fas fa-comments" style="alignment-baseline:middle;"></i>  Comment
</button>
  1. To display the comment count, I am placing the disqus-comment-count with the URL of the entry. Note: if you want, you can replace the span tags with an anchor tag ('a href') and include an onClick event to open up the comments window.
<span class="disqus-comment-count" data-disqus-url="https://gregoryalexander.com/blog/index.cfm/2019/10/6/Incorporate-Disqus-into-Galaxy-Blog--Part-3"></span>
  1. Finally, at the very bottom of the index.cfm page, I am adding the disqus comment count script:
<script id="dsq-count-scr" type="deferjs" src="//gregorys-blog.disqus.com/count.js" async=""></script >

For a demonstration, go to https://gregoryalexander.com/blog/index.cfm, click on a comment link, and make a comment or at least say hi! Happy coding! Gregory

This entry was posted on October 7, 2019 at 4:10 PM and has received 2101 views.