---
title: Migrate widget data as reusable content
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

In this technical deep dive, we will show you how to migrate widget data from Kentico Xperience 13 (KX13) into reusable content items when upgrading to Xperience by Kentico (XbyK). You will learn how to use the [Xperience by Kentico: Kentico migration tool](https://github.com/Kentico/xperience-by-kentico-kentico-migration-tool) together with **custom widget migrations** to transform widget data into reusable content items in Content hub, and reference those items from your migrated widgets in XbyK.

This material focuses on practical widget data migration and code adjustments, exploring the approach that combines Source item API discovery with targeted adjustments we talked about in our [Upgrade widgets from Kentico Xperience 13](https://docs.kentico.com/modules/upgrade-widget-migration.md).

## Understand our migration scenario

For this example, we'll be using the _Hero image_ widget from the KX13 Dancing Goat sample site.

![Hero image widget example in the KX13 Dancing Goat instance](https://docs.kentico.com/docsassets/modules/plan-widget-migration/hero-image-KX13.jpg "Hero image widget example in the KX13 Dancing Goat instance")

Currently, the _Hero image_ widget in KX13 stores all its data directly within its property configuration, which lives in the _CMS\_Document_ table for each page. It has these properties:

- An **image** for the background
- A **text** for the heading
- A **button text** for the call-to-action
- A **button target** URL
- A **theme** selector for light or dark styling

Each widget instance requires editors to manually fill out all this information, and the content can't be reused across different pages.

Together we'll extract the content-related properties (`Text`, `ButtonText`, `ButtonTarget`) into reusable content items stored in the Content hub, while keeping the presentation properties (`Image`, `Theme`) in the widget itself. As a bonus, we'll enhance the widget by adding a custom button text override option and a new "Open in new tab" property.

![A visual representation of the hero widget migration](https://docs.kentico.com/docsassets/modules/plan-widget-migration/hero-image-widget-migration.png "A visual representation of the hero widget migration")

## Map out the widget upgrade workflow

The Kentico migration tool allows you to migrate data iteratively, which we will take advantage of in this scenario. Here's our roadmap:

1. **Run the initial data migration** excluding the pages that contain _Hero image_ widgets.
2. **Create the target content type** in your XbyK instance and generate its code files.
3. **Build the custom migration logic** to transform your widget content.
4. **Run the migration with our custom logic** to transform the widget data.
5. **Adjust the widget code** in the target XbyK instance.

> **Tip:** **Keep these migration best practices in mind:**
>
> - When checking your migrated widget data in the database, always look for GUIDs, not IDs. Numerical IDs will not necessarily match between KX13 and XbyK. They are generated fresh for each new object in a database.
> - Create database backups between successful migrations so you can roll back if needed.
> - To troubleshoot, you can enable detailed (trace) logging in the migration tool:
>
> ```json title="Migration.Tool.CLI/appsettings.json" highlight="8-9"
> ...
> {
>   "Logging": {
>     "LogLevel": {
>       "Default": "Information",
>       "System": "Warning",
>       "Microsoft": "Warning",
>       "Migration.Tool.Source.Services.VisualBuilderPatcher": "Trace",
>       "Migration.Tool.Extensions.CustomWidgetMigrations": "Trace"
>     },
> ...
> ```

## Migrate your site data without widget pages

Let's start by migrating your site data while excluding the pages that contain our _Hero image_ widgets. You can approach this in two ways: either exclude pages entirely using migration command parameters, or exclude specific objects in the migration tool's configuration file.

For our example, we'll use the command parameter approach to migrate everything except pages:

```cmd title="Initial migration excluding pages"
.\Migration.Tool.CLI.exe  migrate --sites --custom-modules --users --settings-keys
```

This gives us a clean foundation to work with. Later, we'll run the migration again with our custom widget migration logic to handle all _Hero image_ widgets across the Dancing Goat site.

Before running any migration command, make sure you have:

- Your source KX13 instance running
- Your target XbyK instance stopped
- [Source instance API discovery](https://github.com/Kentico/xperience-by-kentico-kentico-migration-tool/blob/master/Migration.Tool.CLI/README.md#source-instance-api-discovery) enabled in your migration configuration
  - You'll need this for the widget migration we'll build later; see an example in [upgrade walkthrough](https://docs.kentico.com/guides/upgrade-to-xbyk/upgrade-walkthrough/migrate-data-and-binary-files.md#configuration).

After a successful migration, you should be able to run your target instance.
When you sign in to the administration, you'll see that the DancingGoatCore site has become a website channel without any pages.

## Set up the Hero reusable content type

Now we need to create the **Hero** reusable content type that will store our migrated widget content in the Content hub.

### Define the content type in administration

Start your target XbyK instance and navigate to the **Content types** application in the administration interface. Create your Hero content type with these settings:

- **Content type name:** Hero
- **Namespace:** DancingGoatCore
- **Name:** Hero
- **Icon:** Choose any icon you like
- **Use for:** Reusable content (this is crucial—it makes the content available in the Content hub)
- **Short code name:** Leave the auto-generated value

![Hero reusable content type in the Xperience administration - general properties](https://docs.kentico.com/docsassets/modules/plan-widget-migration/hero-ct-1.png "Hero reusable content type in the Xperience administration - general properties")

Add these three fields, each of the **Text** type, marked as **Required** and using the **Text input** form control:

- **HeroHeading**
- **HeroTarget**
- **HeroCallToAction**

![Hero reusable content type in the Xperience administration - fields](https://docs.kentico.com/docsassets/modules/plan-widget-migration/hero-ct-2.png "Hero reusable content type in the Xperience administration - fields")

### Generate code files

Now let's generate the strongly-typed C# classes for our new Hero content type. Make sure you have the DancingGoat.Entities project set up first—see our [upgrade walkthrough](https://docs.kentico.com/guides/upgrade-to-xbyk/upgrade-walkthrough/adjust-global-code.md#add-a-new-project-to-hold-generated-files) for details.

Run this command from your main project's root directory (in our case, the _DancingGoat.Web_ folder):

```cmd title="Generate Hero content type classes"
dotnet run --no-build -- --kxp-codegen --type "ReusableContentTypes" --namespace "DancingGoatCore" --location "../DancingGoat.Entities/{type}/{name}"
```

You'll find the generated _Hero.generated.cs_ file in your _DancingGoat.Entities_ project under the _ReusableContentTypes_ folder. It should look like this:

```csharp title="Hero.generated.cs"
//--------------------------------------------------------------------------------------------------
// <auto-generated>
//
//     This code was generated by code generator tool.
//
//     To customize the code use your own partial class. For more info about how to use and customize
//     the generated code see the documentation at https://docs.xperience.io/.
//
// </auto-generated>
//--------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using CMS.ContentEngine;

namespace DancingGoatCore
{
    /// <summary>
    /// Represents a content item of type <see cref="Hero"/>.
    /// </summary>
    [RegisterContentTypeMapping(CONTENT_TYPE_NAME)]
    public partial class Hero : IContentItemFieldsSource
    {
        /// <summary>
        /// Code name of the content type.
        /// </summary>
        public const string CONTENT_TYPE_NAME = "DancingGoatCore.Hero";


        /// <summary>
        /// Represents system properties for a content item.
        /// </summary>
        [SystemField]
        public ContentItemFields SystemFields { get; set; }


        /// <summary>
        /// HeroHeading.
        /// </summary>
        public string HeroHeading { get; set; }


        /// <summary>
        /// HeroTarget.
        /// </summary>
        public string HeroTarget { get; set; }


        /// <summary>
        /// HeroCallToAction.
        /// </summary>
        public string HeroCallToAction { get; set; }
    }
}
```
