Migrate widget-collection relationships
When you migrate widget-collection relationships to Xperience by Kentico (XbyK), you’re not just transferring data — you’re making a content-modeling decision.
A widget-collection relationship is the link between a widget and the set of content items it displays.
In Kentico Xperience 13 (KX13), these relationships are often represented indirectly through child pages, folder structures, widget properties, or custom patterns. Migrating this structure as-is (lift-and-shift) can lead to post-migration data reshaping and long content freezes. You can avoid this by customizing the Kentico Migration Tool so the data arrives in the right shape from the start.
This guide covers four strategies for migrating widget-collection relationships to Xperience by Kentico and helps you choose the right one for your project.
By the end of this guide, you should be able to:
- recognize widget-collection migration scenarios
- understand four recommended target strategies
- compare the tradeoffs of each strategy
- choose an approach based on editorial, architectural, and maintenance needs
Understand the scenario
In KX13, projects often store content collections as child pages or folder-like structures in the content tree. Widgets reference these folders and display the collection, e.g., hero slides, article lists, timelines, and similar patterns. These folders and pages typically don’t represent navigable web pages in the website structure. They act as data sources to populate widgets on the parent page.
In XbyK, mixing data-only items into your site’s page hierarchy adds unnecessary clutter and can confuse editors who expect tree items to represent pages.
For this reason, the migration goal is to move to a flatter, more flexible model and preserve the relationship between each widget and the collection it consumes, rather than preserving the page-collection structure exactly as it appears in KX13.
Here’s an example: the Home page is a landing page with widgets, and the underlying folders (Hero Slides, CTAs, Call outs, Articles, Timeline) hold the collection items:

