Showing posts with label blogging. Show all posts
Showing posts with label blogging. Show all posts

14 Apr 2012

How to add infinite scrolling to Blogger blogs

One nice thing I like about Blogger’s Dynamic Views is that they remove older posts/newer posts links from your blog and load more posts as you scroll to the end of a page.  (This is commonly referred to as infinite scrolling.)  Adding infinite scrolling to your Blogger blog with a traditional template is not that hard.

If you don’t care about the details and you only want to enable the feature on your blog, click on the button below and add the code to your blog.  Infinite scrolling should just work on your blog, in most cases.  If you have a custom template, though, you may need to tweak the code a little.  (Scroll down to “Frequently asked question” section for details.)

If clicking on this button does nothing, or it doesn’t work for some reason, you can add this code manually:
  • Add a HTML/JavaScript gadget to your blog.
  • Leave the gadget’s title empty.
  • Paste the following code as the gadget’s content:
    <script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'></script>
    <script type='text/javascript' src='//m-misc.appspot.com/js/blogger-infinite-scrolling.js'></script>
  • Save the gadget, and you’re done.
The code for the widget is available on GitHub.  Feel free to copy or adapt the code.  A few points worth mentioning:
  • This code uses jQuery library, so don’t forget to include it.
  • Custom template blogs may have to change the value of postContainerSelector variable in the code.
  • I have manually added +1 buttons to my blog.  Dynamically loaded posts won’t have the +1 buttons initialised; to fix that issue, I had to call gapi.plusone.go() every time new posts are added to the page.
  • _WidgetManager is a JavaScript object present in Blogger blogs.  You can query this object to find some page metadata.  This code uses _WidgetManager to determine if the current page is showing a single post.  Infinite scrolling is not meaningful when only a single post needs to be displayed.

Frequently asked question

  • Q: My blog uses a script/widget that adds post thumbnails or related posts.  When I add infinite scrolling, only the first few posts have thumbnails/related posts.  How to fix that?
    A: Simple answer is that this script doesn’t work well with other scripts that add content to posts.  But if you are willing to change the code, you can get both scripts to work together.  Right after new posts have been added — which is the line after $(postContainerSelector).append(newPosts); in the script — add the JavaScript that will make your other widget update itself.
  • Q: The script doesn’t work on my blog.  Can you help me debug it?
    A: While I really wish I could help everyone use this script, it’s practically not possible for me to look at everyone’s blog and see what’s wrong.  If I don’t respond to your comment quickly (or at all), it’s because I am just too busy with things like my day job.  I’m sorry I couldn’t help you with your blog.
  • Q: Why can’t I post a comment?
    A: Contact me through Google+ if you need to ask me anything. I believe you can send me a message even if you don’t have a Google+ profile yourself.

Change log

  • Mar 9, 2013: Moved the script to m-misc.appspot.com because Google Code is not setting the right content type.  This disabled the script completely in Google Chrome.
  • Nov 19, 2012: Version 1.6 was released with support for Automatic Thumbnail and Read More.
  • Oct 17, 2012: Version 1.5 was released with support for Facebook buttons and a fix for Disqus integration bug.  Thanks to Alex for sharing Facebook support code in a comment.
  • Oct 11, 2012: Version 1.4 was released with support for Disqus comments.  Do not use this version; Disqus integration is broken in this version.
  • Sep 20, 2012: Version 1.3 was released with support for Google Analytics.  If a blog uses Google Analytics, the script will register all automatic post loading as pageviews.  To Google Analytics, it will look like the reader clicked on the Older Posts link every time the script autoloads posts.
  • May 30, 2012: Version 1.2 was released with fixes for all known bugs.
  • Versions up to (and including) 1.1 have known bugs.

12 Jan 2012

Blogger’s threaded commenting on custom template blogs

Update: Blogger has an official post about this.

Blogger today introduced the long-awaited threaded commenting feature.  It may not work for you even after enabling embedded comment form if you have manually customised your template.  Fear not, enabling threaded commenting on your custom template is not that hard :)

Go through your blog’s template and change all occurrences of
<b:include data='post' name='comments'/>
to
<b:if cond='data:post.showThreadedComments'>
  <b:include data='post' name='threaded_comments'/>
<b:else/>
  <b:include data='post' name='comments'/>
</b:if>
(Make sure you have enabled the “Expand Widget Templates” check box; you may not see the text to be replaced otherwise.)  This change will add a “Reply” link after each comment on your blog.

22 Aug 2011

The importance of URLs

I have been a Blogger user for years. I still swear by Blogger for a number of reasons. One of them is that URLs are very important for the web, and Blogger understands that.

Try this: go to icanread.tumblr.com and click on "next" link at the bottom. You'll be taken to http://icanread.tumblr.com/page/2. Go to blog.fatema.in and click on "previous entries" at the bottom. You'll be taken to http://blog.fatema.in/page/2. Go to thewayialwayswas.blogspot.com and click on "older posts" at the bottom. You'll be taken to http://thewayialwayswas.blogspot.com/search?updated-max=2011-08-12T09%3A00%3A00%2B08%3A00&max-results=3.

