• Publisert
  • 6 min

Introducing the Optimizely Settings Addon

Screen shot showing the editorial interface for settings

In this blog post I’ll re-introduce an Optimizely addon that’s been available for several years but that perhaps has not gotten a proper introduction to the developer community. The addon adds standardized management of settings in the form of content objects that are editable from within the Optimizely platform, just as pages and blocks.

Introduction

And some things that should not have been forgotten were lost. History became legend. Legend became myth. And for two and a half thousand years, the ring passed out of all knowledge.

For anyone that has read the book The Lord of the Rings (or seen the movie), this quote is probably all familiar. Like the ring, there's a lot of great addons to Optimizely just waiting to be "found". In this blog post I’ll re-introduce an Optimizely addon that’s been available for many years but that perhaps has not gotten a proper introduction to the developer community. The addon adds standardized management of settings in the form of content objects that are editable from within the Optimizely Content Cloud, just as pages and blocks.

Prologue: As some of you might know, I used to work at Optimizely (at that time named Episerver) for a long time in the product development team. I spent a lot of time scanning the forums to figure out common problems and needs that partner developers had to be able to deliver solutions to their customers – and then I tried to find easy to use, often out of the box solutions to these needs. In my last few weeks as an employee, I tried to see if I could find a unified way of handling settings for Optimizely and built an embryo for this system that I shared on the firsts OMVP trip. On a later Episerver event I met up with Jeroen Stemerdink and Marija Jemuovic which told me that they had actually took the system in usage for a few sites that they had built which was nice to hear and triggered me to spend some more time in polishing this.

As you that have been working with the Optimizely Content Cloud for quite some time already know – there’s no built-in way for handling your settings – but there’s a few well used approaches:

  • Add a settings page where your settings are placed. This settings page is usually then referred to from the start page.
  • Add a tab or two to the start page where you add your settings.
  • To somewhat separate the connection to a page, some solutions use abstraction in the implementation details – for instance by implementing an interface for your settings that you work against rather than the concrete page.

Before we move on, let’s go through why the above are not ideal solutions:

  • For the case of the start page, you are mixing concerns with content for the start page and settings mixed into one. This means that you need to give access rights to both, the version history will contain a mix of content changes and changes to settings.
  • In the case of a settings page, it’s a bit more elegant where you separate the content from the settings. However, all settings are mixed into the same page type which usually creates a large content type that contains properties that has nothing with each other to do.

I think that the latter is the biggest problem. I am a strong believer of code that should be tightly coupled on a feature basis, not by technology or layer. A settings page type that knows about 15 different features is something that you should try to avoid. One quite common result of this is that the settings page might contain settings that are no longer in use since a feature might have been removed but withing removing the settings.

Goals for the settings addon

When I started the work on this addon, I had a few primary goals:

  1. Settings should be small content types with one or just a few settings that solved a single problem.
  2. If possible – it should solve the need that Optimizely’s now deprecated “dynamic properties” solved – basically a way of changing settings for different parts of the site/solution.
  3. It should use a configuration-based approach for handling the user interface, in order to use Optimizely’s built in content editorial system, aka we should rely on Optimizely creating the UI for us.

The Result

When installing the module, it’s possible to create settings content types, usually by inheriting from one of the base classes. Let’s have a look at a simple example that controls the start point for the menu:

[ContentType(GUID = "a5506171-c6b2-4a7a-9c44-bb870f695956")]

public class MenuSettings : SettingsBase

{

    public virtual ContentReference MenuRoot { get; set; }

}

The solution uses a convention base mapping to find a relevant setting for a given page, by naming a setting property the same name as the settings type. Say that you want to be able to set this setting for each start page in a multi-site solution, you can achieve this in the following way:

public partial class StartPage : SimpleContentPageBase

{

[UIHint("dynamicsettings")][AllowedTypes(new Type[] { typeof(MenuSettings) })][Display(GroupName = "SiteSettings")]

public virtual ContentReference MenuSettings { get; set; } 

Note that the property name is MenuSettings, which is the same as the settings type. The system uses this naming convention to find relevant settings for each content type in the system when traversing the list of parents for a given content object.

 

To fetch the settings, for instance in a controller or MVC filter, you can add the following code:

var settingsService = ServiceLocator.Current.GetInstance<ISettingsService>();

settingsService.GetSettings<MenuSettings>(currentPage);

 

To be able to create a setting, there’s a new gadget that’s added to the side bar that look like this:

Settingsbrowser.jpg

Simply create a new setting and drag and drop this into your page settings property, and you have a valid connection.

Global Settings

Global settings can be seen as singleton instances that are not coupled to the content structure. There’s a separate full page user interface to create and edit these settings that will be initiated on demand the first time a site is started with these settings. Global settings are created by adding a unique SettingsInstanceGUID to the SettingsContentType attribute. Once you deploy this code, the settings addon will find a content instance at startup – or if no one exists, create a new instance with this GUID. This means that you can always rely on that this setting exists in your own code – so no need for null checks for the actual object.

[SettingsContentType(AvailableInEditMode = false, GUID = "15506171-c6b2-4a7a-9c44-bb870f695911", SettingsInstanceGuid = "d8701e64-8206-4e24-bd3f-cb02b875d6c6", SettingsName = "Google Analytics")]

public class GoogleAnalyticsSettings : SettingsBase

{   

    public virtual string TrackingId { get; set; }

}


You can fetch global settings similar to how you fetch regular settings. Just exclude the current page in the call:

var settingsService = ServiceLocator.Current.GetInstance<ISettingsService>();

var gaSettings = settingsService.GetSettings<GoogleAnalyticsSettings>(); 

Global settings are managed from a separate view where you can see and edit all these settings:

Global Settings View.jpg

Mixing and matching

You can mix and match global settings with structure aware settings. Want to use a global setting but allow to override this per site and section? No problem, just combine a global setting but allow editors to create settings instances and add a property with the matching name to the relevant page types.

Working with multi-lingual settings

We’ve seen the need to be able to work with settings in both language dependent as well as multi-lingual cases. For instance, the Google Analytics tracking ID is probably just a simple data structure, while information for a cookie banner might include text that needs to support translation. We’ve recently improved the support for working with multi-lingual settings, for instance by adding a new base class named LocalizableSettingsBase that you can inherit from.

Support for Commerce

Since the addon uses the standard Optimizely Content Cloud editing system, it also supports Commerce Cloud. There was a recently fixed bug connected to editing Commerce properties in the Global Settings view that needed the Commerce client module to be running that has been fixed in the latest version (for .NET5+ only).

Availability and maintenance

The settings addon is an open source addon that’s maintained by a number of people. It’s available for both Optimizely CMS 11 and 12 and you can find it on Github where there’s documentation on usage. New development is focused on CMS 12 right now and it supports both .NET5 and .NET6.

https://github.com/LinusEkstrom/AddOn.Episerver.Settings