# XML Sitemap plugin

**URL:** <https://forum.getkirby.com/t/xml-sitemap-plugin/6666>\
**Category:** Plugins\
**Created:** [February 20, 2017, 12:41pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666 "2017-02-20T12:41:33Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [February 20, 2017, 12:41pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/1 "2017-02-20T12:41:33Z")

</div>

I’m excited to share with you all that I just release a new plugin: [XML Sitemap](https://github.com/pedroborges/kirby-xml-sitemap)

> A flexible & powerful XML Sitemap generator for Kirby CMS!

![](https://cdck-file-uploads-europe1.s3.dualstack.eu-west-1.amazonaws.com/flex017/uploads/getkirby/original/2X/f/f701e74328b96c85635616cc7393a2a7caa49013.png)

### Main features

- Cache support
- Human-readable XML sitemap
- Image attribute
- Multi-language support
- Powerful options

After installing the plugin using any of the methods documented on the [plugin’s repo](https://github.com/pedroborges/kirby-xml-sitemap) you should be able to visit [https://yoursite.com/sitemap.xml](https://yoursite.com/sitemap.xml) to see an human-readable sitemap without doing any initial configuration. Enjoy it 🙂

Feedback is welcome!

---

<div class="post-metadata">

**Author:** ![JimmyRittenborg](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jimmyrittenborg/32/10261_2.png) [@JimmyRittenborg](https://forum.getkirby.com/u/JimmyRittenborg)\
**Post date:** [February 20, 2017, 3:23pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/2 "2017-02-20T15:23:11Z")

</div>

Wow! Beautiful work right there 👏

---

<div class="post-metadata">

**Author:** ![jenstornell](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jenstornell/32/546_2.png) [@jenstornell](https://forum.getkirby.com/u/jenstornell)\
**Post date:** [February 21, 2017, 1:31pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/3 "2017-02-21T13:31:36Z")

</div>

It seems to be similar to the other sitemap plugins out there, but with that little extra, like the stylesheet. It looks good visually. 🙂

How does it work with routed urls? To have complete control, I route all my pages. Because no sitemap plugins support it (as far as I know) I’ve build my own really simple plugin called [Kirby Sitemap Query](https://github.com/jenstornell/kirby-sitemap-query). It’s not as visual as yours but really powerful in terms of complete control.

Do you have plans to include features like that, complete control of the sitemap? Or could it be done with `sitemap.process`?

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [February 22, 2017, 1:06pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/4 "2017-02-22T13:06:20Z")

</div>

There’s really a bunch of XML Sitemap plugins out there. I needed a few extra things so I built my own. Besides the stylesheet which is great for checking what’s sent to search engines, there are some other differences too:

- Cache support
- Image attribute
- Multi-language support
- Option for custom _priority_ and _changefreq_ logic
- Powerful filter control

Right now I can’t think of a way to easily add routes, I’ll keep that in mind for future features. Shouldn’t be hard to add that.

---

<div class="post-metadata">

**Author:** ![jenstornell](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jenstornell/32/546_2.png) [@jenstornell](https://forum.getkirby.com/u/jenstornell)\
**Post date:** [February 22, 2017, 3:34pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/5 "2017-02-22T15:34:47Z")

</div>

In my plugin it’s this simple to add urls. Hopefully you can be inspired by it or make another solution as awesome as this. 😉

```php
<?php
foreach( site()->index() as $page ) {   
    $url['priority'] = ( $page->isHomePage() ) ? 1 : '0.5';

    sitemapQuery::add(array(
        'loc' => $page->url(),
        'lastmod' => $page->modified('Y-m-d'),
        'priority' => $url['priority'],
    ));
}

```

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [February 22, 2017, 3:58pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/6 "2017-02-22T15:58:36Z")

</div>

Yeah, that’s great!

I’ll see what I can do when I get some free time. Thanks for the inspiration 😉

---

<div class="post-metadata">

**Author:** ![11bits](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/11bits/32/860_2.png) [@11bits](https://forum.getkirby.com/u/11bits)\
**Post date:** [November 16, 2017, 12:38pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/7 "2017-11-16T12:38:23Z")

</div>

Hi @pedroborges, I’m testing your sitemap plugin and I have a question.

Is it possible to ignore a subpage?

I’ trying do it including the URI but it seems it doesn’t work:

```auto
c::set('sitemap.include.invisible', true);
c::set('sitemap.ignored.pages', [contact/thank-you, error]);

```

---

<div class="post-metadata">

**Author:** ![pedroborges](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/pedroborges/32/7038_2.png) [@pedroborges](https://forum.getkirby.com/u/pedroborges)\
**Post date:** [November 16, 2017, 12:54pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/8 "2017-11-16T12:54:59Z")

</div>

Hi @11bits! Yes, it’s possible to exclude any page. The values passed inside the array to the `sitemap.ignored.pages` option should be strings, try this:

```php
c::set('sitemap.include.invisible', true);
c::set('sitemap.ignored.pages', [
    site()->errorPage(),
    'contact/thank-you'
]);

```

---

<div class="post-metadata">

**Author:** ![11bits](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/11bits/32/860_2.png) [@11bits](https://forum.getkirby.com/u/11bits)\
**Post date:** [November 16, 2017, 1:15pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/9 "2017-11-16T13:15:43Z")

</div>

In my case, if I use the code of your example, it doesn’t work. But if I use only strings it works perfectly:

```auto
c::set('sitemap.ignored.pages', [
    'error',
    'contact/thank-you'
]);

```

Thanks!

---

<div class="post-metadata">

**Author:** ![anon77445132](https://avatars.discourse-cdn.com/v4/letter/a/4da419/32.png) [@anon77445132](https://forum.getkirby.com/u/anon77445132)\
**Post date:** [November 17, 2017, 4:55pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/10 "2017-11-17T16:55:00Z")

</div>

@pedroborges:

With [Docs: $site-\>errorPage()](https://getkirby.com/docs/cheatsheet/site/error-page):

> [@pedroborges](#):
>
> site()-\>errorPage(),

Returns the $page object for the error page.

I have not tested, but something like using [-\>uri([$lang = null])](https://getkirby.com/docs/cheatsheet/page/uri) may help you.

---

<div class="post-metadata">

**Author:** ![Gert](https://avatars.discourse-cdn.com/v4/letter/g/7bcc69/32.png) [@Gert](https://forum.getkirby.com/u/Gert)\
**Post date:** [October 16, 2018, 6:41pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/11 "2018-10-16T18:41:15Z")

</div>

This is really a great sitemap tool.  
Is it also possible to exclude a certain language from the sitemap? I need this because this language has not yet been fully translated, but the website is supposed to go online anyway.  
Could

```
// URI of pages to remove
c::set('sitemap.ignored.pages', []);

```

be used for this task? If so, what would you have to put between the square brackets to exclude i.e. all ‘en’ pages?

---

<div class="post-metadata">

**Author:** ![jimbobrjames](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jimbobrjames/32/5802_2.png) [@jimbobrjames](https://forum.getkirby.com/u/jimbobrjames)\
**Post date:** [October 16, 2018, 7:18pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/12 "2018-10-16T19:18:30Z")

</div>

You could try:

```auto
c::set('sitemap.ignored.pages', [
    $site->pages()->find('mypage')->content('en'),
    $site->pages()->find('mypagetwo')->content('en'),
    ...
]);

```

However, i’ve used sitemap on translated sites and if the content isnt there for a language, it doesn’t end up in the sitemap as i recall, so I don’t think this actually necessary?

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [October 16, 2018, 8:20pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/13 "2018-10-16T20:20:35Z")

</div>

> [@jimbobrjames](#):
>
> c::set(‘sitemap.ignored.pages’, [$site-\>pages()-\>find(‘mypage’)-\>content(‘en’), $site-\>pages()-\>find(‘mypagetwo’)-\>content(‘en’), …]);

You need to pass an array of page Uris, not content objects…

One thing you can probably do is to remove the language from the language definition (only for the production site config, unless content creation takes place on the live site), or manually exclude the language from this snippet:  
[https://github.com/pedroborges/kirby-xml-sitemap/blob/master/xml-sitemap.php](https://github.com/pedroborges/kirby-xml-sitemap/blob/master/xml-sitemap.php) (line 5).

Not sure if there are other ways, haven’t really used the plugin yet.

---

<div class="post-metadata">

**Author:** ![Gert](https://avatars.discourse-cdn.com/v4/letter/g/7bcc69/32.png) [@Gert](https://forum.getkirby.com/u/Gert)\
**Post date:** [October 17, 2018, 2:04pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/14 "2018-10-17T14:04:09Z")

</div>

> [@jimbobrjames](#):
>
> However, i’ve used sitemap on translated sites and if the content isnt there for a language, it doesn’t end up in the sitemap as i recall, so I don’t think this actually necessary?

This Sitemap tool displays all language versions of the page as a link.

Anyway, thanks for the support, but the mentioned methods are simply too complicated for me, so I will add a ‘manual’ sitemap until the website is translated.

---

<div class="post-metadata">

**Author:** ![Gert](https://avatars.discourse-cdn.com/v4/letter/g/7bcc69/32.png) [@Gert](https://forum.getkirby.com/u/Gert)\
**Post date:** [November 24, 2018, 6:04pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/15 "2018-11-24T18:04:42Z")

</div>

It has turned out that I might well need it more often to exclude a language temporarily in this sitemap-plugin. So here’s another try:

The instructions for the sitemap-xml-plugin say that setting ‘sitemap.process’ in the config.php allows you “to process the pages collection in any way you want, such as removing or adding a specific set of pages”.  
The example for this is the following:

```
// Filter a set of pages based on a field value
c::set('sitemap.process', function($pages) {
return $pages->filter(function($page) {

    // Remove future posts
    if ($page->intendedTemplate() === 'post') {
        return $page->date() < time();
    }

    // Keep all other pages
    return true;
    });
});

```

How can I filter out all English pages instead of removing the future posts? Is that possible?

```
if($page->content() == 'en'){}

```

doesnt work. Do you need “$page-\>language” instead or am I on the completely wrong trail?

---

<div class="post-metadata">

**Author:** ![Gert](https://avatars.discourse-cdn.com/v4/letter/g/7bcc69/32.png) [@Gert](https://forum.getkirby.com/u/Gert)\
**Post date:** [November 27, 2018, 2:14pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/16 "2018-11-27T14:14:06Z")

</div>

I’ve tried to filter out the English pages as described in the Kirby Filter instructions (I’m not a programmer, so I’m pretty much dabbling around). As described there, I first created the file ‘filters.php’ in site/plugins with the following content:

```
<?php
// Anything that matches a given language attribute

collection::$filters['languageIs'] = function($collection, $field, $value) {

  foreach($collection->data as $key => $item) {
    if(collection::extractValue($item->content()->language(), $field) != $value) {
      unset($collection->$key);
    }
  }

  return $collection;

};

```

and then I added the following code to config.php (see old before-code in last post) to remove all english pages from the sitemap:

```
// Filter a set of pages based on a field value
c::set('sitemap.process', function($pages) {
    return $pages->children()->visible()->filterBy('code', 'languageIs', 'en');
    });

```

The result of this is that no pages at all are displayed in the sitemap. Which is some progress, it shows that the code in ‘sitemap.process’ does at least something.

Is my encoding wrong (very likely 😉 ) or does this filter not work in config.php because it is in the plugin folder? How do I correctly write the filter code (if it’s wrong)?

---

<div class="post-metadata">

**Author:** ![splorp](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/splorp/32/29_2.png) [@splorp](https://forum.getkirby.com/u/splorp)\
**Post date:** [July 8, 2020, 3:56pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/17 "2020-07-08T15:56:45Z")

</div>

Hello @pedroborges … will you be updating this plugin for K3?

If this plugin is no longer being developed, what would be recommended as an equivalent replacement? I have several K2 sites that need to get migrated to K3 in the next few weeks and a compatible sitemap plugin is necessary to make this happen.

---

<div class="post-metadata">

**Author:** ![splorp](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/splorp/32/29_2.png) [@splorp](https://forum.getkirby.com/u/splorp)\
**Post date:** [May 4, 2022, 9:44pm UTC](https://forum.getkirby.com/t/xml-sitemap-plugin/6666/18 "2022-05-04T21:44:08Z")

</div>

Since it doesn’t appear that @pedroborges is updating his plugin for K3, here’s a bit of a follow up.

Rather than try to fight with yet another sitemap plugin, I implemented @bastianallgeier’s super simple [sitemap for search engines](https://getkirby.com/docs/cookbook/content/sitemap) recipe in the [Cookbook](https://getkirby.com/docs/cookbook) and then appended the great looking XSL stylesheet from @pedroborges’ original plugin by adding the following decalration in the `sitemap.php` snippet.

`<?= '<?xml-stylesheet type="text/xsl" href="' . url('sitemap.xsl') . '"?>'; ?>`

Enjoy.
