views:

673

answers:

3

If you google "will_paginate" and "ajax", the top result is this blog post: But the original author of will_paginate says to not use this method (bad for SEO/spiders) ...

But I cant get the original authors method to work (his javascript kills all my links). An other gentleman suggests a similar method to mislav's (the original will_paginate author) concept. But I cant get that to work either.

so .... what is the best way to paginate using AJAX, and stay SEO friendly? (for RAILS >2.1)

A: 

Unfortunately, I don't think you can use Ajax in the way you want and still stay SEO friendly as far as the paginated content. The problem is that the robots of Google and friends, as far as I know, won't go through your content using XHR requests so they simply won't see that content.

That said, if the paginated items each have their own static, SEO-friendly pages (or are otherwise statically available on your site), the content will still find its way into their engines. This is the way you'll probably want to go.

fig
+4  A: 

Seo friendly and unobtrusive javascript goes hand in hand. What you can do is the following.

  • Code the entire site as if only html is enabled (incl your pagination thing)
  • Use respond_to and serve only the list of items if the request comes in from js
  • Using onDomReady from whatever library you pick you attempt to catch all pagination links and add an onclick event which triggers an ajax call to that new view and returns the result. You put that result into the container containing the data you are paginating. The onclick then returns false.
  • To give your users a better user experience you can add some features like active links etc to the same javascript method.

Using this approach the pagination will work for JS and non-js as the non-js users (including Googlebot) will traverse your pagination as normal. Only in the event that the user has javascript enabled, the container with data will be updated with new results.

Tomh
"Create a view and map a route to it." should be: use respond_to and serve only the list of items if the request comes in from js.
Andrew Vit
Thanks modified the answer
Tomh
+2  A: 

Tomh's answer is correct. Just for shiggles, I prototyped a quick implementation. Here's a screencast that shows it using Ajax when Javascript is enabled (your users) and still having pretty URLs when Javascript is disabled (Google). And here are a few code snippets to get you rolling on it.

config/routes.rb:

map.connect 'items/:page', :controller => "items", :action => "index", :page => 1

app/controllers/items_controller.rb:

class ItemsController < ApplicationController
  def index
    @items = Item.paginate(:all, :page => params[:page])

    respond_to do |format|
      format.html
      format.js do
        render :update do |page|
          page.replace_html :items, :partial => "items"
          page << "ajaxifyPagination();"
        end
      end
    end
  end
end

app/views/items/index.html.erb:

<h1>Listing items</h1>

<div id="items">
  <%= render :partial => "items" %>
</div>

app/views/items/_items.html.erb:

<%= will_paginate @items %>

<table>
  <% for item in @items %>
    <tr>
      <td><%= item.id %></td>
    </tr>
  <% end %>
</table>

layout:

<%= javascript_include_tag :defaults %>

public/javascripts/application.js:

$(document).ready(function() {
    ajaxifyPagination();
});

function ajaxifyPagination() {
    $(".pagination a").click(function() {
     $.ajax({
       type: "GET",
       url: $(this).attr("href"),
       dataType: "script"
     });
     return false;
    });
}

My example uses jQuery (with jRails), but it's straightforward to do with Prototype as well.

Ian Terrell
+1 for 'shiggles' - you can learn new terminology every day. Oh, good answer too
DanSingerman