---
title: Custom properties
slug: cms-11/dev-docs/custom-properties
docTags: 
createdAt: 2026-07-22T19:45:20.939Z
---

Most common Optimizely Content Management System (CMS) property types have built-in persisting and rendering support. In most cases, you should not need to create custom properties. You can change the editorial experience without creating a custom property. However, if you need a custom property, select a proper base type from which you can inherit, depending on your data type. You can also create a template for the data type (if you want the property to be visible on templates).

The following example shows how to implement a custom property by selecting a suitable base type (for example, `PropertyString`, `PropertyNumber`); a property holds an enumerable of `ContentReference` and stores it as a serialized string.

```csharp
[PropertyDefinitionTypePlugIn]
public class LinkingProperty: PropertyLongString {
  public IEnumerable<ContentReference> LinkedReferences {
    get {
      if (!String.IsNullOrEmpty(LongString)) {
        var entries = LongString.Split(';');
        return entries.Select(e => ContentReference.Parse(e));
      }
      return null;
    }
    set {
      LongString = String.Join(";", value.Select(r => r.ToString()));
    }
  }

  public override object Value {
    get {
      return LinkedReferences;
    }
    set {
      IEnumerable<ContentReference> links = value as IEnumerable<ContentReference>;
      if (links != null) {
        LinkedReferences = links;
      } else {
        base.Value = value;
      }
    }
  }

  public override Type PropertyValueType {
    get {
      return typeof (IEnumerable<ContentReference>);
    }
  }

  public override object SaveData(PropertyDataCollection properties) {
    return base.LongString;
  }
}
```

## Index references to other content from a custom property

If the custom property stores references to other content instances, you should also have a "soft" link indexer for the type. In that case, when an editor tries to delete a content item, a warning displays if a property on another content item holds a reference to the item to be deleted. If the custom property is inheriting `PropertyContentReference`, `PropertyUrl`, or `PropertyXhtml`, then the soft indexing is handled by the base type indexer. The following example shows a soft link indexer for the previous custom property above:

```csharp
[ServiceConfiguration(typeof (IPropertySoftLinkIndexer))]
public class LinkingPropertyIndexer: IPropertySoftLinkIndexer < IEnumerable < ContentReference >> {
  public IEnumerable < SoftLink > ResolveReferences(IEnumerable < ContentReference > propertyValue, IContent owner) {
    var softLinks = new List < SoftLink > ();
    foreach(var link in propertyValue) {
      var softLink = new SoftLink {
        OwnerContentLink = owner.ContentLink.ToReferenceWithoutVersion(),
          OwnerLanguage = (owner as ILocalizable)?.Language,
          ReferencedContentLink = link,
          SoftLinkType = ReferenceType.PageLinkReference
      };
      softLinks.Add(softLink);
    }
    return softLinks;
  }
}
```

The indexer is registered with the IOC container for the `IPropertySoftLinkIndexer` interface, which implements the generic `IPropertySoftLinkIndexer<T>` interface where the generic argument is the `PropertyValueType` for the property implementation.
