My customized Jekyll RSS feed template including Google Analytics campaign tracking and pubsubhubbub support.
I recently moved my personal blog from Wordpress to Jekyll. I made this move primarily as a way to keep my webdev chops current and experiment with Ruby, Amazon S3, Cloudfront, and Markdown. The act of porting my site into Jekyll was fraught with learning opportunities some of which I will begin to document here to help others (as so many have helped me.)
RSS remains my most used form of content discovery. (Sorry Twitter, Facebook, and others.) It is important to me that my site cater to throwbacks like myself and contain an easily findable RSS feed.
Out-of-the-box Jekyll does not create an RSS feed for you. Like so much else that makes me love Jekyll, you need to think about and craft by hand all the functionality you want on your site. No bloat. No unnecessary features. After much searching I found some great starting points but none of them accomplished all of what I needed. My requirements were as follows:
- Atom as opposed to RSS. (This old debate probably doesn’t mean much to folks who weren’t building Web sites in the early naughts.)
- Support for the pubsubhubbub protocol.
- Usage tracking via Google Analytics campaign variables.
1. atom.xml
I created a document named atom.xml
at my Jekyll docroot. Here is the template I placed within this file:
---
layout: nil
title : Atom Feed
---
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="https://www.w3.org/2005/Atom">
<link rel="hub" href="https://pubsubhubbub.appspot.com" />
<title type="text" xml:lang="en">{{ site.name }}</title>
<link type="application/atom+xml" href="{{ site.url }}/atom.xml" rel="self"/>
<link href="{{ site.url }}/"/>
<updated>{{ site.time | date: "%Y-%m-%dT%H:%M:%SZ" }}</updated>
<id>{{ site.url }}/</id>
<author>
<name>{{ site.author.name }}</name>
<email>{{ site.author.email }}</email>
</author>
<rights type="text">Copyright © {{ site.time | date: "%Y" }} {{ site.author }}. All rights reserved.</rights>
{% for post in site.posts limit:10 %}
<entry>
<title>{{ post.title | xml_escape }}</title>
<link rel="alternate" type="text/html" href="{{ site.url }}{{ post.url }}/?utm_source=RSS&utm_medium=RSS&utm_campaign={{ post.title | replace: ',','' | replace: ' ', '' | xml_escape }}" />
<published>{{ post.date | date: "%Y-%m-%dT%H:%M:%SZ" }}</published>
<updated>{{ post.date | date_to_xmlschema }}</updated>
<id>{{ site.url }}{{ post.id }}</id>
<content type="html"><![CDATA[ {{ post.content | markdownify }} ]]></content>
</entry>
{% endfor %}
</feed>
This correctly formatted atom feed does a few things that other templates I found did not do.
- The line
<link rel="hub" href=https://pubsubhubbub.appspot.com />
tells feed readers to subscribe to changes via pubsubhubbub. Allowing for rapid content updates when new content is posted without waiting for a feed reader to re-poll my site. - I appended each link with this code
?utm_source=RSS&utm_medium=RSS&utm_campaign={{ post.title }}"
which tells Google Analytics to record ever click through my feed as a campaign variable of Source: RSS, Medium: RSS, Campaign: Post Title. The additional filters placed on the post title{{ post.title | replace: ',','' | replace: ' ', '' | xml_escape }}
allow the post title to be passed as a single variable to G.A.
2. Automatic Feed Discovery
To make the existence of my RSS feed known to browsers, I added this code to my <head>
.
<link rel="alternate" type="application/atom+xml" title="{{ site.name }}" href="{{ site.url }}/atom.xml" />
3. pubsubhubbub notification
The last step was to notify pubsubhubbub everytime there was a new update to the feed. If you read my blog, you probably know that I’m not a programmer. So I did what any enterprising non-coder would do, I scoured Github for someone who had already solved this problem.
I found this amazingly simple PHP script which not only notifies pubsubhubbub but also pings a number of other web services. After configuring the variables, simply ping the script when you’ve posted new content and feed readers will be notified of your updates.
To Do
One day I plan on scripting this ping into my Jekyll deployment script so I don’t need to do it manually….Haven’t gotten around to that yet.
Extra bonus points. If any of you know Ruby and can tell me how to replace the functionality in the PHP ping script with a Rakefile task, I’ll buy you a beer or five.
UPDATE I finally figured out how to ping pubsubhubbub without that PHP script. I’ve posted about it on this blog.