Table of Contents

How to create sitemap dynamically in Angular 12?

How to Create a Dynamic Sitemap in Angular 12 for SEO Creating an effective sitemap is crucial for Search Engine Optimization (SEO), as it helps search engines...

2026-08-10

How to Create a Dynamic Sitemap in Angular 12 for SEO

Creating an effective sitemap is crucial for Search Engine Optimization (SEO), as it helps search engines crawl and index all the important pages of your website. While static websites handle this easily, Single Page Applications (SPAs) built with frameworks like Angular require a dynamic approach. Since an Angular application primarily loads content via routes rather than traditional server-rendered HTML files, we need to dynamically generate the sitemap data based on the application's routing configuration.

This guide will walk you through the developer-centric process of creating a dynamic sitemap functionality within an Angular 12 environment.

Understanding the Challenge in an SPA Context

For a typical Angular application, the "pages" are defined by the routes set up in your AppRoutingModule. A traditional XML sitemap lists URLs; for an SPA, we need to extract these route definitions and format them into the required XML structure:

<url>
    <loc>https://yourdomain.com/path</loc>
    <lastmod>YYYY-MM-DD</lastmod>
  </url>
  

The challenge is bridging the gap between Angular's internal routing mechanism and the external requirement of an XML sitemap file that search engines can easily read. We will solve this by creating a dedicated service to extract this data.

Step 1: Creating the Sitemap Service

We will use an Angular Service to encapsulate the logic for fetching and formatting the route data. This adheres to the principle of separation of concerns, making our code clean and maintainable—a core concept emphasized in robust application design, similar to how well-structured projects are managed on platforms like https://laravelcompany.com.

Create a new service named SitemapService:

ng generate service sitemap
  

Implement the service to interact with the Angular Router:

sitemap.service.ts

import { Injectable } from '@angular/core';
  import { Router, Routes } from '@angular/router';
  
  // Define a simple interface for our sitemap entries
  export interface SitemapEntry {
    loc: string;
    lastmod?: string; // Optional last modification date
  }
  
  @Injectable({
    providedIn: 'root'
  })
  export class SitemapService {
  
    constructor(private router: Router) { }
  
    /**
     * Gathers all defined routes and formats them into a sitemap-ready structure.
     */
    getSitemapData(): SitemapEntry[] {
      const routes: SitemapEntry[] = [];
  
      // Get the current route configuration from the router
      const routesArray = this.router.config.entries; 
  
      routesArray.forEach(entry => {
        // entry.url is the path, we prepend the base URL for a full URL
        const fullUrl = entry.url.startsWith('/') ? entry.url : `/${entry.url}`;
  
        routes.push({
          loc: fullUrl,
          // In a real application, 'lastmod' would be fetched from the database or file system
          lastmod: new Date().toISOString().split('T')[0] 
        });
      });
  
      return routes;
    }
  }
  

Step 2: Generating the XML Content

Now we need a method to transform this JSON data into the required XML format. We can add this logic directly to our service or create a separate utility function.

sitemap.service.ts (Adding generation logic)

// ... (imports and interface remain the same)
  
  export class SitemapService {
    // ... constructor
  
    getSitemapData(): SitemapEntry[] {
      // ... (logic from above remains here)
      const routes: SitemapEntry[] = [];
      const routesArray = this.router.config.entries; 
  
      routesArray.forEach(entry => {
        const fullUrl = entry.url.startsWith('/') ? entry.url : `/${entry.url}`;
        routes.push({
          loc: fullUrl,
          lastmod: new Date().toISOString().split('T')[0] 
        });
      });
      return routes;
    }
  
    /**
     * Converts the route data into a standard XML sitemap string.
     */
    generateSitemapXml(): string {
      const entries = this.getSitemapData();
      let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/v1">\n';
  
      entries.forEach(entry => {
        xml += `  <url>\n`;
        xml += `    <loc>${entry.loc}</loc>\n`;
        if (entry.lastmod) {
          xml += `    <lastmod>${entry.lastmod}</lastmod>\n`;
        }
        xml += `  </url>\n`;
      });
  
      xml += '</urlset>';
      return xml;
    }
  }
  

Step 3: Integrating and Serving the Sitemap

The final step is to use this service in a component or, more commonly for SEO purposes, configure your Angular build process to generate this file during deployment.

While you can call this.sitemapService.generateSitemapXml() from a component to display it, for external indexing, the best practice is often to use a custom build script (e.g., using Webpack plugins or Angular CLI scripts) to run this service at build time and write the resulting XML file directly into the /dist folder.

Example of how you might trigger generation:

// In your main application component:
  import { Component, OnInit } from '@angular/core';
  import { SitemapService } from './sitemap.service';
  
  @Component({ /* ... */ })
  export class AppComponent implements OnInit {
    sitemapContent: string = '';
  
    constructor(private sitemapService: SitemapService) {}
  
    ngOnInit() {
      // This runs when the component initializes, gathering the data
      this.sitemapContent = this.sitemapService.generateSitemapXml();
      console.log(this.sitemapContent);
  
      // In a production scenario, you would typically use a backend API 
      // to serve this XML file rather than displaying it directly on the UI.
    }
  }
  

Conclusion

Dynamically creating a sitemap in Angular is an exercise in leveraging the framework's routing capabilities to fulfill external SEO requirements. By abstracting the route data into a dedicated service, we ensure our application logic remains clean and testable. While the final deployment strategy involves either generating this XML during the build process or exposing it via a lightweight API endpoint (which aligns with modern backend patterns seen in projects leveraging technologies like those found on https://laravelcompany.com), the core principle remains: use your application's structure to generate accurate, comprehensive metadata for search engines.

Stefan

Stefan

SEO engineer and Laravel developer. Building tools to help Laravel applications rank higher in search results.

Share this article

Back to Blog