What is the best approach for redirection of old pages in Jekyll and GitHub Pages?

18,063

Solution 1

The best solution is to use both <meta http-equiv="refresh" and <link rel="canonical" href=

It works very well, Google Bot reindexed my entire website under new links without losing positions. Also the users are redirected to the new posts right away.

<meta http-equiv="refresh" content="0; url=http://konradpodgorski.com/blog/2013/10/21/how-i-migrated-my-blog-from-wordpress-to-octopress/">
<link rel="canonical" href="http://konradpodgorski.com/blog/2013/10/21/how-i-migrated-my-blog-from-wordpress-to-octopress/" />

Using <meta http-equiv="refresh" will redirect each visitor to the new post. As for Google Bot, it treats <link rel="canonical" href= as 301 redirect, the effect is that you get your pages reindexed and that is what you want.

I described whole process how I moved my blog from Wordpress to Octopress here. http://konradpodgorski.com/blog/2013/10/21/how-i-migrated-my-blog-from-wordpress-to-octopress/#redirect-301-on-github-pages

Solution 2

Have you tried the Jekyll Alias Generator plugin?

You put the alias urls in the YAML front matter of a post:

---
  layout: post
  title: "My Post With Aliases"
  alias: [/first-alias/index.html, /second-alias/index.html]
---

When a user visits one of the alias urls, they are redirected to the main url via a meta tag refresh:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta http-equiv="refresh" content="0;url=/blog/my-post-with-aliases/" />
  </head>
</html>

See also this blog post on the subject.

Solution 3

redirect-from plugin

https://github.com/jekyll/jekyll-redirect-from#redirect-to

It is supported by GitHub and makes it easy:

_config.yml

gems:
  - jekyll-redirect-from

a.md

---
permalink: /a
redirect_to: 'http://example.com'
---

as explained at: https://help.github.com/articles/redirects-on-github-pages/

Now:

firefox localhost:4000/a

will redirect you to example.com.

The plugin takes over whenever the redirect_to is defined by the page.

Tested on GitHub pages v64.

Note: this version has a serious recently fixed bug which wrongly reuses the default layout for the redirect: https://github.com/jekyll/jekyll-redirect-from/pull/106

Manual layout method

If you don't feel like using https://github.com/jekyll/jekyll-redirect-from it's easy to implement it yourself:

a.md

---
layout: 'redirect'
permalink: /a
redir_to: 'http://example.com'
sitemap: false
---

_layouts/redirect.html based on Redirect from an HTML page :

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Redirecting...</title>
  {% comment %}
    Don't use 'redirect_to' to avoid conflict
    with the page redirection plugin: if that is defined
    it takes over.
  {% endcomment %}
  <link rel="canonical" href="{{ page.redir_to }}"/>
  <meta http-equiv="refresh" content="0;url={{ page.redir_to }}" />
</head>
<body>
  <h1>Redirecting...</h1>
  <a href="{{ page.redir_to }}">Click here if you are not redirected.<a>
  <script>location='{{ page.redir_to }}'</script>
</body>
</html>

Like this example, the redirect-from plugin does not generate 301s, only meta + JavaScript redirects.

We can verify what is going on with:

curl localhost:4000/a

Solution 4

This solution allows you to use true HTTP redirects via .htaccess — however, nothing involving .htaccess will work on GitHub pages because they do not use Apache.

As of May 2014 GitHub Pages supports redirects, but according to the jekyll-redirect-from Gem documentation they are still based on HTTP-REFRESH (using <meta> tags), which requires full a page load before redirection can occur.

I don't like the <meta> approach so I whipped up a solution for anyone looking to provide real HTTP 301 redirects within an .htaccess file using Apache, which serves a pre-generated Jekyll site:


First, add .htaccess to the include property in _config.yml

include: [.htaccess]

Next, create an .htaccess file and be sure to include YAML front matter. Those dashes are important because now Jekyll will parse the file with Liquid, Jekyll's templating language:

---
---
DirectoryIndex index.html

RewriteEngine On
RewriteBase /

...

Make sure your posts that require redirects have two properties like so:

---
permalink: /my-new-path/
original: blog/my/old/path.php
---

Now in .htaccess, just add a loop:

{% for post in site.categories.post %}
  RewriteRule ^{{ post.original }} {{ post.permalink }} [R=301,L]
{% endfor %}

This will dynamically generate .htaccess every time you build the site, and the include in your config file ensures that .htaccess makes it into _site directory.

RewriteRule ^blog/my/old/path.php /my-new-path/ [R=301,L]

From there, it's up to you to serve _site using Apache. I normally clone the full Jekyll repo into a non-webroot directory, then my vhost is a symlink to the _site folder:

ln -s /path/to/my-blog/_site /var/www/vhosts/my-blog.com

Tada! Now Apache can serve the _site folder from your virtual root, complete with .htaccess-powered redirects that use whichever HTTP response code you desire!

You could even get super fancy and use a redirect property within each post's front matter to designate which redirect code to use in your .htaccess loop.

Solution 5

The best option is to avoid url changes altogether by setting the permalink format in _config.yml to match your old blog.

