World is now on Opti ID! Learn more

Remko Jantzen
Dec 14, 2021
  38
(0 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 https://cms.example.com and https://www.example.com will work, but https://www.holding-name.com and https://www.brand-name.com 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 https://cms.example.com, this becomes "example.com"
    • 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 https://world.optimizely.com/documentation/developer-guides/CMS/editing/on-page-editing-with-client-side-rendering/ 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 https://cms.example.com, this becomes "example.com". 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 https://cms.example.com/episerver): https://cms.example.com/episerver/cms/latest/clientresources/epi-cms/communicationinjector.js
  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: https://world.optimizely.com/documentation/developer-guides/CMS/editing/on-page-editing-with-client-side-rendering

    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

Comments

Please login to comment.
Latest blogs
Make Global Assets Site- and Language-Aware at Indexing Time

I had a support case the other day with a question around search on global assets on a multisite. This is the result of that investigation. This co...

dada | Jun 26, 2025

The remote server returned an error: (400) Bad Request – when configuring Azure Storage for an older Optimizely CMS site

How to fix a strange issue that occurred when I moved editor-uploaded files for some old Optimizely CMS 11 solutions to Azure Storage.

Tomas Hensrud Gulla | Jun 26, 2025 |

Enable Opal AI for your Optimizely products

Learn how to enable Opal AI, and meet your infinite workforce.

Tomas Hensrud Gulla | Jun 25, 2025 |

Deploying to Optimizely Frontend Hosting: A Practical Guide

Optimizely Frontend Hosting is a cloud-based solution for deploying headless frontend applications - currently supporting only Next.js projects. It...

Szymon Uryga | Jun 25, 2025

World on Opti ID

We're excited to announce that world.optimizely.com is now integrated with Opti ID! What does this mean for you? New Users:  You can now log in wit...

Patrick Lam | Jun 22, 2025

Avoid Scandinavian Letters in File Names in Optimizely CMS

Discover how Scandinavian letters in file names can break media in Optimizely CMS—and learn a simple code fix to automatically sanitize uploads for...

Henning Sjørbotten | Jun 19, 2025 |