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.
Views
Replies
Total Likes
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:
Create separate generators
Build two classes extending ResourceTreeSitemapGenerator:
One for pages (eg. MyCustomSitemap1.java)
One for assets (eg. MyCustomSitemap2.java)
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
}
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.)
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://www.tothenew.com/blog/exploring-apache-sling-sitemap-generator-with-customization-in-aem/
Hope that helps!
Views
Replies
Total Likes
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.
Views
Replies
Total Likes
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.
Views
Replies
Total Likes
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
Views
Replies
Total Likes
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 {
Views
Replies
Total Likes
@neoz_zilon I bet if he'll answer back - because his all answers are form AI tool.
Views
Replies
Total Likes
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.
Views
Replies
Total Likes
Views
Likes
Replies
Views
Likes
Replies
Views
Likes
Replies
Views
Likes
Replies