Instantly share code, notes, and snippets.

@maxivak /readme.md
Last active Jul 12, 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
@williej

This comment has been minimized.

Show comment
Hide comment
@williej

williej Jan 26, 2017

This was awesome. Thanks !

williej commented Jan 26, 2017

This was awesome. Thanks !

@qrush

This comment has been minimized.

Show comment
Hide comment
@qrush

qrush Feb 3, 2017

This was a ton of help. Thanks!! 👏

qrush commented Feb 3, 2017

This was a ton of help. Thanks!! 👏

@PatrickatPaperlessPCS

This comment has been minimized.

Show comment
Hide comment
@PatrickatPaperlessPCS

PatrickatPaperlessPCS 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

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.

Show comment
Hide comment
@scolobey

scolobey 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.

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.

Show comment
Hide comment
@zPhumzani

zPhumzani 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

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