AI agents: the content index is at /llms.txt. Every page is also available as Markdown — send the request header Accept: text/markdown, or append .md to the page URL.
Xperience Docs

Cookie consent

We use necessary cookies (opens in a new tab) to run our website and improve your experience while browsing. Additional cookies are only used with your consent. You may revoke your consent on the Cookies Policy (opens in a new tab) page or in your browser at any time.

Configure (opens in a new tab)
  • Documentation
    Administration interface basicsDevelopers and adminsBusiness usersChangelogGlossary
  • Guides
    Welcome to Xperience by KenticoAdministration interface basicsCustomer journeysDigital marketingConfigurationDevelopmentArchitectureUpgrade to Xperience by Kentico
  • Training
    For AdminsFor Business usersFor DevelopersFor Solution architects
  • API Examples
    ConfigurationContent managementDevelopmentDigital marketing
  • Changelog
    Documentation updatesSecurity advisories
  • Community Questions & Answers (opens in a new tab)
  • Contact support (opens in a new tab)
  1. Home
  2. Developers and admins
  3. Customization
  4. Extend the administration interface
  5. UI form components
  6. UI form component reference extractors

UI form component reference extractors


Was this page helpful?

Send us feedback Go back to top

The system tracks usage of content items to help editors determine the impact of modifying content items on the published data. The system tracks all content item references created using the default system form components (combined content selector, rich text editor). For all custom UI form components that contain links to content item assets or references to content items (e.g., a custom URL selector, a custom rich text inline editor), you need to implement a custom reference extractor.

Additionally, the system tracks references to forms from Page Builder component properties. Properties using the form selector component are tracked automatically. If you use a custom form component (e.g., based on the object selector) to reference forms, you need to mark those properties for form reference tracking. See Assign form reference tracking to Page Builder component properties.

Implement reference extractors

Implement a custom class based on where you want to extract references from:

  • Page and Email Builder component properties
  • Content type fields

Page and Email Builder component properties extractors

To extract references from Page Builder component properties (widget, section, and page template properties) and Email Builder component properties, implement the IContentItemReferenceExtractor interface in a custom class. Within the Extract method, process the content of the property and return a collection of ContentItemReference objects, which contain GUID Identifier of content items that are linked in the property.

You need to register the extractor and assign the extractor to all properties where references to content items were created using custom form components.

Content type fields extractors

To extract references from content type fields, implement the IFormFieldContentItemReferenceExtractor interface in a custom class. The interface requires you to implement the following methods:

  • Extract – processes the content of the field and returns a collection of ContentItemReference objects, which contain GUID Identifier of content items that are linked in the field.
  • CanExtractReferences – returns a bool value that specifies whether the extractor supports the field type specified in the FormFieldInfo parameter. To determine whether a field contains references that can be extracted, use the field's data type (fieldInfo.DataType property) and the form control used by the field (fieldInfo.GetComponentName() method).

You need to register the extractor. After any content item is modified, content type fields of the item are checked against all registered IFormFieldContentItemReferenceExtractor implementations and their CanExtractReferences methods to determine if references need to be extracted from said fields and the extraction is performed using the Extract method of the suitable extractor.

The following example shows the implementation of the default reference extractor used by the system to extract references from rich text fields:

C#Default extractor for references in the system rich text fields
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

using AngleSharp.Html.Dom;
using AngleSharp.Html.Parser;

using CMS;
using CMS.ContentEngine;
using CMS.Core;
using CMS.FormEngine;

...

public class ContentItemReferenceExtractor : IFormFieldContentItemReferenceExtractor
{
    private const string CONTENT_ITEM_GROUP_NAME = "ContentItemGuid";
    private const string GUID_REGEX = @"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";

    private readonly HtmlParser htmlParser;
    private readonly Regex contentItemLinkRegex = new Regex(@$"getContentAsset\/(?<{CONTENT_ITEM_GROUP_NAME}>{GUID_REGEX})\/{GUID_REGEX}\/", RegexOptions.Compiled | RegexOptions.IgnoreCase);

    public ContentItemReferenceExtractor()
    {
        htmlParser = new HtmlParser();
    }

    // Returns whether the field in the parameter is supported by this extractor
    public bool CanExtractReferences(FormFieldInfo field)
    {
        return string.Equals(field.DataType, FieldDataType.RichTextHTML, StringComparison.InvariantCultureIgnoreCase) ||
            (string.Equals(field.GetComponentName(), RichTextEditorConstants.IDENTIFIER, StringComparison.OrdinalIgnoreCase) &&
                (field.DataType.Equals(FieldDataType.Text, StringComparison.Ordinal) || field.DataType.Equals(FieldDataType.LongText, StringComparison.Ordinal)));
    }


