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.

7 min read
On this page
  1. Add it to a page
  2. In the block editor
  3. With the shortcode
  4. What is listed
  5. Options
  6. The markup
  7. Caching
  8. Limits
  9. Developer filters
  10. hydrogen_seo_html_sitemap_query_args
  11. hydrogen_seo_html_sitemap_html
  12. Performance
  13. FAQ
  14. Do I need an HTML sitemap if I have an XML sitemap?
  15. Why is a page missing from the list?
  16. I published a post and it is not in the list yet. Why?
  17. Can I show posts grouped by category?
  18. Should the sitemap page be noindex?
  19. Can I use more than one on a site?
  20. 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

  1. Create a page, for example Sitemap, or open an existing one.
  2. Click +, search for HTML Sitemap and insert it. The block is in the Widgets category.
  3. The block shows the list as visitors will see it. Adjust the options in the sidebar if needed.
  4. Publish the page and link to it, usually from the footer.

With the shortcode

text
[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 settingShortcode attributeDefaultWhat it does
Content checkboxes, post typespost_typesEvery post type in the XML sitemapComma list of post type names, such as page,post. post_types="none" lists taxonomies only
Content checkboxes, taxonomiestaxonomiesNoneComma list of taxonomy names, such as category,post_tag
Order byorderbyPages by title, posts by datetitle, date (publish date) or modified (last modified date). The default is title for hierarchical post types and date for the others
OrderorderA to Z, newest firstasc or desc. The default is ascending for titles and descending for dates
Show datesshow_datesOfftrue 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 sectionlimit500The most entries listed per post type or taxonomy, at most 2000
Section heading levelheading_level2Level of the section headings, 2 to 6

Examples:

text
[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

html
<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.

php
// 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.

php
// 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.

Was this page helpful?
Still stuck? Contact support