Skip to content

XML Sitemaps

Dylan Fisher edited this page Jul 3, 2019 · 3 revisions

This is a quick pattern that can be used to generate sitemaps for small or medium sized projects, where the contents of the sitemap can fit into a single file. For larger or more complex sites, you may want to use a more robust solution.

Add builder to Gemfile

gem 'builder'

Add sitemap.xml to routes.rb

get '/sitemap.xml', to: 'sitemap#index', format: :xml

Create SitemapController

class SitemapController < ForestController
  def index
    @pages = Page.all.published

    respond_to do |format|
      format.xml
    end
  end
end

Create views

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

cache Page.cache_key, expires_in: 4.weeks do
  xml.instruct! :xml, version: '1.0'
  xml.tag! 'urlset',
           'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
           'xmlns:xhtml' => 'http://www.w3.org/1999/xhtml',
           'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
           'xmlns:image' => 'http://www.google.com/schemas/sitemap-image/1.1',
           'xsi:schemaLocation' => 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd' do
    xml << render('sitemap/pages', pages: @pages)
  end
end
# /app/views/sitemap/_pages.xml.builder

pages.each do |page|
  xml.url do
    if I18n.available_locales.length > 1
      xml.loc page_url(page.path, locale: I18n.default_locale)
    else
      xml.loc page_url(page.path)
    end

    if I18n.available_locales.length > 1
      I18n.available_locales.each do |locale|
        xml.tag! 'xhtml:link', rel: 'alternate', hreflang: locale, href: page_url(page.path, locale: locale)
      end
    end

    xml.lastmod page.updated_at.to_date

    page.typical_media_items.each do |media_item|
      xml.tag!('image:image') do
        xml.tag!('image:loc', media_item.attachment.url(:large))

        if media_item.title.present?
          xml.tag! 'image:title' do
            xml.cdata! stripdown(media_item.title)
          end
        end

        if media_item.caption.present?
          xml.tag! 'image:caption' do
            xml.cdata! stripdown(media_item.caption)
          end
        end
      end
    end
  end
end