Skip to content

Instantly share code, notes, and snippets.

@calebhearth
Last active August 29, 2015 13:55
Show Gist options
  • Save calebhearth/8711343 to your computer and use it in GitHub Desktop.
Save calebhearth/8711343 to your computer and use it in GitHub Desktop.
---
title: External Posts in Jekyll
layout: post
external: http://robots.thoughtbot.com/post/55507617156/external-posts-in-jekyll
description: |
If you contribute to more than one blog, you may want to have all of your posts show up in a single stream, even if they aren't hosted on that same site.
---
{{ post.description }}
In my case, I like to have the "external posts" I write here for Giant Robots to show up on my [personal blog], so that I can direct people to a single place to see everything I write. Having the posts all in one place also allows me to use Google Analytics to track clicks from my site to posts on Giant Robots.
At first glance, [Jekyll] doesn't seem suited to this, but let's dive in and see if we can make it work.
[personal blog]: http://calebthompson.io
[Jekyll]: http://jekyllrb.com
## Meta Refresh
The first thing that comes to mind isn't always the best, but let's take a look at my original attempt.
The desire was to keep our Google Analytics page views by setting up a custom layout for external posts that will use a `<meta>` tag to redirect to the post externally after we get our pageview:
YAML [front-matter] in `_posts/2013-07-12-external-posts-in-jekyll.md`:
[front-matter]: http://jekyllrb.com/docs/frontmatter/
---
title: External Posts in Jekyll
layout: external
external_url: http://robots.thoughtbot.com/post/12345/external-posts-in-jekyll
---
`_layouts/external.html`:
<!DOCTYPE html>
<html>
<head>
<title>{% raw %}{{ page.title }}{% endraw %}</title>
<meta http-equiv="refresh" content="0;url={% raw %}{{ page.external_url }}{% endraw %}" />
</head>
<body><!-- Google Analytics JavaScript --></body>
</html>
This does the trick: We get Google Analytics to tell us that we had a page view, but the user is still redirected to the post externally before too long. Even with the `0` as the refresh delay, most browsers will load the entire page and render before redirecting, so unless we want to add an ugly "You are being redirected" message, we need a new solution.
## Conditional when rendering `site.posts`
We already know whether a post is "external" to our site based on the `external_url` key in the front matter. Let's see if we can use that knowledge when rendering the list of posts on our `index.html`.
{% raw %}
{% for post in site.posts %}
<dt><time>{{ post.date | date: "%d %b %Y" }}</time></dt>
<dd>
{% if post.external_url %}
<a href="{{ post.external_url }}">{{ post.title }}</a>
{% else %}
<a href="{{ post.url }}">{{ post.title }}</a>
{% endif %}
</dd>
{% endfor %}
{% endraw %}
Okay, now we have posts rendering in our main post list, but if they have the `external_url` front-matter they will automatically link wherever the post was originally published. Sweet.
Unfortunately, there are a couple of downsides to this approach. First, we are probably confusing the user by linking them to an external post that looks just like the links within our site. Second, we have lost the ability to track page views.
## Solutions
Fortunately, Jekyll has our back.
1. We can add another bit of front-matter to tell us what the actual site is that we're linking to. This allows us to style the links that will take the user away from the domain differently:
```
---
...
external_site: thoughtbot
---
```
2. We can take advantage of the `onclick` attribute to trick Google Analytics into thinking that by clicking on the link, we're actually viewing that page:
```
{% raw %}<a href="{{ post.external_url }}" onclick="_gaq.push(['_trackPageview', '{{ post.url }}']);" >{{ post.title }}</a>{% endraw %}
```
We use `post.url` which actually comes out looking like `/external-posts-in-jekyll` since Google Analytics requires that page views be from a single site.
We could also achieve this without using `onclick` by setting a [data attribute] such as `data-analytics-path` and write JavaScript to find links with that attribute and add a click handler.
[data attribute]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global\_attributes#data-\*
## Bringing it all together
`index.html`:
{% raw %}
<dl>
{% for post in site.posts %}
<dt><time>{{ post.date | date: "%d %b %Y" }}</time></dt>
{% if post.external_url %}
<dd class="{{ post.external_site }}">
<a href="{{ post.external_url }}" onclick="_gaq.push(['_trackPageview', '{{ post.url }}']);" >{{ post.title }}</a>
</dd>
{% else %}
<dd><a href="{{ post.url }}">{{ post.title }}</a></dd>
{% endif %}
{% endfor %}
</dl>
{% endraw %}
`style.css`:
dl dd.thoughtbot:before {
height: 26px;
width: 27px;
content: " ";
background: url("ralph.png") no-repeat;
background-size: cover;
position: relative;
display: inline-block;
top: 4px;
margin-right: 6px; }
front-matter:
---
title: External Posts in Jekyll
layout: post
external_url: http://robots.thoughtbot.com/post/12345/external-posts-in-jekyll
external_site: thoughtbot
---
If you'd like to see what this looks like in practice, all of this code was adapted from my implementation at http://calebthompson.io.
Written by [Caleb Thompson](https://plus.google.com/111599109936753790268/).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment