19 Years Later: The Undocumented Optimizely Category Inheritance That Caught Me Out

By Dom Reilly · Posted 20 Mar 2026 · 3 min read

I recently ran into an issue on a site running Optimizely CMS 12 where categories assigned to a parent page were automatically being applied to newly created child pages.

After reviewing the ticket, I was able to reproduce the issue locally without much trouble.

This one genuinely confused me.

My immediate assumption was that the project must have had some custom initialization logic causing the behaviour. I went through each initialization module, adding breakpoints anywhere that looked even remotely suspicious - particularly anything that could be copying categories from the parent.

Nothing stood out. Still, I stepped through everything just to be sure.

No luck.

At that point, I started digging deeper. I spent hours going through Optimizely’s documentation, source code, forum posts, and blogs. The only thing I could find was a forum thread from 2009 discussing how to stop category inheritance:

 https://world.optimizely.com/forum/developer-forum/Developer-to-developer/Thread-Container/2009/11/Stop-inheritance-of-categories/  

Surely this couldn’t still be relevant in 2026 - 19 years later?!

Turns out, it was!

After a quick support ticket with Optimizely, an escalation to an SME, it was confirmed that it was an undocumented feature in the CMS! Thankfully, the SME provided me with some example code to work around this using...yep, you guessed it: an initialization module!

Code below:

using EPiServer;
using EPiServer.Core;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;
using System.Linq;
namespace EpiserverFull.Business.Initialization
{
    [InitializableModule]
    [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    public class StopCategoryInheritInitialization : IInitializableModule
    {
        public void Initialize(InitializationEngine context)
        {
            var events =
            ServiceLocator.Current.GetInstance<IContentEvents>();
            events.CreatingContent += CustomCreatingContent;
        }
        public void Uninitialize(InitializationEngine context)
        {
        }
        public void Preload(string[] parameters)
        {
        }
        private void CustomCreatingContent(object sender, ContentEventArgs
        e)
        {
            //clear the category if the content is child page and inherits 
            the category from parent
            var content = e.Content as PageData;
            if (content != null)
            {
                if (content.Category.Any())
                {
                    content.Category.Clear();
                }
            }
        }
    }
}

Hopefully, that helps someone out who might be facing a similar issue! I have no doubt that I'll be revisiting this post again, at some point in the future!



Dom Reilly

Written by

Dom Reilly

Senior Software Developer and Tech Lead working with .NET and Blazor. Sharing real-world problems, tech, and lessons learned - not always just development. Views expressed here are my own and do not represent my employer.

Keep reading

The Architecture Behind the Blog: From Zero to Production

What started as an all in one Blazor blog gradually evolved into something quite different. From moving the data layer to MySQL and rebuilding the backend in Go, to Dockerising the applications and putting Caddy in...

Posted: 10 Aug 2026
APIArchitectureBlazorBlogdockerAnd 4 more
Read more
I spend my life changing software, so why do I feel so uncomfortable with change?

As developers, we spend our careers helping organisations embrace change through migrations, upgrades and modernisation. So why is personal change so much harder? A reflection on moving house, letting go of memories,...

Posted: 21 Jul 2026
careerchangegrowthpersonalpersonal developmentAnd 1 more
Read more