November Happy Hour will be moved to Thursday December 5th.

Giuliano Dore
May 11, 2021
  2548
(7 votes)

How to integrate Optimizely Feature Rollout with EPiServer

I have been writing a number of posts about agency clients and use-cases for agencies pain points here on EPiServer World and on other blogging platforms in the past. I also had the chance to work for startups and product companies and I could notice that the process for feature delivery is sometimes a bit different.  

Product companies tend to focus on a small number of products and a large number of deployments for features, micro-features and components. One requirement that is listed is that It must be possible to release specific features for specific targets like markets, user groups or audiences without “corrupting” the integrity of the project.

As an example, social networks with a few billion users in hundreds of countries are regularly publishing different features for different countries with full control over the delivery and no downtime.

I have had the opportunity to play with Optimizely during my free time, and I was very pleased with the capabilities of their latest ‘Feature Rollout’ release.

One of the perks regarding feature rollout is that it helps avoiding messy rollbacks and hotfixes as it is possible to use feature flags to roll out features to users with an option to roll back if needed to reduce the risk using a convenient interface.

Technical limitations

Let’s get back into EPiServer for a second. We have a wonderful system with flags that can be controlled in a separate backoffice. However, due to the nature of c# and the ‘code first’ approach in EPiServer regarding data models, there are items that we cannot ‘roll out’, I listed a few of them:

  • Page & Block types
  • Product types in EPiServer Commerce
  • Selection factories & rules about allowed content
  • New Scheduled jobs

The main reason regarding this limitation is that the flag coming from Optimizely is a Boolean and it is not possible to set wrap ‘if’ statements around classes or attributes.

The default behaviour in EPiServer regarding components like Scheduled Jobs is that they become available once the class is included in the dll.

While we can’t ship pages or blocks as Optimizely “features”; we still have a wide range of opportunities to use feature rollout:

We can use the flag to hide / show new features in a page like new sections of a page:

@{
       var optimizelyClient = OptimizelySDK.OptimizelyFactory.NewDefaultInstance(System.Configuration.ConfigurationManager.AppSettings["Optimizely:sdkKey"]);

       //testing for all clients
       var user = optimizelyClient.CreateUserContext("");

       //feature flag
       var decision = user.Decide("enable_messenger_chat");

       var enableMessengerChat = decision.Enabled;
}
@if (enableMessengerChat)
{
         <div>new feature here</div>
}

We can also use the flag at the page controller level to “disable” pages and blocks from being rendered until the Optimizely feature is marked as enabled:

public class NewFeaturePageController : PageController<NewFeaturePage>
    {
        public ActionResult Index(NewFeaturePage currentPage)
        {
              var optimizelyClient = OptimizelySDK.OptimizelyFactory.NewDefaultInstance(System.Configuration.ConfigurationManager.AppSettings["Optimizely:sdkKey"]);

              var user = optimizelyClient.CreateUserContext("");

              var decision = user.Decide("enable_new_feature");

              var isEnabled = decision.Enabled;
              if(isEnabled)
                   return View(currentPage);
              else
                   throw new NotImplementedException();
        }
    }

With this code, even if the page is deployed, users - like the content team - will not be able to see the page until the feature is enabled in Optimizely.

Update: there is a way to "hijack" the creation of pages, blocks and other episerver components using Initialization modules and the right service, solving the "we can't wrap a boolean around a class or an attribute" issue. However this is a lot more advanced and I chose to cover examples that are available using the standard online training classes.

Integration

I created a test project in github to review the capabilities of Feature Rollout, the code is available here: https://github.com/giuunit/optimizely-feature-rollout-test - it's an example of a feature (enabling facebook messenger web plugin) using Optimizely Rollout Feature. Most of the code is inside the master layout as I wanted the plugin to be available for all the pages in the web project. The code below shows how to integrate the FB Messenger chat web plugin using Feature Rollout and a variable for the page id:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";

    //setting up Optimizely;
    var optimizelyClient = OptimizelySDK.OptimizelyFactory.NewDefaultInstance(System.Configuration.ConfigurationManager.AppSettings["Optimizely:sdkKey"]);

    var user = optimizelyClient.CreateUserContext("");

    //feature flag
    var decision = user.Decide("enable_messenger_chat");
    var enableMessengerChat = decision.Enabled;

    //retrieving the page id
    var pageId = decision.Variables.GetValue<string>("page_id");
}

@if (enableMessengerChat & !string.IsNullOrWhiteSpace(pageId))
{
    <!-- Messenger Chat Plugin Code -->
    <div id="fb-root"></div>
    <script>
        window.fbAsyncInit = function() {
          FB.init({
            xfbml            : true,
            version          : 'v10.0'
          });
        };
        (function(d, s, id) {
          var js, fjs = d.getElementsByTagName(s)[0];
          if (d.getElementById(id)) return;
          js = d.createElement(s); js.id = id;
          js.src = 'https://connect.facebook.net/en_US/sdk/xfbml.customerchat.js';
          fjs.parentNode.insertBefore(js, fjs);
        }(document, 'script', 'facebook-jssdk'));
    </script>

    <!-- Your Chat Plugin code -->
    <div class="fb-customerchat"
         attribution="biz_inbox"
         page_id="@pageId">
    </div>
}


Do you have ideas about integrations between Optimizely and EPiServer CMS ? Leave a comment below 😊

May 11, 2021

Comments

Paul Gruffydd
Paul Gruffydd May 11, 2021 12:18 PM

Nice. I do like the capabilities of rollouts, particularly for progressive or targetted rollout rather than just switching a feature on or off for everyone.

Interestingly, the topic of dynamically showing/hiding content types that you mention as a limitation came up in conversation with one of my colleagues yesterday and it's certainly possible, you just need to know where to look. I wrote a post on feature switching per language a while back which shows how it can be done:
https://world.episerver.com/blogs/paul-gruffydd/dates/2019/3/language-based-feature-switching/

I suspect the other limitations could be worked around too if you wanted to though I've never tried it.

Giuliano Dore
Giuliano Dore May 11, 2021 01:52 PM

Thank you for your comment Paul 😊 It's an excellent suggestion & article. I added a note about the possibility to "hijack" some of the components that I listed as part of the limitations paragraph. I wanted to keep this article at a level where new developers would be comfortable trying it.

Please login to comment.
Latest blogs
Optimizely SaaS CMS + Coveo Search Page

Short on time but need a listing feature with filters, pagination, and sorting? Create a fully functional Coveo-powered search page driven by data...

Damian Smutek | Nov 21, 2024 | Syndicated blog

Optimizely SaaS CMS DAM Picker (Interim)

Simplify your Optimizely SaaS CMS workflow with the Interim DAM Picker Chrome extension. Seamlessly integrate your DAM system, streamlining asset...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Optimizely CMS Roadmap

Explore Optimizely CMS's latest roadmap, packed with developer-focused updates. From SaaS speed to Visual Builder enhancements, developer tooling...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Set Default Culture in Optimizely CMS 12

Take control over culture-specific operations like date and time formatting.

Tomas Hensrud Gulla | Nov 15, 2024 | Syndicated blog

I'm running Optimizely CMS on .NET 9!

It works 🎉

Tomas Hensrud Gulla | Nov 12, 2024 | Syndicated blog

Recraft's image generation with AI-Assistant for Optimizely

Recraft V3 model is outperforming all other models in the image generation space and we are happy to share: Recraft's new model is now available fo...

Luc Gosso (MVP) | Nov 8, 2024 | Syndicated blog