During a project upgrade to Xperience by Kentico, we recommend migrating these content-only pages into the Content hub as reusable content items and flattening the content tree. From there, you need to decide how to organize those items in the Content hub and how widgets will reference them.
The four recommended strategies
The goal is to transform your data, taking advantage of XbyK’s capabilities while keeping the editing experience user-friendly. All four strategies achieve this in different ways, organizing and referencing the collection in the Content hub.
- Use a parent reusable content item referenced by a widget
- Store the collection in a widget property
- Leverage smart folders and a smart-folder widget property
- Represent collections via taxonomy
Watch the video for a visual overview of all four strategies. Then use the rest of this guide for more detailed written guidance and quick-reference decision support.
Notice that we do not recommend turning each collection into a fixed field on the page type. A page can contain different widgets over time, and editors may remove or replace those widgets as the page evolves. For that reason, the target model should keep the page flexible and represent the collection in a way that supports widget-based composition.
Compare the strategies
|
Strategy |
Best for |
Benefits |
Tradeoffs |
|
Use a parent reusable content item |
Shared managed collections |
|
|
|
Store the collection in a widget property |
Local explicit collections |
|
|
|
Leverage smart folders |
Dynamic source-driven collections |
|
|
|
Represent collections via taxonomy |
Classification-based grouping |
|
|
Decide which approach best fits your use case
Use this practical guidance to choose the strategy that fits your target model.
Choose the parent reusable content item approach when:
- the collection should be centrally managed
- the same grouping appears in multiple places
- governance and consistency matter
- the collection has value beyond one page
For example: The “Homepage Hero Slides” collection is reused on the homepage, seasonal landing pages, and campaign microsites. Editors manage one reusable collection item in Content hub.
Choose the store the collection in a widget property approach when:
- the collection is local to a page or widget
- explicit curation is needed
- reuse is minimal
- simplicity is the priority
For example: A campaign landing page has a temporary curated list of 4 promotions that editors want to edit directly in the widget.
Choose a smart-folder widget property approach when:
- the collection should be sourced dynamically
- editors should manage the source grouping rather than the final list
- the collection changes over time
- source-based grouping is the right long-term model
For example: An “Upcoming Events” widget should automatically pull all future-dated event items from a defined source group.
Choose the taxonomy-based approach when:
- the grouping is based on classification
- items may belong to multiple collections
- the project needs scalable metadata-driven grouping
- cross-cutting reuse is important
For example: An Articles widget on multiple pages filters by topics such as Security, Integrations, or Performance, so editors manage classification once and reuse it everywhere.
Use multiple strategies
Most projects include multiple widget-collection scenarios, so you can and should use different strategies within the same project.
Choose the strategy based on how each widget consumes its collection, not on how the legacy folders happened to sit under the page.
Validate your target model before implementation
Before implementing the migration, confirm the following:
- what the collection represents in the business domain
- whether the grouping is structural or conceptual
- whether items need to belong to multiple collections
- what the target widget or component expects
- how editors will manage it after launch
- whether the selected model improves on the legacy structure
Avoid common anti-patterns
- copying the legacy structure directly without evaluating the target needs
- choosing the easiest migration path instead of the best long-term model
- using reusable content items for collections that are never reused
- using taxonomy or smart folders when editors really need explicit curation
- keeping collections in widget properties when they should be centrally governed
- using regular content folders as a delivery grouping strategy (content folders are for administration organization and navigation only; use smart folders when grouping needs to drive delivery behavior)
Implement your chosen strategies
Once you choose a strategy, use the following implementation overviews and code samples to guide your migration.
Lay the groundwork - applies to all approaches
In all four cases, we are flattening the content tree and migrating content-only pages from KX13 into XbyK’s Content hub as reusable items. Therefore, each strategy requires configuring the Kentico Migration Tool to perform this transformation, using the ConvertClassesToContentHub option in the appsettings.json config file. For example:
...
"ConvertClassesToContentHub": "DemoSite.TimelineEntry, DemoSite.HeroSlide, DemoSite.CallOut",
...
See details in the migration tool GitHub repository.
All four strategies rely on a widget property migration, so for all of them, the following steps apply:
- Define a widget property migration (
IWidgetPropertyMigration) targeting the relevant property. - Create a widget migration (
IWidgetMigration) targeting the source widget identifier. - In the widget migration, declare the widget property migration strategy for the relevant property.
- Register both the widget migration and widget property migration in the service collection.
Learn more about custom widget migration in our guides.
The strategies differ in how the widget organizes and references those items.
Use a parent reusable content item
What this transforms: a widget property that points to a folder-like source becomes a single reusable parent content item reference.
- Create a
MultiClassMappingfor the source folder page type, settingClassContentTypeType.REUSABLEandClassWebPageHasUrl = false. This causes the migration tool to migrate that page type into Content hub as a reusable content item during the page migration phase, before the widget migration runs. - Map source fields to target fields using
BuildField().SetFrom(). - Register the mapping with
AddSingleton<IClassMapping>().
Find more information on custom class mapping in the migration tool repository. Learn how to utilize AI agents to aid with mapping larger classes in our Speed up remodeling with AI guide.
...
var m = new MultiClassMapping(targetClassName, target =>
{
target.ClassName = targetClassName;
target.ClassTableName = "Hero_slides";
target.ClassDisplayName = "Hero slides";
target.ClassType = ClassType.CONTENT_TYPE;
target.ClassContentTypeType = ClassContentTypeType.REUSABLE;
target.ClassWebPageHasUrl = false;
});
// map any fields you need
m.BuildField("XYZ")
.SetFrom(sourceClassName, "ABC", true)
.WithFieldPatch(f => f.SetPropertyValue(FormFieldPropertyEnum.FieldCaption, "new value"));
serviceCollection.AddSingleton<IClassMapping>(m);
...
- Use a content item director to link the migrated child items to the parent content item in Content hub. The director runs during the page migration phase and automatically creates the relationship field between parent and children.
- In the widget property migration, return a single
ContentItemReferencepointing to the parent content item. The parent was already migrated into Content hub during the page migration phase. Its GUID in XbyK is derived from its KX13 node GUID — useEnsureNodeGuid()with the node GUID stored in the source page selector value to resolve it.
Store the collection directly in a widget property
What this transforms: a folder reference in the source widget property becomes a direct list of content item references in the target widget property.
- In the widget property migration, query the child nodes of the folder node referenced by the page selector value.
- Resolve the target GUIDs of the child items using
EnsureNodeGuid(). - Return the result as a list of
ContentItemReferenceobjects.
...
// The source widget property holds a page selector pointing to a promotions folder.
// This migration flattens that folder into a direct list of content item references
// so editors can manage the promotions directly in the widget property.
if (value?.ToObject<List<PageSelectorItem>>() is { Count: > 0 } items)
{
var children = GetChildGuids(items.First().NodeGuid);
var result = children.Result
.Select(x => new ContentItemReference { Identifier = spoiledGuidContext.EnsureNodeGuid(x, siteId) })
.ToList();
var resultAsJToken = JToken.FromObject(result);
return Task.FromResult(new WidgetPropertyMigrationResult(resultAsJToken));
}
...
Leverage smart folders and smart-folder widget properties
What this transforms: a source folder/page selector becomes a smart-folder reference that resolves the collection dynamically.
- In the widget property migration, create a
SmartFolderInfowith a filter that targets the relevant content items. - Return a
SmartFolderReferenceas the widget property value.
...
// The source widget property holds a page selector pointing to an events folder.
// This migration creates a smart folder filtered by the appropriate criteria
// so the widget resolves its collection dynamically after migration.
var newSmartFolder = new SmartFolderInfo
{
SmartFolderName = folderName,
SmartFolderDisplayName = folderTitle,
SmartFolderGUID = GuidHelper.CreateFolderGuid(folderName),
SmartFolderIsContentDeliveryEnabled = true,
// Define filter criteria appropriate for your use case
SmartFolderFilter = "{ ... }"
};
SmartFolderInfo.Provider.Set(newSmartFolder);
var result = new SmartFolderReference { Identifier = newSmartFolder.SmartFolderGUID };
var resultAsJToken = JToken.FromObject(result);
return new WidgetPropertyMigrationResult(resultAsJToken);
...
The SmartFolderFilter field expects a specific JSON structure. To see examples, create a smart folder manually in your Xperience by Kentico instance and inspect the SmartFolderFilter column in the CMS_SmartFolder database table.
For example, the following filter returns content items of the content type with the specified GUID:
{"classGUID":["8a4c740c-e8d1-4452-af02-8db2b41e1930"],"tags":[],"lastPublishedAbsolute":null,"lastPublishedRelative":null,"selectedLastPublishedTimeFrame":"absolute"}
You can also use this filter structure to filter by taxonomy tags.
Represent collections via taxonomy
What this transforms: folder-based grouping in the source becomes taxonomy tagging, and the widget property stores taxonomy-based selection.
- Create a
MultiClassMappingfor the source child page type and add aUsageTagstaxonomy field usingAddField(), configured with the taxonomy group GUID. - Register the mapping before running the widget migration.
...
// Add a taxonomy field to the Article content type so items can be tagged
// by topic and resolved across multiple widgets and pages.
var m = new MultiClassMapping(targetClassName, target =>
{
target.ClassName = targetClassName;
target.ClassTableName = "MyProject_Article";
target.ClassDisplayName = "Article";
target.ClassType = ClassType.CONTENT_TYPE;
target.ClassContentTypeType = ClassContentTypeType.REUSABLE;
target.ClassWebPageHasUrl = false;
});
m.AddField("UsageTags", "taxonomy")
.WithFieldPatch(field =>
{
field.AllowEmpty = true;
field.Caption = "Usage Tags";
field.DataType = "taxonomy";
field.Settings["controlname"] = "Kentico.Administration.TagSelector";
field.Settings["TaxonomyGroup"] = "[\"<taxonomy-guid>\"]";
});
serviceCollection.AddSingleton<IClassMapping>(m);
...
- In the widget property migration, create a tag via
IImporterusing the folder name and parent page name as identifiers. - Query the child nodes of the source folder and assign the tag to each migrated content item by creating a draft, updating it with the tag value, and publishing.
- Return a
ContentItemReferencepointing to the tag GUID directly as the widget property value.
...
// The source widget property holds a page selector pointing to a topic folder
// (e.g. Blogs). This migration creates a tag for that topic
// and assigns it to all child articles, so the widget can resolve
// the same collection by tag across multiple pages.
if (tagInfo is TagInfo tag)
{
var tagGuid = tag.TagGUID;
// Assign the tag to each migrated content item using IContentItemManager.
foreach (var item in contentItems)
{
ContentItemData data = new(new Dictionary<string, object>
{
{ "UsageTags", "[{ \"Identifier\":\"" + tagGuid + "\"}]" }
});
var contentItemManagerFactory = Service.Resolve<IContentItemManagerFactory>();
var defaultAdmin = UserInfoProvider.ProviderObject.Get(UserInfoProvider.DEFAULT_ADMIN_USERNAME);
var contentItemManager = contentItemManagerFactory.Create(defaultAdmin.UserID);
// Create draft version.
bool draftCreated = await contentItemManager.TryCreateDraft(item.ContentItemID, languageName);
if (!draftCreated) { continue; }
// Update draft with new data.
bool updateSuccess = await contentItemManager.TryUpdateDraft(item.ContentItemID, languageName, data);
if (!updateSuccess) { continue; }
// Publish the updated draft.
bool publishSuccess = await contentItemManager.TryPublish(item.ContentItemID, languageName);
if (!publishSuccess) { continue; }
}
// Return the tag reference directly as the widget property value.
// The widget resolves the collection by tag at runtime.
var result = new ContentItemReference { Identifier = tagGuid };
var resultAsJToken = JToken.FromObject(result);
return new WidgetPropertyMigrationResult(resultAsJToken);
}
...
The tagging process uses IContentItemManager. For full API reference and usage examples, see Content items API in our documentation.
What’s next?
This guide focused on choosing the right target model for widget-collection relationships and mapping those choices to migration implementation patterns.
For property-level migration details and UI control mapping, review transforming widget properties. For end-to-end examples of moving widget-owned data into reusable Content hub items, see migrating widget data to Content hub.
You can find more advanced upgrade and data migration scenarios in our upgrade deep dive guides. If you haven’t already, follow the upgrade walkthrough to see these decisions in the context of a full project upgrade.
If you encounter a widget-collection scenario that doesn’t fit these strategies well, let us know through the Send us feedback button at the bottom of this page.