Now, the designer kind might think that Blogger URLs are ugly while WordPress and Tumblr URLs are neat. But there's more than what meets our eyes.

Let's say you find the content in one of these links interesting, and you share it with some of your friends. Naturally you'd just grab the URL from the address bar and share it. If your friend happens to open your link only a few weeks later, they might be seeing content that is completely different from what you intended to share.

Why? Because both Tumblr and WordPress "page" URLs are not unique identifiers to content. The same /page/2 URL will be showing different content based on how many new posts are added after you copied the URL. Blogger's URL, on the other hand, fixes on published date, so the content is much more likely to stay the same over time.

PS: It might be possible to configure WordPress to generate good URLs like Blogger; I don't know for sure.

2 Jun 2011

Add +1 buttons to your blog manually

Want +1 button on your Blogger blog, but you don’t want the full share widget?  Here’s how you can manually add only the +1 button to your blog:
  • Configure your +1 button and get the code from Google.
  • Remove href attribute of <g:plusone> starting tag; insert expr:href='data:post.canonicalUrl' in its place.  For example, the code on my blog is: <g:plusone expr:href="data:post.canonicalUrl" size="medium"/>
  • Insert the code in your blog’s template.
    • Open Blogger > your blog > Design > Edit HTML.
    • Check “Expand Widget Templates”.
    • Look for <div class="post-footer">
      if you want to place the +1 button at the bottom of each post; look for <div class="post-header"> if you want it at the top of each post.
    • Paste the +1 button’s code.  View your blog to see if the button appears at the right place, and adjust the placing accordingly.
Leave a comment if you have any questions.

16 Feb 2011

Tracking clicks on blog widgets

I play around with the layout and widgets used in my blog all the time.  Every time I make a change I believe that the change makes the blog better, for example by providing more useful links on the sidebar.  All this while I had to blindly hope that the sidebar links are useful.  But today I made a change so I can measure the usefulness of the sidebar widgets.

Side note: Google Analytics has a feature called event tracking that can be used to track events that happen within a single page.  Let's say you have built an awesome game hosted on a single URL on your web site.  Your game might be so addictive that many users open it first thing in the morning and keep playing all day.  If you measure only page views you won't know that people are playing the game all day because technically the game is loaded only once (though it's kept open for much longer).  To get more accurate usage data you can add some event tracking code and record an event every time the game begins.

I decided to add event tracking to several widgets in my blog so I can know which widgets are being clicked by the visitors and which are not.  But adding event tracking to Blogger's built-in widgets was not very obvious.  I navigated to Design > Edit HTML tab of my blog's dashboard and selected Expand Widget Templates check box to see the code for widgets.


I had to locate each widget's code within the template.  Searching for the widget title text was sufficient.  Code for the label cloud widget, for example, starts like this:
<b:widget id='Label1' locked='false' title='labels' type='Label'>
<b:includable id='main'>
  <b:if cond='data:title'>
  ...
The widget code had different sections of HTML pertaining to different configurations provided by the widget (show list vs. cloud, show post count, etc).  I added onclick event handlers to the links so every time a link is clicked an event will be recorded.  Here's one such modification I made:
<a expr:dir='data:blog.languageDirection' expr:href='data:label.url' onclick='_gaq.push(["_trackEvent", "label-cloud", "follow-link"])'><data:label.name/></a>

Now that event tracking is in place, decision making in the future will be easy.  Hopefully :)

9 Feb 2011

Can't customize ad placement in Blogger?

Are you trying to add ads to your Blogger blog, but the blog Layout doesn't show the ad gadget at all?  Maybe you're running an ad blocker extension (like AdBlock for Chrome or Firefox).  Do the following to get going:
  • Disable your ad blocker extension on blogger.com and draft.blogger.com domains.  Otherwise you cannot customize where ads are placed on your blog.
  • You will want to see how your blog looks to others without ad blocking.  So, whitelist all your blogs so that ads won't be blocked on your own blogs.

2 Jun 2010

Buzz feed widget for your blog

Google Buzz has a JavaScript API that lets you do several things with Buzz.  What I needed was a widget on my blog that would show my recent Buzz activity.  I spent a few hours and hacked up one myself.  Thought of sharing the code with others. (This code doesn't come with any sort of expressed or implied warranty. You can do with this code whatsoever you like.)

The widget shows your 6 recent activities on Buzz.  It links to your Google Buzz profile at the bottom.  For each post, it adds a link to the Buzz item and shows number of likes and comments.  This was my feed at the time of posting:

You can use this form to quickly add the widget to your blog:

Buzz User ID What's my user id?
Number of activities to show

For now, I am sharing the code here.  I should build some simple UI where you would specify the parameters like no. of items to show, your Buzz user id, etc. and get the code customized for you automatically.  I should also upload the code to someplace prominent, maybe Google Code.  But I would take some time before I do all this.

If you are adding this widget to your blog, don't forget to replace all occurrences of BUZZ_USER_ID with your own Buzz user id.  If you want to add this to your Blogger blog, but you are not sure how to do it, About.com has an article showing how to add any such widget to Blogger.  This is all HTML, JavaScript, and CSS.  So, you should be able to toss this code into any blog or web page and it should work.


If you don't use Blogger, you can use the following code to get the widget on your blog.  (Don't forget to replace all occurrences of BUZZ_USER_ID with your own Buzz user id.)

