HTML Sitemap Block and Shortcode
Add a visitor-facing list of your pages, posts and other content to any page with a block or shortcode. It lists only what the XML sitemap includes.
On this page
- Add it to a page
- In the block editor
- With the shortcode
- What is listed
- Options
- The markup
- Caching
- Limits
- Developer filters
- hydrogen_seo_html_sitemap_query_args
- hydrogen_seo_html_sitemap_html
- Performance
- FAQ
- Do I need an HTML sitemap if I have an XML sitemap?
- Why is a page missing from the list?
- I published a post and it is not in the list yet. Why?
- Can I show posts grouped by category?
- Should the sitemap page be noindex?
- Can I use more than one on a site?
- Related reading
An HTML sitemap is an ordinary page that lists your site's content as links, for visitors who want an overview or cannot find something through the menu. From version 0.0.31, Hydrogen SEO builds one with the HTML Sitemap block or the [hydrogen_seo_html_sitemap] shortcode. It lists only what your XML sitemap includes, so the two never disagree, nests pages under their parents, and is cached. It is free, needs no account, and adds no script or stylesheet to the page.
Add it to a page
In the block editor
- Create a page, for example Sitemap, or open an existing one.
- Click +, search for HTML Sitemap and insert it. The block is in the Widgets category.
- The block shows the list as visitors will see it. Adjust the options in the sidebar if needed.
- Publish the page and link to it, usually from the footer.
With the shortcode
[hydrogen_seo_html_sitemap]
With no attributes, the shortcode lists every post type your XML sitemap includes, with pages ordered by title and posts by date, newest first. Hydrogen SEO → Sitemap has an HTML sitemap note with the shortcode ready to copy.
What is listed
The HTML sitemap follows the XML sitemap:
- Post types switched on under Hydrogen SEO → Sitemap and not set to noindex site-wide. By default all of them are listed.
- Taxonomies switched on there and not noindex, but only the ones you ask for. By default none are listed.
- Not listed, whatever you ask for: posts and terms set to noindex, drafts, scheduled and private posts, password-protected posts, and terms that have no published posts.
So if a post type is missing, check that it is switched on in the Sitemap settings and is not noindex under robots meta settings. A name that the XML sitemap does not include is dropped without an error.
Each post type and taxonomy gets its own section with a heading, such as Pages and Posts. Hierarchical content is nested: child pages sit under their parent, and child categories under theirs. If a parent is not listed, because it is a draft, noindex or past the limit, its children move to the top level instead of disappearing. A post without a title is listed as (no title). A section with nothing to list is left out.
Options
In the block, Content and Display panels hold the options. In the shortcode they are attributes.
| Block setting | Shortcode attribute | Default | What it does |
|---|---|---|---|
| Content checkboxes, post types | post_types | Every post type in the XML sitemap | Comma list of post type names, such as page,post. post_types="none" lists taxonomies only |
| Content checkboxes, taxonomies | taxonomies | None | Comma list of taxonomy names, such as category,post_tag |
| Order by | orderby | Pages by title, posts by date | title, date (publish date) or modified (last modified date). The default is title for hierarchical post types and date for the others |
| Order | order | A to Z, newest first | asc or desc. The default is ascending for titles and descending for dates |
| Show dates | show_dates | Off | true prints each entry's date after its title, in your site's date format. It is the publish date, or the last modified date when ordering by modified. Terms have no date |
| Entries per section | limit | 500 | The most entries listed per post type or taxonomy, at most 2000 |
| Section heading level | heading_level | 2 | Level of the section headings, 2 to 6 |
Examples:
[hydrogen_seo_html_sitemap post_types="page,post" taxonomies="category" show_dates="true" limit="200"]
[hydrogen_seo_html_sitemap post_types="page" heading_level="3"]
[hydrogen_seo_html_sitemap post_types="none" taxonomies="category,post_tag"]
A value that is not recognised falls back to the default: an unknown orderby, a limit below 1 or a heading level outside 2 to 6. A limit above 2000 is treated as 2000. The limit counts entries that are listed, so noindex posts do not use it up.
The Content panel in the block carries a reminder of the rule above: Only content in the XML sitemap can be listed. Noindex, private and password-protected content is always left out.
The markup
<div class="hydrogen-seo-html-sitemap">
<section class="hydrogen-seo-html-sitemap__section hydrogen-seo-html-sitemap__section--post-type-page">
<h2 class="hydrogen-seo-html-sitemap__heading">Pages</h2>
<ul class="hydrogen-seo-html-sitemap__list">
<li><a href="https://example.com/about/">About</a>
<ul>
<li><a href="https://example.com/about/team/">Team</a></li>
</ul>
</li>
</ul>
</section>
</div>
With Show dates on, each link is followed by <time class="hydrogen-seo-html-sitemap__date" datetime="2026-10-02">October 2, 2026</time>. Taxonomy sections use the class hydrogen-seo-html-sitemap__section--taxonomy-category, with the taxonomy's name at the end.
No CSS is added. The lists take your theme's list and link styles; use the classes above to arrange them in columns or change spacing.
Caching
The listed content is cached together with the XML sitemap, so both are rebuilt by the same events: a post of a public type is saved, trashed or deleted, a term is added, edited or deleted, or a noindex setting changes. Otherwise a copy is kept for a day.
- Only a logged-out visitor's page view fills the cache, so the shared copy is always what the public sees.
- A logged-in view reads the cache. If there is no copy yet, the list is built for that one view and nothing is stored.
- The preview in the block editor is always built fresh.
- The heading level, dates and limit are applied when the list is written, so changing them does not multiply the cached copies.
- A list too large for an object cache to hold (about 900 KB of data) is not cached and is built on each view. Lower the limit, or list fewer post types, if that applies to you.
Nothing is queried on pages that do not contain the block or shortcode.
Limits
- 2000 entries per section is the ceiling. On a site with more posts than that, list pages and categories in the HTML sitemap and let the category archives lead to the posts. A page of several thousand links is of little use to a visitor anyway.
- It cannot list what the XML sitemap leaves out. That is deliberate: the HTML sitemap should not link to a page you have asked search engines not to index. To add a post type, switch it on in the Sitemap settings.
- No search box, pagination or grouping by date or author. It is one list per post type or taxonomy.
- Changes made by plugins that filter queries per visitor are not reflected per visitor, because the list is cached. What a logged-out visitor sees is what is stored.
Developer filters
hydrogen_seo_html_sitemap_query_args
Filters the WP_Query arguments for one post type. Arguments: $args (array), $post_type (string) and $limit (int, the most entries the section will list). posts_per_page, offset, fields and no_found_rows are set after the filter, and only published posts without a password are listed whatever the status arguments say. The result is cached, so the arguments must not depend on who is viewing the page.
// Leave one category out of the Posts section.
add_filter( 'hydrogen_seo_html_sitemap_query_args', function ( $args, $post_type ) {
if ( 'post' === $post_type ) {
$args['category__not_in'] = [ 42 ];
}
return $args;
}, 10, 2 );
hydrogen_seo_html_sitemap_html
Filters the finished markup. Arguments: $html (string, empty when nothing is listed) and $atts (array of the validated attributes: post_types, taxonomies, orderby, order, show_dates, limit, heading_level). It runs on every render, after the cache.
// Add a line above the list.
add_filter( 'hydrogen_seo_html_sitemap_html', function ( $html ) {
return '' === $html ? $html : '<p>Everything on this site, by section.</p>' . $html;
} );
Performance
For each post type, building the list takes one query for the post IDs, one for the few columns an entry needs and one for the robots meta the noindex check reads. Post content and other meta are never loaded. After that, the page is served from the cache until content changes.
FAQ
Do I need an HTML sitemap if I have an XML sitemap?
Search engines do not need it. The XML sitemap is how they find your URLs. An HTML sitemap is for people, and it also adds ordinary internal links to pages that may be many clicks from the homepage. It is worth having on a site with a deep structure and of little use on a ten-page site. See HTML sitemap vs XML sitemap.
Why is a page missing from the list?
In order of likelihood: it is set to noindex, its post type is switched off in the Sitemap settings, it is not published or is password-protected, or the section has reached its limit.
I published a post and it is not in the list yet. Why?
Saving a post clears the cache, so it should appear on the next view. If your site also has a page cache, the sitemap page itself may be served from there; clear that page in your caching plugin.
Can I show posts grouped by category?
Not as nested groups. You can list the categories themselves with taxonomies="category", and each category link leads to its archive of posts.
Should the sitemap page be noindex?
It does not need to be. It is a normal page whose links search engines can follow. Leave it indexable unless you have a reason not to.
Can I use more than one on a site?
Yes. Each block or shortcode is independent, so you can have a page listing pages only and another listing products.