---
title: Adjust your code and adapt your project
---

> 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).

While sites built on **Kentico Xperience 13 (KX13)** and **Xperience by Kentico (XbyK)** are all .NET applications, there are some differences in the code to consider when upgrading to XbyK, and considerations for where to go with a project once it is on the new platform.

This guide will provide more details about the code adjustment and validation points from the [upgrade overview](https://docs.kentico.com/modules/upgrade-overview/upgrade-from-kx13-overview.md).

> **Tip:** The [KentiCopilot](https://docs.kentico.com/guides/development/kenticopilot.md) [KX13 migration plugin](https://github.com/Kentico/xperience-by-kentico-kenticopilot/tree/main/plugins/kentico-kx13-migration) takes on much of the work on this page. Its skills audit the content model of your KX13 project, generate and run the migration tool's configuration and customizations, and then migrate global code, shared components, Page Builder widgets and page presentation logic. The plugin works in any AI coding assistant with agent plugin support (such as GitHub Copilot or Claude Code). To see what each stage looks like in practice, including what the agent hands back and what still needs your attention, see [Assisted upgrades](https://docs.kentico.com/guides/upgrade-to-xbyk/assisted-upgrades.md).

> **Info:** We've released a [Kentico Xperience 13 library on Context7](https://context7.com/websites/kentico_13) that you can use to look up KX13 API references and code samples when working on code migration. Note that Context7 is a third-party service not maintained or supported by Kentico, so your experience may vary.

## Adjust your code

### Update content querying code

Xperience by Kentico uses the [ContentRetriever API](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/content-retriever-api.md) and the [Content item query API](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/content-item-query-api.md) to query content, in place of [DocumentQuery and MultiDocumentQuery](https://docs.kentico.com/13/custom-development/working-with-pages-in-the-api.md) from Kentico Xperience 13.

The documentation in the above link has more information about the specifics of how it works, but in broad strokes, here are the steps to retrieve content:

- **ContentRetrieval API**
  - This is an approach we recommend.
  - Use an `IContentRetriever` object and its generic extension methods that fit your scenario, e.g., `RetrieveContentByGuids` or `RetrieveCurrentPage`.
    - Specify the content type you want to retrieve for each method call - the implementation takes care of the data mapping for you.
    - You can pass additional information specifying your request through method parameters, like `additionalQueryConfiguration` or `cacheSettings`.
- **Content item query API**
  - You can use this approach for advanced scenarios which the ContentRetrieval API doesn't cover.
  - Use a `ContentItemQueryBuilder` object to construct a query.
    - Apply one of the `ForContentType` or `ForContentTypes` extension methods to filter the query based on system aspects of the content type. For example, whether content items include a given reusable field schema, whether they _link to_ or _are linked from_ another item, and whether they are part of a given website channel.
    - Call the `Parameters` extension method to add standard query operations like _OrderBy_ and _Where_ conditions that test the values of the content type's fields.
    - Call the `InLanguage` extension method to determine which language versions of content items Xperience should retrieve.
      - If a website channel uses [language-specific domains](https://docs.kentico.com/documentation/developers-and-admins/configuration/languages.md#content-languages-and-channel-url-formats), make sure to [use the correct language fallback behavior](https://docs.kentico.com/documentation/developers-and-admins/development/content-retrieval/retrieve-page-content/retrieve-page-urls.md) when retrieving pages or work with absolute URLs instead of just URL paths.
  - Use an `IContentQueryExecutor` to get a result from the query.

We recommend creating some kind of shared resource that you can use across your project to centralize content querying logic, such as a service.

> **Info:** The [ContentItemRetrieverService](https://github.com/Kentico/xperience-by-kentico-training-guides/blob/finished/src/TrainingGuides.Web/Features/Shared/Services/ContentItemRetrieverService.cs) from our Training guides repository illustrates both approaches, though you may want to create different methods to more closely mirror the content in your KX13 project.

There are some notable changes in related functionality as well:

- `PageDataContext` and `IPageDataContextRetriever` are now `WebPageDataContext` and `IWebPageDataContextRetriever`.
  - Unlike the `Page` property of `PageDataContext` in KX13, XbyK's `WebPageDataContext` does not contain the full page data. It contains a `RoutedWebPage` object with information you can use to retrieve the correct page.
- KX13's `IPageUrlRetriever` corresponds to `IWebPageUrlRetriever`, which now works asynchronously.
- The Kentico Migration Tool converts page attachments and media library files to [content item assets](https://docs.kentico.com/documentation/business-users/content-hub/content-item-assets.md). It creates the content types the migrated files use: `Legacy.Attachment` for attachments and `Legacy.MediaFile` for media library files.

### Adjust Page Builder components

In Kentico Xperience 13, Page Builder components such as _widgets_, _page templates_, and _sections_ use C#-based editing components for their properties. These editing components are assigned to properties using attributes such as this one:

```csharp title="Kentico Xperience 13 editing component assignment"
// Assigns the 'TextInputComponent' as the editing component of the 'TextProperty' property
[EditingComponent(TextInputComponent.IDENTIFIER)]
public string TextProperty { get; set; }
```

Xperience by Kentico supports the same format for the sake of backward compatibility, but primarily uses a new format of [UI form components](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-form-components/reference-admin-ui-form-components.md). These components are assigned using dedicated attributes, for example:

```csharp title="Xperience by Kentico editing component assignment"
// Assigns the 'TextInputComponent' as the editing component of the 'TextProperty' property
[TextInputComponent(Label = "Enter text")]
public string TextProperty { get; set; }
```

If you choose to enable [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) during data migration, which we recommend, you will need to change the attributes used by the properties of your Page Builder components to the new UI form components. Otherwise, your project will continue to use Page Builder in _Legacy mode_, which won't require these changes but lacks many benefits for the content editors.

### Rehome custom tables

Xperience by Kentico does not have a direct analog for the [Custom tables](https://docs.kentico.com/13/developing-websites/defining-website-content-structure/managing-custom-tables.md) functionality in legacy Kentico products.

By default, the Kentico Migration Tool creates a [custom object type](https://docs.kentico.com/documentation/developers-and-admins/customization/object-types.md) for each custom table, but leaves you in charge of defining their user interface.

If you choose to do so, each _custom table_ will correspond to an _object type_ or class, and each _custom table row_ will correspond to an _object_ of that type. You'll need a UI application page to host one or more custom tables to define the following parts for each of these custom table types:

- An alternative form that determines which form controls Xperience should render for each field of the object type
- A [listing page](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-pages/reference-ui-page-templates/listing-ui-page-template.md) that displays a list of the objects and includes delete functionality
- An [\*Edit section\* and an \*Edit page\*](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-pages/reference-ui-page-templates/edit-ui-page-template.md) that allow editors to alter the values of individual objects
- A [Create page](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-pages/reference-ui-page-templates/edit-ui-page-template.md#use-edit-pages-to-create-new-objects) to add new objects

You can choose whether each type should have its own [UI application page](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-pages/ui-application-pages.md) or if they should be located collectively beneath the same application page.

This may sound complicated, but these basic operations are fairly simple to implement, and you can find an example of building such a UI in our [training guides](https://docs.kentico.com/guides/development/customizations-and-integrations/create-basic-module.md#build-the-module-ui). The CLI tools in [this repository](https://github.com/seangwright/xperience-community-dotnet-item-templates) can help to speed up the process.

We recommend this approach when the data in the table is more procedural than content-focused, or your client needs to edit the values through a dedicated admin UI.

When custom tables contain structured content, we recommend using [reusable content items](https://docs.kentico.com/documentation/business-users/content-hub.md) instead.

You can use the `ConvertClassesToContentHub` configuration in the **appsettings.json** file of the _Migration.Tool.CLI_ project to [automatically convert your custom tables to reusable content types](https://github.com/Kentico/xperience-by-kentico-kentico-migration-tool/tree/master/Migration.Tool.CLI#convert-pages-or-custom-tables-to-content-hub). Then you will not need to build a dedicated UI for the existing types, or any similar types your client might want in the future.

Editors can use the [Content hub](https://docs.kentico.com/documentation/business-users/content-hub.md) to manage the items. By selecting a content type in the Content hub's filter, they can view the custom table's data.

### Convert custom module pages

Xperience by Kentico's admin UI no longer runs on web forms, so you'll need to recreate any [custom module pages](https://docs.kentico.com/13/custom-development/creating-custom-modules.md) as [UI pages](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/ui-pages.md) in XbyK.

Most custom modules revolve around performing basic operations on custom objects, so in many cases, the [previous heading's](#rehome-custom-tables) guidance about the types of pages you'll need still applies.

Xperience by Kentico also supports custom page templates, if your scenario requires more advanced customization. You can find an example in the [admin boilerplate project](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface/prepare-your-environment-for-admin-development.md#client-development-boilerplate).

You can find resources covering the process of creating custom modules with complex hierarchical structures in the [training guides](https://docs.kentico.com/guides/development/customizations-and-integrations.md#custom-modules).

You can find general guidance and reference material in the [admin UI documentation](https://docs.kentico.com/documentation/developers-and-admins/customization/extend-the-administration-interface.md).

### Alter auth and user management

Xperience by Kentico introduces a new [Member](https://docs.kentico.com/documentation/business-users/members.md) object type to represent people who register and sign in to the live site. Your team must change [old registration and authentication code](https://docs.kentico.com/13/managing-users/user-registration-and-authentication.md) to [work with the changes](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication.md).

The approaches are fairly similar, as both utilize [ASP.NET Identity](https://learn.microsoft.com/en-us/aspnet/identity/overview/getting-started/introduction-to-aspnet-identity), but syntax has changed. You'll need to make some alterations to your controllers and initialization.

Member accounts [arrive without passwords](https://github.com/Kentico/xperience-by-kentico-kentico-migration-tool/blob/master/Migration.Tool.CLI/README.md#members). The migration tool leaves the KX13 password hashes behind, so every migrated member has a `null` password and can't sign in until that password is reset. Plan the reset flow before you go live, following the process in [Forms authentication](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/forms-authentication.md). External sign-in information stays behind as well, so members who signed in through a provider such as Google or Facebook need [external authentication](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/external-authentication.md) reconnected in your code instead of a reset.

At this time, [multi-factor authentication](https://docs.kentico.com/documentation/developers-and-admins/configuration/users/user-management.md#multi-factor-authentication) in Xperience by Kentico is supported only for users signing into the administration, not for members.

### Choose a search integration

Xperience by Kentico does not support search functionality natively, but it has three search integrations:

- [Lucene](https://github.com/Kentico/xperience-by-kentico-lucene)
- [Azure AI search](https://github.com/Kentico/xperience-by-kentico-azure-ai-search)
- [Algolia](https://github.com/Kentico/xperience-by-kentico-algolia).

Each integration has its own specifics regarding how the code should look, so we recommend reviewing the **docs** folder of the one you choose for specific advice on how to structure its code.

### Address differences in localization

Xperience by Kentico uses [Languages](https://docs.kentico.com/documentation/developers-and-admins/configuration/languages.md), where KX13 used Cultures.

In cases where you want to know the preferred language of current site visitor you can use `IPreferredLanguageRetriever`.

As mentioned earlier, you can use the `InLanguage` extension method for content item query to determine which variant of content items or pages Xperience should retrieve. If a website channel uses [language-specific domains](https://docs.kentico.com/documentation/developers-and-admins/configuration/languages.md#content-languages-and-channel-url-formats), make sure to [use the correct language fallback behavior](https://docs.kentico.com/documentation/developers-and-admins/development/content-retrieval/retrieve-page-content/retrieve-page-urls.md) when retrieving pages or work with absolute URLs instead of just URL paths.

Note that languages are global in XbyK, so if you have KX13 code to retrieve cultures associated with a given site, you'll need to adjust it to account for this.

#### Localization of resource strings

Editors in Kentico Xperience 13 were able to [define custom resource strings](https://docs.kentico.com/13/multilingual-websites/setting-up-a-multilingual-user-interface/working-with-resource-strings.md#adding-your-own-strings) in the administration interface. This functionality doesn't exist natively in XbyK, and there are a few possible approaches to handle custom resource strings.

- **Move them to a resource file** - If you move custom resource strings to a [resource file](https://docs.kentico.com/guides/development/multilingual/display-your-website-content-in-multiple-languages.md#translate-other-application-texts), you can resolve them easily in your application. This, however, does not allow your editors to create new strings.

- **Use the content hub** - If you want to allow editors to create strings, you can create a [reusable content type](https://docs.kentico.com/guides/architecture/content-modeling/model-reusable-content/model-a-reusable-article.md) to represent a string. Editors will create language versions of this type in the Content hub. Then, in code, you can dynamically look up the appropriate translation via the [Content item API](https://docs.kentico.com/documentation/developers-and-admins/api/content-item-api/content-item-query-api.md), for example, in your custom `IStringLocalizer` and `IHtmlLocalizer` [implementations](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization/make-content-localizable).

- **Use the _Community localization_ module** - If it is important to your client to have a separate localization module to manage their custom resource strings rather than working in the Content hub, consider the [Xperience community localization](https://github.com/nittin-cz/xperience-community-localization) module by Nittin, which recreates the experience from KX13. Note that this community module is not developed or supported by Kentico.

- **Implement your own custom module** - If your project requires a specific way of handling resource strings, your team can create a custom implementation using the XbyK [custom module](https://docs.kentico.com/guides/development/customizations-and-integrations/create-basic-module.md) that suits your client’s needs.

#### Localization of the admin UI

Since there are significant differences in the keys and values of resource strings between KX13 and XbyK, you will need to create new resource files for XbyK while [localizing the administration interface](https://docs.kentico.com/documentation/developers-and-admins/customization/admin-ui-localization.md).

We recommend using AI tools to help speed up translation of the default UI string values.

### Migrate commerce

Xperience by Kentico now includes native support for digital commerce. The commerce capabilities have been completely rewritten, which means many components from KX13 do not map directly to XbyK capabilities. As a result, your existing implementations will require updates, and the level of effort will depend on the complexity of each project.

The Kentico Migration Tool brings customers, customer addresses, orders, order items and order addresses across from KX13. Order statuses aren't part of that set, so create them on the target instance and map each KX13 status to its XbyK counterpart under `CommerceConfiguration` → `OrderStatuses` in the tool's **appsettings.json** before you migrate orders. The tool skips any order whose status has no mapping, with only a line in the log to show for it. The tool also sets the new `OrderItemTotalTax` and `OrderItemTaxRate` fields to 0, which matters for any code or report that reads tax off historical orders.

#### Key implementation requirements

To use XbyK commerce features, you first enable and configure the [commerce](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/commerce-config.md) module. From there, you'll [set up the product catalog](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/model-product-catalog.md) and [define products](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/model-product-catalog.md#general-recommendations). Then, you'll need to _upgrade the code that displays the product catalog_. Next, you'll configure [order statuses](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/configure-order-statuses.md) and the built-in [notifications](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/configure-order-statuses.md#enable-notifications-for-order-statuses).

The new XbyK approach offers flexibility, but it also means you'll need to budget for custom development. Beyond displaying the catalog and handling order-related entities, you must upgrade your existing code for:

- [Checkout and shopping cart](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/checkout-process.md) flows.
- [Shipping and payment](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/shipping-and-payment-methods.md) methods.
- Any additional functionality that your KX13 project leverages, for example, _integrations_ with third-party systems.

[Promotions](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/promotions.md) are an exception worth planning around. [Catalog discounts](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/promotions/catalog-discounts.md), [order discounts](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/promotions/order-discounts.md), [coupon codes](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/promotions/coupon-codes.md) and [free shipping](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/promotions/free-shipping.md) come with XbyK, so most of what your KX13 project implemented in code becomes configuration. Rules that go beyond the built-in discount types stay in code, through [customer eligibility customization](https://docs.kentico.com/documentation/developers-and-admins/digital-commerce-setup/promotions/customer-eligibility-customization.md) and the other extension points of the commerce module.

> **Tip:** If you're missing a specific commerce feature, check the [product roadmap](https://roadmap.kentico.com/tabs/6-next-refreshes) to see what's planned. If you don't find what you're looking for, submit the idea to help us prioritize future development.

If you choose to migrate your commerce to [Shopify](https://www.shopify.com/) and use the [Shopify integration](https://github.com/Kentico/xperience-by-kentico-shopify), you won't need your calculation and checkout code, as these things are handled directly in Shopify. From the Xperience side, you'll need to add code to manage the contents of shopping carts and discount coupons.

### Handle marketing changes

XbyK and KX13 both feature online marketing, but key differences exist. Let's take a look into some of them.

When you log custom activities from server-side code in Xperience by Kentico, use `ICustomActivityLogger` instead of `IActivityLogService`. Custom activities no longer need an _initializer_ class for the logger to work. Note that XbyK also allows you to log custom activities with _client-side code_.

Automation processes are rebuilt from scratch in XbyK, but the logic behind your KX13 custom steps has a home. Reimplement each one as a [custom action or custom condition](https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/automation-customization/automation-custom-steps.md), and anything that started a KX13 process on an event as a [custom trigger](https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/automation-customization/automation-custom-triggers.md).

Regarding marketing and consents, note that you should register custom cookies by configuring `CookieLevelOptions` during startup, rather than using `CookieHelper`. Additionally, set cookies in the visitor's browser using `ICookieAccessor`.

### Plan for features with no out-of-the-box equivalent

A few KX13 features have no direct counterpart in Xperience by Kentico at the moment. XbyK offers more modern and composable tools instead, so these are the places where you pick an approach rather than port code: one of our integrations, a [custom module](https://docs.kentico.com/guides/development/customizations-and-integrations/create-basic-module.md), or a wait for something already on the roadmap. The earlier you make each call, the more room your plan has for it.

- **Integration bus** – connectors that synchronize KX13 data with external systems become direct integrations in your own code, triggered by an event or on a schedule. Follow the [product roadmap](https://roadmap.kentico.com/tabs/4-planned) for updates.
- **Personas, lead scoring and advanced segmentation** – [contact groups](https://docs.kentico.com/documentation/business-users/digital-marketing/contact-groups.md) cover deterministic segmentation. Scoring rules and persona assignment require a custom implementation, so treat your KX13 rules as a description of the behavior you need, and build it from scratch.
- **Social marketing** – posts and social campaigns managed from the KX13 administration move to dedicated social tools outside Xperience. Feeding Xperience data into channels like these is a [roadmap item](https://roadmap.kentico.com/c/225-custom-channel-types).
- **A/B testing and web analytics** – both run through integrations. The [tag manager integration](https://github.com/Kentico/xperience-by-kentico-tag-manager) handles the script injection, with VWO for testing and Google Analytics or Microsoft Clarity for analytics. Custom conversions and test variants from KX13 don't carry over, and A/B testing for emails is one to watch on the [roadmap](https://roadmap.kentico.com/tabs/4-planned) rather than a feature to plan around today.
- **Reporting** – [customer journeys](https://docs.kentico.com/documentation/business-users/digital-marketing/customer-journeys.md) show how contacts progress across channels, built from standard and custom activities. For more advanced analytics, you'll typically need a custom module, or an export of the data into your client's BI tool. For simpler cases, take a look at the [Kentico Labs Simple Stats](https://github.com/Kentico/xperience-by-kentico-simple-stats) project, which adds predefined charts for contacts, emails, content and commerce to the administration.
- **Custom settings** – the settings XbyK supports migrate with their values, but custom settings keys need a custom module, and website-specific ones follow the example in [Add channel-specific configuration to a module](https://docs.kentico.com/guides/development/customizations-and-integrations/add-channels-to-module.md). Values set in **web.config** or **appsettings.json** stay behind as well, so move each one to the matching [setting](https://docs.kentico.com/documentation/developers-and-admins/configuration/settings.md) or [configuration key](https://docs.kentico.com/documentation/developers-and-admins/configuration/reference-configuration-keys.md).

## Validate and evolve your solution

### Post-migration validation

Once you've completed the initial migration and code adjustments, take time to:

- **Test core functionality** – Verify that content displays correctly, forms submit properly, and user workflows function as expected.
- **Monitor performance** – Check page load times, database query efficiency, and overall system responsiveness.
- **Gather editor feedback** – Have content editors test the new admin interface and content management workflows to identify any usability issues.

### Iterative content model improvements

While we strongly recommend planning and remodeling your content during the upgrade (as covered in the [planning phase](https://docs.kentico.com/modules/upgrade-overview/upgrade-from-kx13-overview.md#plan-your-upgrade-approach)), we understand that budget constraints or tight timelines may have required a more conservative first pass.

If you performed a lift-and-shift migration or made only partial content model adjustments, you can progressively enhance your solution using the [expand-contract approach](https://community.kentico.com/blog/safely-evolving-a-content-model-with-expand-and-contract):

For example, to convert flat KX13 pages that contain both web-specific fields and content fields into the modern pattern of web pages referencing reusable content items, you can follow these general steps:

1. Create a new reusable content type that has all the same fields as your web page type.
2. Add a _Content items_ field to the _Web page content type_, referencing an item of the _reusable content type_.
3. Create a one-off script that utilizes Xperience APIs to do the following:
   1. Create a new item of the _reusable type_, copying all the values of their matching fields.
   2. Reference the new reusable item from the web page item's _Content items_ field.
4. Delete all the web page-specific fields from the _reusable content type_.
5. Delete all the content-specific fields from the _web page content type_.

Similarly, if you choose to convert common fields into [reusable field schemas](https://docs.kentico.com/documentation/developers-and-admins/development/content-types/reusable-field-schemas.md) after migration, you can add the schema to all the child content types, write a one-off script to copy content from the old fields to the schema fields, and then delete the old fields.

When time and budget allow, return to your content model and take advantage of the full potential of Xperience by Kentico's modern architecture. Be aware that depending on the project, restructuring content post-migration may require more effort and cost than doing it during the initial upgrade.

> **Tip:** Use [KentiCopilot](https://docs.kentico.com/guides/development/kenticopilot.md) tools and the [documentation MCP server](https://docs.kentico.com/documentation/developers-and-admins/installation/mcp-server.md) to accelerate post-migration content model evolution with AI-powered assistance.
