Exclude children from the sitemap

I found this old topic: Exclude children of a page from sitemap.xml?

I’d like to exclude all children that are under my “changelogs” template.

If I try the suggested solution:

<?php if (in_array($p->uri(), $ignore) || in_array($p->parent()->uri(), $ignore)) continue ?>

I get an error “Call to a member function uri() on null”.

My code:

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

  <?php foreach ($pages as $p): ?>
    <?php if (in_array($p->uri(), $ignore)) continue ?>
      <url>
        <loc><?= html($p->url()) ?></loc>
        <lastmod><?= $p->modified('c') ?></lastmod>
        <priority><?= ($p->isHomePage()) ? 1 : number_format(0.5 / $p->depth(), 1) ?></priority>
      </url>
  <?php endforeach ?>

</urlset>

Before calling $p->parent()->uri() you have to check if the page has a parent, otherwise you get the error.

1 Like

Ah of course! Now I don’t get the error but I still get all children listed in the sitemap.

<?php if (in_array($p->uri(), $ignore) || ($p->parent() && in_array($p->parent()->uri(), $ignore))) continue ?>

I’d do it differently:

<?php foreach ( $pages->not( $ignore ) as $p ) : ?>

How is $ignore defined?

My current sitemap:

<?= '<?xml version="1.0" encoding="utf-8"?>'; ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

  <?php foreach ($pages as $p): ?>
    <?php if (in_array($p->uri(), $ignore) || ($p->parent() && in_array($p->parent()->uri(), $ignore))) continue ?>
      <url>
        <loc><?= html($p->url()) ?></loc>
        <lastmod><?= $p->modified('c') ?></lastmod>
      </url>
  <?php endforeach ?>

</urlset>

My ignore:

$ignore = kirby()->option('sitemap.ignore', ['error', 's']);

If I add changelog to $ignore:

$ignore = kirby()->option('sitemap.ignore', ['changelog', 'error', 's']);

Then the changelog page is also removed. I only whant the children to be removed, changelog/*

$ignore = kirby()->option('sitemap.ignore', [ 'error', 's']);
$ignore = $ignore->add(page('changelog')->children());

Thanks @texnixe for your reply! But I get the following error:
Call to a member function add() on array

Then try

$ignore = kirby()->option('sitemap.ignore', [ 'error', 's']);
$changelog = page('changelog')->children()->pluck('id', ',');
$ignore = array_merge($ignore, $changelog);
2 Likes

Awesome, this works! Thanks so much!

I did not like the solution from @pixelijn, b/c it has hardcoded values. So I built a little snippet, that allows me to include children in the ignore list (e.g. “[‘error’, ‘mypage/*’]”).

[
    'pattern' => 'sitemap.xml',
    'action'  => function () {
      $pages = site()->pages()->index();
      $ignores = kirby()->option('sitemap.ignore', ['error']);
      // Allow ignore option to include children via 'page/*' syntax
      $ignoresExpanded = [];
      foreach ($ignores as $ignore) {
        if (str_ends_with($ignore, '/*')) {
          $ignore = substr($ignore, 0, -2);
          foreach ($pages as $page) {
            if (str_starts_with($page, $ignore)) {
              array_push($ignoresExpanded, $page);
            }
          };
        }
      }
      $ignore = array_merge($ignores, $ignoresExpanded);
      $content = snippet('sitemap', compact('pages', 'ignore'), true);

      return new Kirby\Cms\Response($content, 'application/xml');
    }
  ],