Snipsnap SEO Hacking: Post title optimization 
Yesterday while surfing on the web I found an interesting article about
the importance of title tags in search engine optimisation (SEO). It's a good reading if you have a couple of minutes, and the main idea is that the
<title> tag
is important regarding SEO and in blogs is good that each post page has as it's title the post title.
On the following paragraphs, I'm gonna explain what kind of titles does snipsnap use by default and how you can improve them for SEO, with a minimum coding effort.
On SnipSnap each page has as it's title the string
"blog name :: page name", for example, "pabrantes' Weblog :: start" if you are accessing the main page of my blog.
When it comes to blog post on snipsnap the developers -
funzel and
leo - to avoid collisions have chosen the format "DATE/number" for the post's name, for example, 2006-11-29/1 for the 1st post of 29 November 2006, 2006-11-29/2 for the 2nd and so on.
Now what this means is that when you access a direct post page, the page title will be something like " pabrante's Weblog :: 2006-11-29/1" and as you can imagine this is definitely
not optimised for search engines.
Realising this I wanted to implement the underlying tip of the article I've previously mentioned, have as page title the posts subject. I've done it with some minor changes on the
SnipImpl class and on the main.jsp. These means if you want to do this optimisations, you have to download the source, change it the way I'm suggesting, compiling and finally deploy the new version.
Let me introduce the changes on each file.
- Description: This is one of the classes that implements the snip interface and it's the one that actually represents snipsnap pages (AKA snips).
- Location: org.snipsnap.snip
The snip interface has a
getTitle although you'll need to change it a bit in order to give the posts subject when you are requesting it is a blog post.
The code by snipsnap devs:
public String getTitle() {
if (null == nameFormatter) {
nameFormatter = new PathRemoveFormatter();
nameFormatter.setParent(new WeblogNameFormatter());
}
return nameFormatter.format(name);
}
My code:
public String getTitle() {
String title = null;
Snip parent = getParent();
if (parent != null && parent.isWeblog()) {
String postTitle = getContent();
return postTitle.substring(postTitle.indexOf("1") + 2, postTitle
.indexOf("{"));
} else {
if (null == nameFormatter) {
nameFormatter = new PathRemoveFormatter();
nameFormatter.setParent(new WeblogNameFormatter());
}
title = nameFormatter.format(name);
}
return title;
}
The main idea is to check if the snip in question has a parent and that parent is a weblog, if those conditions do happen we are requesting the title of a blog post, so we access it's content and strip out it's subject. Otherwise we just execute the old code.
While implementing this idea I found out that the code related to parents weren't working as I would expect, no snips had parents. Now this might be because I'm using the file system storage and there's a bug on the metadata materialisation or something. Anyway the closest fix I've made up, was to instead of relaying on possible metadata to find out the parent by ourselves.
To do this 2 methods were changed on the SnipImpl class, getParent and getParentName. Once again I'll present the old code and new code for each method.
Snipsnap developers code:
public Snip getParent() {
if (null != parentName && !"".equals(parentName)
&& null == parent) {
parent = SnipSpaceFactory.getInstance().load(parentName);
}
return parent;
}
My code:
public Snip getParent() {
if (null != getParentName() && !"".equals(getParentName())
&& null == parent) {
parent = SnipSpaceFactory.getInstance().load(parentName);
}
return parent;
}
The change was minimal but you'll understand it when I'll show you the getParentName() method.
Snipsnap developers code:
public String getParentName() {
return this.parentName == null ? parentName : this.parent.getName();
}
This is an interesting recursive solution. Although since parentName is never set (once again, maybe due to metadata problems… I really hadn't the time to go investigate that, maybe some other time) getParentName would always be null.
My code:
public String getParentName() {
return this.parentName !=
null ? parentName : resolveParentName();
}
private String resolveParentName() {
String[] snips =
this.getName().split(
"/");
if (snips.length == 1) {
return null;
}
else {
setParentName(snips[0]);
return snips[0];
}
}
My code does the same although instead of using recursion to find out the parent's name I just grab the snipname split it by the character "/" and go fetch the first if the size of the string array is bigger than one.
Keep in mind that for snip B which has A as parent B.getName() returns the string "A/B". Indeed it's a bit bigger but works in perfection.
Regarding java code that's all! Now we just need to do a minor change on the jsp that takes care of the pages titles.
- Description: Like the name says it's the main JSP.
- Location: You can find it on the apps/default folder
Search for the <title> tag in the main.jsp file you'll find the code that renders the format I've already discussed:
<title><c:out value="${app.configuration.name}" default="SnipSnap"/> :: <c:out value="${snip.name}"/></title>
You should change it to:
<title>
<c:choose>
<c:when test="${snip.weblog}">
<c:out value="${app.configuration.name}" default="SnipSnap"/> :: <c:out value="${app.configuration.tagline}"/>
</c:when>
<c:otherwise>
<c:out value="${snip.title}"/>
</c:otherwise>
</c:choose>
</title>
Which mainly does the following, if you are in a weblog snip the title becomes
weblog name :: weblog tagline . Otherwise it will show the pages title, which in the case of the blogs becomes their subject.
Now you can run
ant to compile the new modified snipsnap and you are ready to go!
As you can verify I already have this hack deployed on my blog and I'm not having any problems with it (at least for now).
And that's all folks!