Beyond that, the most complete solution is generating redirect pages, but isn't necessarily worth the effort. I ended up simply making my 404 page a bit friendlier, with javascript to guess the correct new url. It doesn't do anything for search, but actual users can get to the page they were looking for and there's no legacy stuff to support in the rest of the code.

http://tqcblog.com/2012/11/14/custom-404-page-for-a-github-pages-jekyll-blog/

Share:
18,063

Related videos on Youtube

Mailo Světel
Author by

Mailo Světel

Updated on February 26, 2020

Comments

  • Mailo Světel
    Mailo Světel over 4 years

    I have blog on github pages - jekyll

    What is the best way to solve url strategy migration?

    I found the best practice in common is create htaccess like so

    Redirect 301 /programovani/2010/04/git-co-to-je-a-co-s-tim/ /2010/04/05/git-co-to-je-a-co-s-tim.html
    

    But it does not seems to work with Github. Another solution i found is create rake task, which will generate redirection pages. But since it's an html, it's not able to send 301 head, so SE crawlers will not recognize it as an redirection.

  • Mailo Světel
    Mailo Světel about 12 years
    SE is not what bother me. I am getting 404 by links from other sites/forums. I've made fake pages with zero refresh time which will "redirect" user. I did test it in webmaster tools and it seems crawler is also happy with that. But i am not ;)
  • Janikan
    Janikan about 12 years
    If you are still having problems with 404 errors, shoot me a link to one of them and I'll take a look and see if I can tell what's going on.
  • Mailo Světel
    Mailo Světel about 12 years
    Right now i resolved it by the fake pages. One of the former 404 was rooland.cz/programovani/2010/04/git-co-to-je-a-co-s-tim . I am generating them by this git.io/UrlZaQ . The script is terrible, but it do what i need
  • tekknolagi
    tekknolagi over 11 years
    GitHub Pages does not use plugins
  • ms-ati
    ms-ati over 11 years
    @tekknolagi Perhaps I don't understand GitHub Pages. But if you are running jekyll, and just posting the static site to Github, then this would work, as the generated pages would include meta refreshes for the old urls?
  • tekknolagi
    tekknolagi over 11 years
    that is correct, but GitHub won't run Jekyll with the plugins, just serve the compiled static site
  • Mailo Světel
    Mailo Světel almost 11 years
    I've ended up with something like this. I generate the redirection pages locally by Rake task and push them to Github as static pages
  • Joel Glovier
    Joel Glovier over 10 years
    The permalink attribute just tells jekyll what to make the new generated URL, but doesn't provide anything in the way of redirects for old permalink structure that might have been in place prior.
  • Mike
    Mike over 10 years
    You mean redirects of old pages on the old site? Like this is the third time the page has been moved?
  • smholloway
    smholloway over 10 years
    I followed this approach and it was pretty easy. I ran into two issues: 1) the plugin wouldn't run--I had to set safe: false in _config.yml 2) I was going to have to create over 400 alias entries. Instead of hand-crafting those, I automated it with a Python script: gist.github.com/smholloway/8726873
  • Mike Cole
    Mike Cole about 10 years
    When moving to GitHub pages, this worked for me: help.github.com/articles/redirects-on-github-pages. It looks like it does everything you mentioned.
  • Yuri
    Yuri about 9 years
    Does the effect of using canonical imply that Google will reindex the pages from scratch, or does it transfer the ranking score to the new page? Can you clarify how this approach affects the page ranking?
  • Erik Berkun-Drevnig
    Erik Berkun-Drevnig almost 9 years
    Won't the <meta http-equiv="refresh" cause an infinite redirect loop? That is what I am getting, maybe I am doing something wrong?
  • Erik Berkun-Drevnig
    Erik Berkun-Drevnig almost 9 years
    Would this support more complex redirects? Such as with a single domain if I wanted to redirect links like example.com/index.html to example.com or example.com/some-post/index.html to example.com/some-post/.
  • vossad01
    vossad01 over 7 years
    @ErikBerkun-Drevnig the content seen above is added on the "old" page and should point to the "new" page. Done that way, there should not be an infinite loop.
  • Sharath kumar
    Sharath kumar about 7 years
    This seems great! But what if there are multiple original(previous links now hitting 404) links for a post?
  • Chris Ruppel
    Chris Ruppel about 7 years
    The solution would involve a more complex piece of logic when you generate the .htaccess file. For example, you could convert the YAML so that original is an array instead of a string. Then you need a nested loop so that every original entry generates a redirect to permalink. Take this code as a starting point and experiment for yourself!
  • Sharath kumar
    Sharath kumar about 7 years
    Thank you. I got it to work as you suggested. I've used this method for a tutorial.
  • Corey Goldberg
    Corey Goldberg about 6 years
    since this solution doesn't work on GitHub pages, it doesn't answer the question whatsoever. The number of irrelevant answers is infinite, so why post this at all?
  • Chris Ruppel
    Chris Ruppel about 6 years
    @CoreyGoldberg mostly to give people like you something to comment about ;)
  • stragu
    stragu almost 6 years
    If anyone is wondering: those two lines should be included in your <head> block.