Configure an xml sitemap using Firebase

As is pointed out on the Google Search Console guidelines, it's recommended to build a sitemap and make it available to Google.

There are various formats supported by Google, in this post I will cover how to build an xml sitemap using Firebase.

Let's start with a simple skeleton of an xml sitemap:

xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 
    <url>
        <loc>https://erikmartinjordan.com/blog</loc>
        <lastmod>2020-10-20</lastmod>
    </url>
    <url>
        <loc>https://erikmartinjordan.com/projects</loc>
        <lastmod>2020-10-20</lastmod>
    </url>
    <url>
        <loc>https://erikmartinjordan.com/about</loc>
        <lastmod>2020-10-20</lastmod>
    </url>
</urlset>

In this example, I will configure the file to display the sitemap from https://erikmartinjordan.com/sitemap.xml.

Server configuration

The first step is to configure the Firebase server editing firebase.json:

json
"rewrites": [
  {
    "source": "/sitemap.xml",
    "function": "buildSitemap"
  },
  {
    "source": "!/sitemap.xml",
    "function": "preRender"
  }
]

If the user accesses to /sitemap.xml, Firebase will run the buildSitemap function.

Otherwise, it'll display a normal page using the preRender function. If you don't know what a preRender function does, you can check this post.

Creating the function

We'll create a Firebase function in ../functions/index.js.

This function returns a string with the sitemap info:

javascript
exports.buildSitemap = functions.https.onRequest((request, response) => {

    let sitemapHeader = `<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`; 
    
    let blogURL       = `<url><loc>https://erikmartinjordan.com/blog</loc><lastmod>2020-10-20</lastmod></url>`;
    let projectsURL   = `<url><loc>https://erikmartinjordan.com/projects</loc><lastmod>2020-10-20</lastmod></url>`;
    let aboutURL      = `<url><loc>https://erikmartinjordan.com/about</loc><lastmod>2020-10-20</lastmod></url>`;
    
    let sitemapFooter = `</urlset>`;
    
    let sitemapString = sitemapHeader + blogURL + projectsURL + aboutURL + sitemapFooter;
    
    response.set('Content-Type', 'text/xml');
    response.status(200).send(sitemapString);
    
});

That's it.

Note: generate URLs dynamically

The benefit of using Firebase functions is that you could generate URLs dynamically by accessing your database.

Example:

javascript
exports.buildSitemap = functions.https.onRequest(async (request, response) => {

    let sitemapHeader = `<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`; 
    
    let blogURL       = `<url><loc>https://erikmartinjordan.com/blog</loc><lastmod>2020-10-20</lastmod></url>`;
    let projectsURL   = `<url><loc>https://erikmartinjordan.com/projects</loc><lastmod>2020-10-20</lastmod></url>`;
    let aboutURL      = `<url><loc>https://erikmartinjordan.com/about</loc><lastmod>2020-10-20</lastmod></url>`;
    
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Reading data dynamically from the database
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    let snapshot      = await admin.database().ref('blog').once('value');
    let posts         = snapshot.val();
    let postURLs      = Object.keys(posts).reduce((acc, url) => {
        
        acc = acc + `<url><loc>https://erikmartinjordan.com/${url}</loc><lastmod>${posts[url].date}</lastmod></url>`;
        
        return acc;
        
    }, ''); 
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    let sitemapFooter = `</urlset>`;
    
    let sitemapString = sitemapHeader + blogURL + projectsURL + aboutURL + postURLs+ sitemapFooter;
    
    response.set('Content-Type', 'text/xml');
    response.status(200).send(sitemapString);
    
});

The URLs of the blog posts are generated automatically by reading the database.

Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.