AEM sitemap - request two sitemaps in the same Node | Community
Skip to main content
neoz_zilon
May 1, 2025

AEM sitemap - request two sitemaps in the same Node

  • May 1, 2025
  • 4 replies
  • 957 views

Hi team ,

 

I have a request to implement two different Sling sitemaps in the same page/node which will be the language page.

 

one will be for pages and the other for assets , the content is irrelevant but I’m looking for tips more on the option to invoke or schedule two different sitemaps in the same node like:

 

 

- com.mypackage.MyCustomSitemap1.java

- com.mypackage.MyCustomSitemap2.java 

 

and invoke the sitemap like :

 

en.sitemap.xml

en.sitemap2.xml 

 

I tried setting it up as a different selector extending from ResourceTreeSitemapGenerator and set a selector in here , also registering in the sitemap servlet configuration but it is not working , does anybody has any advice how to configure this scenario ? Is highly appreciate it.

 

 

 

 

4 replies

SantoshSai
Community Advisor
Community Advisor
May 1, 2025

Hi @neoz_zilon,

You can register multiple custom sitemap generators for the same page node (like a language root) in AEM using Sling Sitemap. Each one can be tied to a different selector, like sitemap.xml and sitemap-assets.xml. Here's how I usually approach it:

  1. Create separate generators
    Build two classes extending ResourceTreeSitemapGenerator:

    • One for pages (eg. MyCustomSitemap1.java)

    • One for assets (eg. MyCustomSitemap2.java)

  2. Register with unique names (selectors)
    Give each generator a unique name using the SitemapGenerator.NAME property. This controls the selector used in the URL.

    Eg.

    @Component( service = SitemapGenerator.class, property = { SitemapGenerator.NAME + "=pages" // becomes sitemap.xml } ) public class MyCustomSitemap1 extends ResourceTreeSitemapGenerator { // logic for pages } @Component( service = SitemapGenerator.class, property = { SitemapGenerator.NAME + "=assets" // becomes sitemap-assets.xml } ) public class MyCustomSitemap2 extends ResourceTreeSitemapGenerator { // logic for assets }
  3. Configure the Sitemap Servlet
    Make sure the sitemap servlet is set up to handle both selectors:

    { "sling.servlet.selectors": ["sitemap", "sitemap-assets"], "sling.servlet.extensions": "xml", "sling.servlet.resourceTypes": ["sling:Folder", "cq:Page"] }

    (Or use a factory config for org.apache.sling.sitemap.SitemapServlet.)

  4. Access the URLs
    Once everything is registered, you should be able to access:

    • /en.sitemap.xml --> page sitemap

    • /en.sitemap-assets.xml --> asset sitemap

    These selectors are customizable based on what you register.

References: https://github.com/apache/sling-org-apache-sling-sitemap

https://javadoc.io/doc/org.apache.sling/org.apache.sling.sitemap/latest/org/apache/sling/sitemap/spi/generator/SitemapGenerator.html

https://www.tothenew.com/blog/exploring-apache-sling-sitemap-generator-with-customization-in-aem/

Hope that helps!

 

Santosh Sai
neoz_zilon
May 1, 2025

hi @santoshsai 

 

Thanks for your reply! this is what I needed.

 

Just have one extra question, I'm unable to resolve the CONSTANT: SitemapGenerator.NAME and reviewed the source code as well for this one, and don't see the constant. Do you know if it is another class, or the value of this constant, to add it.

 

Really appreciate it. 

SantoshSai
Community Advisor
Community Advisor
May 1, 2025

@neoz_zilon 

The constant SitemapGenerator.NAME is not defined in the Sling Sitemap API. That line is a common shorthand used in examples, but in actual implementation, you need to manually define the property key as a string.

Refer: 

@Component(
    service = SitemapGenerator.class,
    property = {
        "sling.sitemap.name=pages"  // this defines the selector as 'sitemap-pages.xml'
    }
)
public class MyCustomSitemap1 extends ResourceTreeSitemapGenerator {
    // implement logic for page sitemap
}

@Component(
    service = SitemapGenerator.class,
    property = {
        "sling.sitemap.name=assets"  // this defines the selector as 'sitemap-assets.xml'
    }
)
public class MyCustomSitemap2 extends ResourceTreeSitemapGenerator {
    // implement logic for asset sitemap
}

This maps to the selector used in the sitemap URL.

  • So /en.sitemap-pages.xml and /en.sitemap-assets.xml will be the result.

Santosh Sai
AmitVishwakarma
Community Advisor
Community Advisor
May 2, 2025

Hi @neoz_zilon ,

To create two separate sitemaps (e.g., one for pages and one for assets) under the same AEM node (like /en) using Apache Sling Sitemap in AEM, follow this implementation approach:


Step-by-Step Working Solution

1. Create Two Sitemap Generator Components

MyCustomPageSitemap.java

@Component( service = SitemapGenerator.class, property = { "sling.sitemap.name=pages" // becomes selector "sitemap-pages.xml" } ) public class MyCustomPageSitemap extends ResourceTreeSitemapGenerator { // Optional: override methods to customize page sitemap logic }

MyCustomAssetSitemap.java

@Component( service = SitemapGenerator.class, property = { "sling.sitemap.name=assets" // becomes selector "sitemap-assets.xml" } ) public class MyCustomAssetSitemap extends ResourceTreeSitemapGenerator { // Optional: override methods to customize asset sitemap logic }

Note: There's no constant like SitemapGenerator.NAME in the current Sling Sitemap API — use string literal: "sling.sitemap.name=your-selector"

2. Sitemap Servlet Configuration (IMPORTANT)

If you need to ensure the sitemap servlet can respond to both selectors:

org.apache.sling.sitemap.SitemapServlet.cfg.json (OSGi config file)

{ "sling.servlet.selectors": [ "sitemap-pages", "sitemap-assets" ], "sling.servlet.extensions": ["xml"], "sling.servlet.resourceTypes": [ "cq:Page", "sling:Folder" ] }

You can also create this config via the Web Console or in Code (OSGi Factory Config).

3. Deploy & Access

Assuming the language root is /content/site/en, these URLs will now work:

/content/site/en.sitemap-pages.xml /content/site/en.sitemap-assets.xml

Verify below:

 - Both components use @Component(service = SitemapGenerator.class)
 - You’ve used unique selectors: sitemap-pages, sitemap-assets
- Your servlet is configured to recognize those selectors
- You’re requesting sitemaps from nodes of type cq:Page or sling:Folder
- The sitemap service is enabled for the site root in /conf (if using configuration-based setup)

Regards,
Amit

 

 

neoz_zilon
May 2, 2025

HI ,

 

Thanks for the detailed instructions, I tried this option but didn't work.

 

even turned debug logs nothing ... Only triggers doing the en.sitemap.xml 

 

but nothing for en.sitemap-pages.xml or en.sitemap-assets.xml

 

@Component(
service = SitemapGenerator.class,
property = {
"sling.sitemap.name=assets" // becomes selector "sitemap-assets.xml"
}
)

public class AssetsSitemapGenerator extends ResourceTreeSitemapGenerator {
@Component(
service = SitemapGenerator.class,
property = {
"sling.sitemap.name=pages" // becomes selector "sitemap-pages.xml"
}
)

public class PagesAndAssetsSitemapGenerator extends ResourceTreeSitemapGenerator {

 

 

 

 

 

 

 

Level 2
May 2, 2025

@neoz_zilon I bet if he'll answer back - because his all answers are form AI tool.

neoz_zilon
May 2, 2025

None of the proposed solutions worked, not sure if anybody has tested this one, and it might be a reason why there are no examples about this one ... If anyone has any clues'll appreciate it, if I find the way to fix it, I'll share it.