Edit domains and sitemaps

Apr 4, 2025
By myq for Developers

Problem

In same cases you may want to set up a specific domain just for editing your Concrete site. This may be beacuse you have set up redundant servers for high availability or you want to increase security by limiting the IP addresses that can access the edit interface. Another reason for setting up an edit domain is to avoid issues with aggressive caching.

Whatever the use case, one of the challenges that can arrise is generating a sitemap.xml file. By default, the links to all of the content in a site contained in the sitemap.xml file will be created using the domain where the command is issued from. If someone is manually generating the it from edit domain using the Dashboard, then the links will point to the edit domain rather than the public domain.

Solution

Fortunately, Concrete supports many application event hooks which can be used to modify it's behavior. One useful event in this scenario is on_sitemap_xml_element. This event is fired each time an element is added to the sitemap.xml file as it's generated. We can hook into this event and change the URL's host before it's written to disk.

In the example below, the public and edit domains are specified in a .env file and are accessed in the $_ENV global variable with by using the vlucas/phpdotenv package to load the values by adding something like this to application/bootstrap/autoload.php:

$env = Dotenv\Dotenv::createImmutable(__DIR__ . '/../../../' /* path to .env outside of public directory */);

These values can be used in the application/config/site.php to set the canonical URL as well. Below, they are used to ensure that the URLs in the sitemap.xml nodes reference the public domain.

$app['director']->addListener('on_sitemap_xml_element', function ($event) {
    // Don't make changes if edit and public URLs not detected
    if (empty($_ENV['CANONICAL_URL_EDIT']) || empty($_ENV['CANONICAL_URL_PUBLIC'])) {
        return $event;
    }

    /** @var \Concrete\Core\Page\Sitemap\Event\ElementReadyEvent $event */
    $element = $event->getElement();

    // Don't try to modify a header or footer element.
    if (!$element instanceof \Concrete\Core\Page\Sitemap\Element\SitemapPage) {
        return $event;
    }

    /** @var \Concrete\Core\Url\UrlImmutable $url */
    $url = $element->getUrl();

    // Don't modify if no URL is set
    if (!$url instanceof \Concrete\Core\Url\UrlImmutable) {
        return $event;
    }

    if ((string) $url->getHost() !== $_ENV['CANONICAL_URL_PUBLIC']) {
        /** @var \Concrete\Core\Page\Sitemap\Element\SitemapPage $element */
        $element->setUrl($url->setHost($_ENV['CANONICAL_URL_PUBLIC']));
    }


    return $event;
});
Recent Tutorials
Edit domains and sitemaps
Apr 4, 2025
By myq.

How to create a sitemap when using an edit domain

Customize the default page title
Mar 12, 2025

Change the default " :: " and/or "site name :: page title" formatting separator to something else.

Configure Composer to work with a Page Type
Feb 20, 2025
By myq.

Fix the "Unable to load block into composer. You must edit this content from within the context of the page." error message

Permissions for editors in a multilingual site
Feb 2, 2025
By myq.

How to set up a multilingual Concrete CMS site for groups of language-specific editors

Restoring deleted pages using advanced search
Jan 16, 2025
By myq.

How to recover deleted pages when there are more than a few to choose from.

How to Automate the Copyright Year
Dec 27, 2024

Learn how to keep your website's copyright year updated automatically in Concrete CMS.

Improvements?

Let us know by posting here.