SaaS CMS has officially launched! Learn more now.

Remko Jantzen
Dec 14, 2021
(1 votes)

Twelve points to start with on page editing in CMS 11 or 12

Over the past few months, I've received a number of questions regarding the support for on-page editing by the CMS. It's not hard to enable, but you need to know where to look for. As I haven't found a complete overview of all steps needed to make it work, hence this blog post.

I will only cover the configuration needed and constraints to be obeyed to make on-page editing work, but won't go into the specifics of making changes within the CMS and/or building the decoupled frontend. The steps are the same for CMS 11 and CMS 12, on the few points where the version matters, I've highlighted these differences.

General setup

  1. As the Edit Mode requires communication between the shell and decoupled frontend the current constraint is that both must share the same domain. Thus and will work, but and will not work.

    Also make sure all domains are running either on HTTPS with certificates trusted by the browser or on HTTP, when you'll mix HTTP and HTTPS it will not work.
  2. In the Site configuration, make sure that the website URLs are configured correctly:
    • Website URL: The domain where the decoupled frontend is running
    • Host Names: Configure at a minimum two host-names
      • The domain of the decoupled frontend should have the type: Primary
      • The domain of the shell should have the type: Edit
  3. Though not a firm requirement, having the CMS control the URLs and routing within the decoupled frontend gives two major benefits:
    • Editors retain full control over both the website structure and content, at the expense of a slightly more complicated initial build - especially with Server Side Rendering involved.
    • Routing for edit-mode URLs is much easier to implement.

CMS configuration

  1. Ensure that your CMS is capable to serve unpublished versions of a content item, either by extending the Content Delivery API or using the Content Management API.

    Tip 1: To get close to feature parity, you'll need to extend the CMS with support for loading by Project ID, Visitor Group ID, and Channel ID. (The last one as 3rd party modules within the CMS may depend on it).

    Tip 2: By default, the Context Mode resolution differs between the Content Delivery/Management API and the regular CMS, so any 3rd party add-on will behave like you're working on a public endpoint, even when accessing the API from within edit mode. Easy solution? Create a single ContextModeResolver unifying both resolvers into one single implementation.
  2. Ensure that your CMS supports a form of single-sign-on between the Shell and Decoupled frontend. There's no requirement on which IAM solution is used, beyond it enabling the decoupled frontend to send authenticated requests to the Content Delivery/Management API.
  3. Make sure that the ContentDeliveryAPI option "OptimizeForDelivery" has been set. Furthermore it is highly recommended to invoke the following extension methods on the service container in your startup: "ConfigureForExternalTemplates()" and "ConfigureForContentDeliveryClient()"

    Note: If you make these changes on an application already using the Content Delivery API you will find it changing the data returned by the Content Delivery API.
  4. Make sure the shell updates the document.domain value in the browser. Yes, this is a deprecated setting, but at the time of writing, it's the only way to get On-Page Editing to work. This must be the domain, without subdomains, protocol, and port number. So for, this becomes ""
    • CMS 11: Add the AppSetting "episerver:ManagementDomain" with the value as above
    • CMS 12: At the time of writing, there's no standard way of doing this. Probably injecting a script into the shell will give you the ability to update this value.

Frontend requirements

  1. The shell determines the currently selected item by URL and uses special URLs to render edit mode. Hence:
    • All navigation between content items must happen by a regular page unload/load. So using the History API or on-page routers is not allowed in this mode.
    • The Decoupled frontend must support the special URLs generated by the shell to load the content item selected by the editor 
  2. The actual DOM tree must have the appropriate attributes to inform the shell where the editable fields actually are presented on the page. See for more details.

    Note: This is the actual DOM tree, shown by "inspect element" in a browser, not the virtual DOM maintained by React, Vue, etc...
  3. When the page runs in edit mode it must update the document.domain value in the browser. This must be the domain, without subdomains, protocol, and port number. So for, this becomes "". This must be the same value as for step 4 in the CMS.
  4. To ensure that the edit mode renders correctly and can communicate with the SPA/PWA, the communicator script must be loaded and executed (verify that there’re no CORS or other security measures preventing this). The URL for this script is (assuming that the CMS runs at
  5. Last, but certainly not least, the frontend must listen to the contentSaved event to refresh the view with the latest data. The documentation for this is available at:

    When running decoupled, with the communicationInjector (Step 4 above) loaded, this can be done by using the global "epi" variable like so:
    epi.subscribe("contentSaved", event => { /* Your handler here */});

And that's it, these are my "Twelve points to start with on-page-editing in CMS 11 or 12".

Happy coding!

Dec 14, 2021


Daniel Jan 19, 2022 11:15 AM


Thank you for clarifying the on page editing setup!

I have a question regarding decoupled and OPE:

This page of the documentation recommends breaking apart the CMS UI from the public facing server.

If you have a public facing server (SSR javascript) with no EPiServer reference other than the @episerver/content-delivery npm package and (when signed in) the DOM attributes utilized by the communicationinjector-script.

And an internal server with the CMS UI and the Content Delivery API (only reachable by the public facing server).

Should the CMS UI somehow be kept separate from the Content Delivery API for some reason or is this setup fine provided the SSO is in place?


Or are there any potential pitfalls regarding decoupled setup and OPE to be aware of security-wise?

Best regards

Please login to comment.
Latest blogs
Getting Started with Optimizely SaaS using Next.js Starter App - Extend a component - Part 3

This is the final part of our Optimizely SaaS CMS proof-of-concept (POC) blog series. In this post, we'll dive into extending a component within th...

Raghavendra Murthy | Jul 23, 2024 | Syndicated blog

Optimizely Graph – Faceting with Geta Categories

Overview As Optimizely Graph (and Content Cloud SaaS) makes its global debut, it is known that there are going to be some bugs and quirks. One of t...

Eric Markson | Jul 22, 2024 | Syndicated blog

Integration Bynder (DAM) with Optimizely

Bynder is a comprehensive digital asset management (DAM) platform that enables businesses to efficiently manage, store, organize, and share their...

Sanjay Kumar | Jul 22, 2024

Frontend Hosting for SaaS CMS Solutions

Introduction Now that CMS SaaS Core has gone into general availability, it is a good time to start discussing where to host the head. SaaS Core is...

Minesh Shah (Netcel) | Jul 20, 2024

Optimizely London Dev Meetup 11th July 2024

On 11th July 2024 in London Niteco and Netcel along with Optimizely ran the London Developer meetup. There was an great agenda of talks that we put...

Scott Reed | Jul 19, 2024

Getting Started with Optimizely SaaS using Next.js Starter App - Configure local development - Part 2

This is part 2 of a proof-of-concept (POC) blog. In this post, I will guide you through the steps to configure your SaaS instance with your local...

Raghavendra Murthy | Jul 19, 2024 | Syndicated blog