<style type="text/css">
#buzz-widget {
  width: 95%;
  padding: 2px;
}
#buzz-header {
  text-align: center;
}
#buzz-footer {
  text-align: right;
}
#buzz-footer a {
  text-decoration: none;
  font-weight: bold;
}
.buzz-feed {
  padding: 0;
  margin: 0;
}
.buzz-feed .buzz-entry {
  list-style-type: none;
  text-indent: 3px;
  border-bottom: 1px dotted gray;
  padding: 0.5em 0 0.5em 0;
  background-image: none;
}
img.buzz-icon {
  vertical-align: text-bottom;
  width: 16px;
  height: 16px;
}
</style>

<div id="buzz-widget">
<div id="buzz-feed"></div>
<div id="buzz-footer"><img src="http://goo.gl/TmmA" class="buzz-icon" /> <a href="http://www.google.com/profiles/BUZZ_USER_ID">View all buzz &raquo;</a></div>
</div>
<script type="text/javascript">
function getVerb(verb) {
  verbs = {
    'post': 'Posted',
    'share': 'Shared'
  };
  return verbs[verb] || 'Posted';
}

function normalizeTitle(title) {
  var MAX_LEN = 30;
  if (title.length > MAX_LEN) {
    return title.substr(0, MAX_LEN - 3) + '...';
  } else {
    return title;
  }
}

function getAttachmentHtml(attachments) {
  for (var i = 0; i < attachments.length; ++i) {
    var atch = attachments[i];
    if (atch.type == 'photo' || atch.type == 'video') {
      return '<img src="' + atch.links.preview[0].href + '">';
    }
  }
  return '';
}

function getItemHtml(item) {
  var html = getVerb(item.verbs[0]);
  var linkUrl = '';
  if (item.links.alternate[0]) {
    linkUrl = item.links.alternate[0].href;
    html += ' <a href="' + linkUrl + '">' +
        normalizeTitle(item.title) + '</a>';
  } else {
    html += normalizeTitle(item.title);
  }
  html += ' on ' + item.source.title;
  if (item.object.attachments) {
    var attachmentHtml = getAttachmentHtml(item.object.attachments);
    if (attachmentHtml) {
      if (linkUrl) {
        html += '<br><a href="' + linkUrl + '">' + attachmentHtml + '</a>';
      } else {
        html += '<br>' + attachmentHtml;
      }
    }
  }
  
  var numComments = item.links.replies[0].count;
  if (numComments > 0) {
    html += '<br><img src="http://goo.gl/Y4eU" class="buzz-icon"> ' +
        numComments + (numComments > 1 ? ' comments' : ' comment') + '&nbsp;&nbsp;';
  }
  
  var numLikes = item.links.liked[0].count;
  if (numLikes > 0) {
    if (numComments > 0) {
      html += '&nbsp;&nbsp;'
    } else {
      html += '<br>';
    }
    html += '<img src="http://goo.gl/0l9D" class="buzz-icon"> ' +
        numLikes + (numLikes > 1 ? ' likes' : ' like');
  }
  return html;
}

function showFeed(response) {
  var entries = [];
  var items = response.data.items;
  for (var i = 0; i < items.length; ++i) {
    entries.push(getItemHtml(items[i]));
  }
  document.getElementById('buzz-feed').innerHTML =
      '<ul class="buzz-feed"><li class="buzz-entry">' +
      entries.join('</li><li class="buzz-entry">') +
      '</ul>';
}
</script>
<script type="text/javascript"
    src="https://www.googleapis.com/buzz/v1/activities/BUZZ_USER_ID/@public?alt=json&max-results=6&callback=showFeed">
</script>

30 May 2010

Excluding self traffic from Google Analytics data

Google Analytics lets you track how your site is used, which is great.  But did you know that the data Analytics reports includes your own visits too?  You probably wouldn't your own visits to your site to be included in the Analytics data.  Analytics Help Center has an article detailing how this could be done.  This post tries to add some clarity to the "To exclude traffic by Cookie Content" section of that help article.

Depending on which version of tracking code you are using on your site, you have to do this in different ways.  If your tracking code has the line
var pageTracker = _gat._getTracker('UA-xxxxxxx-x');
then you can follow the instructions provided in Google Analytics Help Center and everything should work fine.  However, if your tracking code has the line
var _gaq = _gaq || [];
then change your HTML file to contain this code instead:
<body onLoad="javascript:_gaq.push(['_setVar', 'test_value']);">
Pro Tip: You don't really have to create new HTML file on your site for setting the cookie.  You can just open your site on the browser and type the value of onLoad attribute in the address bar.  For example, in my case, I opened blog.manki.in on my browser; typed javascript:_gaq.push(['_setVar', 'test_value']); on the address bar and pressed Enter.