    // Returns a collection of reference object found in the field
    public IEnumerable<ContentItemReference> Extract(object fieldValue)
    {
        if (fieldValue is not string html)
        {
            return Enumerable.Empty<ContentItemReference>();
        }

        var referencesGuids = new HashSet<Guid>();
        var document = htmlParser.ParseDocument(html);

        referencesGuids.UnionWith(document.Images.Where(image => contentItemLinkRegex.IsMatch(image.Source))
            .Select(image => GetContentItemReferenceGuidFromLink(image.Source)));

        var anchors = document.QuerySelectorAll("a").Select(anchors => anchors as IHtmlAnchorElement);

        referencesGuids.UnionWith(anchors.Where(anchor => contentItemLinkRegex.IsMatch(anchor.Href))
            .Select(anchor => GetContentItemReferenceGuidFromLink(anchor.Href)));

        return referencesGuids.Select(guid => new ContentItemReference { Identifier = guid });
    }

    // Converts plaintext links to GUIDs
    private Guid GetContentItemReferenceGuidFromLink(string source)
    {
        return Guid.Parse(contentItemLinkRegex.Match(source).Groups[CONTENT_ITEM_GROUP_NAME].Value);
    }
}

Universal extractors

It is generally recommended to use individual extractors for distinct fields or properties. However, as the IFormFieldContentItemReferenceExtractor inherits from the IContentItemReferenceExtractor, you can create a universal extractor for all fields and properties where the references are stored in the same format.

Register reference extractors

To register a reference extractor, use the RegisterImplementation assembly attribute. This attribute ensures the reference extractor is recognized by the system.

C#Registration of an extractor
[assembly: RegisterImplementation(typeof(IFormFieldContentItemReferenceExtractor),
                                  typeof(ContentItemReferenceExtractor),
                                  Lifestyle = Lifestyle.Singleton,
                                  Priority = RegistrationPriority.Default)]

Assign reference extractors to Page and Email Builder component properties

After you implement and register an instance of the IContentItemReferenceExtractor, you need to assign it to all Page Builder component properties (widget, section, and page template properties) or Email Builder component properties that may contain the corresponding type of references to content items.

Use the TrackContentItemReference attribute and specify the type of your extractor as a parameter. Two versions of the attribute are available in different namespaces:

  • Kentico.PageBuilder.Web.Mvc – for Page Builder component properties
  • Kentico.EmailBuilder.Web.Mvc – for Email Builder component properties
C#Properties model
// Page Builder widget properties model example
public class CustomPageBuilderWidgetProperties : IWidgetProperties 
{
    [CustomEditingComponent]
    [Kentico.PageBuilder.Web.Mvc.TrackContentItemReference(typeof(CustomExtractor))]
    public string PropertyName { get; set; }
}

// Email Builder widget properties model example
public class CustomEmailBuilderWidgetProperties : IEmailWidgetProperties 
{
    [CustomEditingComponent]
    [Kentico.EmailBuilder.Web.Mvc.TrackContentItemReference(typeof(CustomExtractor))]
    public string PropertyName { get; set; }
}

Assign form reference tracking to Page Builder component properties

If you use a custom form component to reference forms (e.g., through the object selector), you need to mark the corresponding properties with the TrackFormReference attribute from the Kentico.PageBuilder.Web.Mvc namespace. The attribute can be applied to properties of type IEnumerable<ObjectRelatedItem> or ObjectRelatedItem.

Properties of Page Builder widgets that use the form selector component are automatically included in form usage tracking.

Form reference tracking is not supported for properties within Page Builder sections and page templates.

Unlike content item reference tracking, you do not need to implement a custom extractor.

C#Properties model
using Kentico.PageBuilder.Web.Mvc;
using Kentico.Xperience.Admin.Base.FormAnnotations;

// Custom form selector using the object selector
public class CustomFormWidgetProperties : IWidgetProperties
{
    [ObjectSelectorComponent("cms.form", MaximumItems = 1, Label = "Selected form", Order = 1)]
    [TrackFormReference]
    public IEnumerable<ObjectRelatedItem> SelectedForm { get; set; } = new List<ObjectRelatedItem>();
}

On this page

  • Implement reference extractors
    • Page and Email Builder component properties extractors
    • Content type fields extractors
  • Register reference extractors
    • Assign reference extractors to Page and Email Builder component properties
    • Assign form reference tracking to Page Builder component properties

Related pages

  • Editing components
  • UI form components
  • Widget properties
  • Inline editors for widget properties