On a recent project I've used Insert Options Rules to implement interesting logic around when certain Insert Options should appear in the Content Editor. If you've not used Insert Options Rules before, they allow you to define Insert Options through the Sitecore rules engine instead of Standard Values (or directly on items). Fellow Sitecore MVP Marek Musielak has a great blog post on how to use them.

By default, to add new Insert Options Rules you must create your rules under /sitecore/system/Settings/Rules/Insert Options/Rules. Maybe that's fine if you're just creating one rule, but if you're creating several, sticking your custom rules alongside the 20 or so out-of-the-box rules is a bit unruly. A cleaner approach would be to organize your rules by folder, e.g., /Feature/Module Name and /Project/Module Name if you're using the Helix principles. Fortunately, Sitecore makes that easy through the uiGetMasters pipeline--the pipeline responsible for resolving Insert Options.

Create Pipeline Processor

Create your pipeline processor as follows:

public class RunCustomInsertOptionsRules  
{
  private readonly ID _insertOptionsRuleTemplateId = new ID("{664E5035-EB8C-4BA1-9731-A098FCC9127A}");

  public List<string> Folders { get; set; }

  public RunCustomInsertOptionsRules()
  {
    Folders = new List<string>();
  }

  public void Process(GetMastersArgs args)
  {
    Assert.ArgumentNotNull(args, nameof(args));

    var database = args.Item.Database;
    var insertOptionRules = new List<Item>();
    foreach (var folder in Folders)
    {
      var rulesInFolder = GetInsertOptionsRules(database, folder);
      insertOptionRules.AddRange(rulesInFolder);
    }

    var rules = RuleFactory.GetRules<InsertOptionsRuleContext>(insertOptionRules, "Rule");
    if (rules == null) return;

    var ruleContext = new InsertOptionsRuleContext
    {
      Item = args.Item,
      InsertOptions = args.Masters
    };
    rules.Run(ruleContext);
  }

  protected virtual IEnumerable<Item> GetInsertOptionsRules(Database database, string rootPath)
  {
    IEnumerable<Item> insertOptionsRules;
    using (new SecurityDisabler())
    {
      insertOptionsRules = database.SelectItems($"{rootPath}//*[@@templateid='{_insertOptionsRuleTemplateId}']");
    }
    return insertOptionsRules;
  }

This processor takes a list of folder paths from configuration, finds all of the Insert Option Rules under those folders, and runs the rules to resolve all Insert Options.

Tip: If you're going to have a lot of Insert Options Rules, forgo Sitecore Query in GetInsertOptionsRules in favor of other methods to avoid performance issues in the Content Editor.

Plug Processor into uiGetMasters Pipeline

Add your processor into the uiGetMasters pipeline through configuration before the CheckSecurity processor:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">  
  <sitecore>
    <processors>
      <uiGetMasters>
        <processor mode="on" type="OrganizeInsertOptionsRules.Pipelines.GetMasters.RunCustomInsertOptionsRules, OrganizeInsertOptionsRules"
                   patch:before="processor[@type='Sitecore.Pipelines.GetMasters.CheckSecurity, Sitecore.Kernel']">
          <folders hint="list">
            <folder>/sitecore/system/Settings/Rules/Insert Options/Rules/Foundation</folder>
            <folder>/sitecore/system/Settings/Rules/Insert Options/Rules/Feature</folder>
            <folder>/sitecore/system/Settings/Rules/Insert Options/Rules/Project</folder>
          </folders>
        </processor>
      </uiGetMasters>
    </processors>
  </sitecore>
</configuration>  

The processor takes a list of folder paths that define to search for custom Insert Options Rules. This list of folders will automatically populate the Folders property in the pipeline processor above through the Sitecore Configuration Factory.

In this example I'm organizing my Insert Options Rules according to Helix principles, so I've added Feature, Foundation, and Project folders under the default Insert Options Rules folder. You can replace these folders with any folders you like, from anywhere in the content tree.

Make Some Rules

Now go make some Insert Options Rules. In the screenshot below you can see the Helix folder structure under the Insert Options folder.

Custom Insert Options Rules Folders

I've created some rules based on Habitat templates so that those templates show up as Insert Options everywhere in the content tree.

Habitat Insert Options

Conclusion

Organizing your Insert Options Rules by custom folder structure makes it much easier to maintain and serialize your Insert Options Rules using TDS Classic or Unicorn.

For more examples of how to use the uiGetMasters pipeline to supercharge your Insert Options Rules, check out the Data Definition Cookbook from Sitecore.

All code in this blog post can be found on GitHub here: https://github.com/coreyasmith/OrganizeInsertOptionsRules.