Sitemaps with ExpressionEngine ~ Create an index and organize entries by year or month

Sitemap Index with ExpressionEngine

Sites that are driven by new entries every week can quickly grow to have thousands of entries in a channel. In which case, having a single sitemap is very taxing on resources, and the end result is a sitemap that is slow to render.

SEO discussions are the politics of web design. Page load speed and resource usage on the other hand are something everyone can agree on. My goal is to show a sustainable solution that is considerate of resources and quick to render.

The example below creates a yearly archive of posts. It can be easily modified to create a monthly archive if necessary.

P.S: I formatted the code for readability and added comments to make it self explanatory

Sitemap Index Template

<?xml version="1.0" encoding="UTF-8">
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 
    http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd">

{!-- Use EEs channel:month_links tag to generate years or months of entries --}
{exp:channel:month_links channel="articles" limit="10000" status="not closed"}
{year_heading}
<sitemap>

{!-- Link to sitemap for specific year --}
<loc>{site_url}/sitemap/entries-{year}.xml</loc>

{!-- Get the date of the most recent entry --}
{exp:channel:entries channel="articles" dynamic="no" status="not closed" limit="1" orderby="edit_date" sort="desc" year="{year}" disable="member_data|pagination|categories|custom_fields|relationships"}

<lastmod>{edit_date format='%Y-%m-%dT%H:%i:%sZ'}</lastmod>
{/exp:channel:entries}
</sitemap>
{/year_heading}
{/exp:channel:month_links}
</sitemapindex>

Next step is to create a template group named sitemap and add a template named entries to it. Then your template will look something like this:

Sitemap Entries Template

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" 
    xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 
    http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">

{!-- Use entries_year segment from template route to determine year --}
{exp:channel:entries channel="articles" status="not closed" dynamic="no" orderby="entry_date" sort="desc" disable="member_data|pagination|categories|custom_fields|relationships" limit="5000" year="{segment:entries_year}"}

<url>
{!-- Hardcoding URL is highly recommended and saves seconds when dealing with 1000s of entries --}
<loc>http://domain.com/news/{url_title}</loc>
<lastmod>{edit_date format="%Y-%m-%dT%H:%i:%sZ"}</lastmod>
<priority>1.0</priority>  
<changefreq>daily</changefreq>
</url>
{/exp:channel:entries}  
</urlset>

Template Route

The last step is to set the template route for /sitemap/entries to the following:

/sitemap/entries-{entries_year:alpha_numeric}.xml

Reference

  1. Sitemap Index (Google)
  2. Template Routes (ExpressionEngine)