Instantly share code, notes, and snippets.

@maxivak /readme.md
Last active Nov 10, 2018

Embed
What would you like to do?
sitemap.xml for Rails 4 application

Generate sitemap.xml in Rails app

This post shows how to make sitemap.xml for your web site. The sitemap will be accessible by URL http://mysite.com/sitemap.xml

Routes

Myrails::Application.routes.draw do
  get "/sitemap.xml" => "sitemap#index", :format => "xml", :as => :sitemap

end

Controller

# app/controllers/sitemap_controller.rb

class SitemapController < ApplicationController

  def index
    respond_to do |format|
      format.xml
    end
  end

end

View

XML will be generated using XML builder. Create a view file 'sitemap/index.xml.builder' where you can use xml builder methods.

# app/views/sitemap/index.xml.builder

base_url = "http://#{request.host_with_port}/"

xml.instruct! :xml, :version=>"1.0"
xml.tag! 'urlset', 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9', 'xmlns:image' => 'http://www.google.com/schemas/sitemap-image/1.1', 'xmlns:video' => 'http://www.google.com/schemas/sitemap-video/1.1' do
  xml.url do
    xml.loc base_url
  end
  xml.url do
    xml.loc base_url+'about.html'
  end
  xml.url do
    xml.loc base_url+'contacts.html'
  end
end

Generate XML dynamically

To do some refactoring let's prepare some data in controller for static pages and dynamic pages (like products).

controller:

class SitemapController < ApplicationController

  def index

    @pages = ['', 'about.html', 'contacts.html']

    @products = Product.all

    respond_to do |format|
      format.xml
    end
  end

end

change view:

# app/views/index.xml.builder

base_url = "http://#{request.host_with_port}/"

xml.instruct! :xml, :version=>"1.0"
xml.tag! 'urlset', 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9', 'xmlns:image' => 'http://www.google.com/schemas/sitemap-image/1.1', 'xmlns:video' => 'http://www.google.com/schemas/sitemap-video/1.1' do
  xml << (render :partial => 'sitemap/common', pages: @pages)
  xml << (render :partial => 'sitemap/products', items: @products)

end

and our partials:

# app/views/sitemap/_common.xml.builder

base_url = "http://#{request.host_with_port}/"

# pages = ['about.html', 'contacts.html' ]

pages.each do |page|
  xml.url do
    xml.loc base_url+page
  end

end
# app/views/sitemap/_products.xml.builder

items.each do |item|
  xml.url do
    xml.loc product_path(item)
  end

end
@ghost

This comment has been minimized.

ghost commented Jan 26, 2017

This was awesome. Thanks !

@qrush

This comment has been minimized.

qrush commented Feb 3, 2017

This was a ton of help. Thanks!! 👏

@PatrickatPaperlessPCS

This comment has been minimized.

PatrickatPaperlessPCS commented Jul 15, 2017

Really like what you've built but wanted to make note of an issue I ran into for future users:

My sitemap was failing google tests and giving an invalid URL error for items. This was easily fixed by modifying the product partial to include the base URL:

# app/views/sitemap/_products.xml.builder

base_url = "http://#{request.host_with_port}"

items.each do |item|
  xml.url do
    xml.loc base_url+product_path(item)
  end

end

Updated to remove extra / in the base url

@scolobey

This comment has been minimized.

scolobey commented Nov 9, 2017

Found this super useful. One issue I had though. The render partial wasn't delivering the items for some reason, so it was throwing an error in app/views/sitemap/_products.xml.builder saying that items didn't exist. Fixed it by just iterating the products in the index.xml.builder itself. Lazy, but I'm moving on for now.

@zPhumzani

This comment has been minimized.

zPhumzani commented Mar 30, 2018

This sitemap is cool and flexible. For a quick base url just use

# app/views/sitemap/_products.xml.builder

items.each do |item|
  xml.url do
    xml.loc product_url(item)
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment