Kentico MVC Page Builder Do's and Don'ts
Tags: dotnet, kentico, cms
Published: 2020-05-02 15:07:35

---
title: Kentico MVC Page Builder Do's and Don'ts
published: true
date: 2020-04-30 23:56:57 UTC
tags: dotnet, kentico, cms
canonical_url: https://www.mcbeev.com/Blog/April-2020/Kentico-MVC-Page-Builder-Dos-and-Donts
---

**Kentico 12.0** (and really [**Kentico 12.0 Service Pack 1**](https://www.kentico.com/product/kentico12)) has brought many welcome enhancements to the Kentico platform when it comes to the ASP.Net MVC development style. But the one true killer feature when it comes to MVC is the **Kentico MVC Page Builder**. The drag and drop Page Builder allows content editors to create content and control page layout very easily. Combine that with the ability to create MVC page templates, easy to use A/B tests, and easy to use Personalization variations, and you don't have much excuse not to use it in Kentico 12.

Even though this feature is pretty new, time has moved on since last summer, when service pack 1 was officially released. That means developers have most likely had enough time to enjoy the pleasure of working with the system, as well as the pain of dealing with the system when it doesn't quite behave as designed. I know personally I have lost more than just an hour or two to a weird random JavaScript error that kept the Page Builder from loading, or some weird Content Security Policy error that prevented the Preview mode from even loading the Page Builder. The list goes on from there.

I have also seen the beauty of the system working in advanced ways, such as MVC Page Builder widgets being crafted out of ReactJS that makes front end developers happy or MVC widgets that pull from structured data in the Content Tree to allow for full content reusability and flexibility, and my end clients raving about how easy it is to build landing pages out of the Page Builder. This list goes on too.

Since the feature has been out for a bit now (and matured quite nicely), and I have seen the good and the bad, I felt it time to create a list of what I will call the **Do's and Don'ts of Kentico MVC Page Builder** to help other Kentico developers and Kentico partners out there get the most out of the system.

### Creating Kentico MVC Page Builder Widgets

This blog post is not going to go through the process of creating widgets for the Page Builder because there are quite a few good blog posts and documentation articles on how to do this already. If you are new to creating Kentico Widgets in MVC I would pause here and quick read through the following list.

*   [Kentico Docs - Using widgets in MVC](https://docs.kentico.com/k12sp/managing-website-content/using-widgets-in-mvc)
*   [Kentico Docs - Developing widgets in MVC](https://docs.kentico.com/k12sp/developing-websites/page-builder-development/developing-widgets-in-mvc)
*   [Kentico Docs - Developing a widget in MVC](https://docs.kentico.com/k12sp/developing-websites/page-builder-development/developing-widgets-in-mvc/example-developing-a-widget-in-mvc)
*   [Sean Wright - MVC Widget Tips](https://dev.to/seangwright/kentico-12-design-patterns-part-21-mvc-widget-tips-3img)
*   [Sean Wright - MVC Widget Experiments - Dynamic Views](https://dev.to/seangwright/kentico-ems-mvc-widget-experiments-part-1-dynamic-views-66l)
*   [Ondrej Polesny - Bing Maps MVC Widget Example](https://devnet.kentico.com/articles/build-a-portal-engine-widget-in-mvc)

After you have the basics in mind, or have even created a few "Hello World" MVC widgets in Kentico, you will probably have a better handle on the rest of this article. Assuming you are ready, let's jump right in.

### DON'T: Build Every Aspect of Your Entire Kentico Site with the Page Builder

Let's start with an easy one. The **Kentico MVC Page Builder** feature is not a feature that is meant to build out an entire site with. It doesn't magically turn Kentico into Wix or Squarespace or Dreamweaver or even Microsoft FrontPage for that matter. Yeah, FrontPage, I said it, who remembers that editor? I do, ...sadly. DO NOT DO THIS. I have had so many people over the course of the last year ask me why can't we just use the Page Builder on every page of the site. There are many reasons why not to do this, but they really boil down to two main reasons. The primary reason is performance of the MVC live site, and the second main reason is re-usability of weakly structured content that only lives on one widget on one page makes a site hard to edit and maintain over time.

In the real world, I have talked to more than one senior developer at more than one Kentico partner out there who have told me the horror stories of taking over a project where the entire thing was built with the Page Builder. The reason they were taking the project over was because of the fact the site was slow to load and slow to perform at scale. The reason for this is that if you create quick and dirty widgets, the configuration of the Editable Area (it's sections and widgets and properties) as well as the content of simple widgets are all stored in a serialized manner in one field on the Node (DocumentContent). It takes time for the system to then render that out to your view and if not done carefully, is a very expensive operation to do in terms of resources.

Also, think about it. If you create a Page in the Content Tree, add an Editable Area with a simple one section one text widget, and add some text onto that page, only that page knows about it. Other pages who you might want to have show the same exact text cannot easily do that unless you A) copy the MVC Page Template and use it as a second disconnected template / page or B) just write the same text twice (or more) on the pages you need it. Both A and B become nightmares to maintain over time. In my experience things that are hard to maintain don't get maintained and become stale or worse yet tend to get replaced with other shiny new systems. It is better to make a slightly more customized widget that ties its storage to a Page Type in the content tree and think of the widget as just the presentation layer (more on this later).

Don't get me wrong, my statements here are not intended to scare you away from using the MVC Page Builder, you should totally use it. Just please, use it wisely (follow the best practices) on campaign landing pages, to spice up side-bars, and around structured re-usable content.

### DO: Refer to the Kentico Dancing Goat MVC Starter Site on How to do the Basics

Yes, our good old friend the **Dancing Goat**. It's around for a reason. Kentico has spent quite an amount of time and resources over the last two or so years to update the sample starter site to showcase the MVC technology that the Kentico platform now has. A big thank you to Kentico for keeping this sample site up to date with the latest, because other .Net CMS's out there do not do a good of a job at this.   

The Dancing Goat MVC installation can easily be installed on a local machine (via the **Quick installation (MVC)** option in the fantastic **Kentico 12.0 Installer** tool). It gives you a very good basic blue print on how to setup a Kentico MVC site. Inside of the DancingGoatMVC.sln solution you can see 6 or so built in widgets that illustrate a few different types of widgets. The code there is a good way to start. Pay close attention to the Articles Widget (**ArticlesWidgetViewModel.cs** / **ArticlesWidgetController.cs** / **_ArticlesWidget.cshtml**) as it showcases how to create a widget that works with the current page, has an inline editor for properties, ties to the Content Tree for its content, has correct caching, and is setup with correct conventions.  

To be clear though. This is a sample site only, it is not intended to be the starting point for your project. Don't just try and use it as a short cut to start your next e-commerce project (yes, I have literally seen this...).   

![Kentico 12 Installer](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-12-installer.png)

### DO: Ensure you are Running Kentico 12.0 Service Pack 1

What I mean here is that you really don't want to run on any version of Kentico 12 that is lower than Service Pack 1 (which is really hotfix 29 and higher). The hotfixes for version 12 can be found on the Kentico DevNet Download page. If you look at the bug list on the download page there is also a little bit of a nasty bug with the Page Builder that was fixed in hotfix 12.0.43 that bit my team at BizStream. Combine that fact with a few other fixes that happened after 43, that honestly at time of writing of this blog post, **I would recommend being on at least 12.0.61** (but not the most recent hotfix possible, it's too bleeding edge).  

The reasoning for SP1 being so highly recommended is the fact that Service Pack 1 added in a range of MVC selectors for the Page Builder so that you can develop faster without having to worry about creating selectors for pages and media library items from scratch (more on this coming). SP1 also added in the concept of MVC Page Templates (for the Page Builder) and the completion of the MVC A/B Testing ability of Page Builder.   

### DON'T: Ignore Caching

When you are a developer it's tempting to just get your widget working and move on without thinking about what if someone adds 10 of these widgets to the page, or this widget is used on 30 pages of the site over and over. If you are making a data access layer call to populate the content this could create inefficiencies and be a drag on performance. [Caching on MVC in Kentico](https://docs.kentico.com/k12sp/configuring-kentico/configuring-caching/caching-on-mvc-sites) (and in .Net in general) is very important to get right. That's part of the reason that Kentico offers a [Glimpse](/Blog/January-2018/Why-Kentico-Glimpse-is-a-Must-Have-Tool-for-Kentico-MVC-Developers) integration and why I created the [Kentico Cache Doctor NuGet package](/Blog/September-2019/KenticoCacheDoctor-2-Now-With-Kentico-Glimpse) for Kentico developers.     

A lot of code samples out there will simply show some widget controller logic that grabs something via DoumentQuery like so:

<pre style="font-family: Consolas; font-size: 13px; background: rgb(30, 30, 30);"><span style="color: gainsboro;"><span style="color:#569cd6;">var</span> articles <span style="color:#b4b4b4;">=</span> <span style="color:#4ec9b0;">ArticleProvider</span><span style="color:#b4b4b4;">.</span>GetArticles()
    <span style="color:#b4b4b4;">.</span>OnSite(</span><font color="#dcdcdc">siteName)
    </font><span style="color: rgb(180, 180, 180);">.</span><font color="#dcdcdc">TopN(count)
    </font><span style="color: rgb(180, 180, 180);">.</span><font color="#dcdcdc">OrderByDescending(</font><span style="color: rgb(214, 157, 133);">"DocumentPublishFrom"</span><font color="#dcdcdc">)
    </font><span style="color: rgb(180, 180, 180);">.</span><font color="#dcdcdc">ToList();</font></pre>

This should be wrapped in at least one level of caching (the data access call being cached) or even better two layers of caching (data access call + output cache) like so:

<pre style="font-family:Consolas;font-size:13px;background: rgb(30, 30, 30);"> <span style="color: gainsboro;"><span style="color:#569cd6;">string</span> culture <span style="color:#b4b4b4;">=</span> <span style="color:#d69d85;">"en-us"</span>;
<span style="color:#569cd6;">string</span> siteName <span style="color:#b4b4b4;">=</span> <span style="color:#4ec9b0;">SiteContext</span><span style="color:#b4b4b4;">.</span>CurrentSiteName;

<span style="color: gainsboro;">Func</span><<span style="color:#b8d7a3;">IEnumerable</span><<span style="color:#4ec9b0;">Article</span>>> dataLoadMethod <span style="color:#b4b4b4;">=</span> () <span style="color:#b4b4b4;">=></span> <span style="color:#4ec9b0;">ArticleProvider</span><span style="color:#b4b4b4;">.</span>GetArticles()
        <span style="color:rgb(180, 180, 180);">.</span>OnSite(siteName)
        <span style="color:#b4b4b4;">.</span>Culture(culture)
        <span style="color:#b4b4b4;">.</span>TopN(count)
        <span style="color:#b4b4b4;">.</span>OrderByDescending(<span style="color:#d69d85;">"DocumentPublishFrom"</span>)
        <span style="color:#b4b4b4;">.</span>TypedResult; <span style="color:#57a64a;">// Ensures that the result of the query is saved, not the query itself</span>

<span style="color:#569cd6;">var</span> cacheSettings <span style="color:#b4b4b4;">=</span> <span style="color:#569cd6;">new</span> <span style="color:#4ec9b0;">CacheSettings</span>(<span style="color:#b5cea8;">10</span>, <span style="color:#d69d85;">"myapp|data|articles"</span>, siteName, culture, count)
{
    GetCacheDependency <span style="color:#b4b4b4;">=</span> () <span style="color:#b4b4b4;">=></span>
    {
        <span style="color:#57a64a;">// Creates caches dependencies. This example makes the cache clear data when any article is modified, deleted, or created in Kentico.</span>
        <span style="color:#569cd6;">string</span> dependencyCacheKey <span style="color:#b4b4b4;">=</span> <span style="color:#4ec9b0;">String</span><span style="color:#b4b4b4;">.</span>Format(<span style="color:#d69d85;">"nodes|{0}|{1}|all"</span>, siteName, <span style="color:#4ec9b0;">Article</span><span style="color:#b4b4b4;">.</span>CLASS_NAME<span style="color:#b4b4b4;">.</span>ToLowerInvariant());
        <span style="color:#569cd6;">return</span> <span style="color:#4ec9b0;">CacheHelper</span><span style="color:#b4b4b4;">.</span>GetCacheDependency(dependencyCacheKey);
    }
};

<span style="color:#569cd6;">return</span> <span style="color:#4ec9b0;">CacheHelper</span><span style="color:#b4b4b4;">.</span>Cache(dataLoadMethod, cacheSettings);</span></pre>

### DO: Setup your Admin Domain and Live Site Domain to Work with Preview Mode Correctly

This one was a killer for me when Kentico 12 first came out. I didn't get the fact that the Kentico Admin tool URL had to basically match the MVC Live Site presentation URL. You couldn't just mix and match them. If you do you could run into a all sorts of fun errors like _**Message received from forbidden origin: http://localhost:8080.**_ or other weird behavior with Content Security Policy issues with iframes. 

Copied from the docs, because most people miss it: Because the preview URLs on the MVC Live Site could potentially be vulnerable to clickjacking attacks, the _UsePreview_ feature automatically adds the [Content Security Policy](https://en.wikipedia.org/wiki/Content_Security_Policy) (CSP) HTTP response header with the _frame-ancestors_ policy, and sets the Kentico administration site's domain as a valid source. This allows you to display previewed pages in the Kentico administration, while preventing embedding on any other domains.

The correct way is to have the same domain (different port is ok on localhost):

![Kentico 12 Site Edit](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-12-sites.png)

The incorrect way is if you have different domains, or mis matched http vs https protocols in the uri.

![Kentico 12 Sites Edit wrong](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-12-sites-wrong.png)

### DON'T: Expect Every Piece of Text in a Standard Widget to be Searchable

Yeah, this one is kind of a big deal. It also goes to my first point in this post about don't build your whole site with the Kentico MVC Page Builder. Currently in all versions of Kentico 12, content inside of a widget is not translatable, not searchable, and doesn't really respect workflow 100%. Luckily Kentico 2020 or Kentico 13 fixes this. Read point 3 in my blog post about [20 Things Kentico Developers Should Know about Kentico 2020](/Blog/January-2020/20-Things-Developers-Should-Know-about-Kentico-2020) to find out how Kentico is fixing this in the next flagship version. For now, again standard widget content is not searchable. 

That is not totally the end of the story though. If you have any kind of **Custom Search Indexors** created for your site, say in the case that you are using [**Azure Search indexes**](https://docs.kentico.com/k12sp/configuring-kentico/setting-up-search-on-your-website/using-azure-search/customizing-azure-search) in Kentico, chances are you can correct this. While creating a Search Document you can look at the **DocumentContent** field parse the text out of the JSON object and add the content into a Search Field. It's a bit of work, but we have done it, and it works just fine. Although I will be happy when Kentico 13 squashes this known issue.

[![](https://www.mcbeev.com/MBV/media/uploads/2020/K2020-Phoenix-Logo-RGB-221.png)](https://www.kentico.com/product/roadmap)

### DO: Think about Structured Content Models (Storing Content in the Page Tree and Presenting via Widgets)

I am a big fan of this approach. It is pretty much the solution to the point of maintainability and ease of use for editors for a large site. 

_**Click on the small image below to see the full version of it.**_

[![Kentico 12 Widgets Content From Tree](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-12-Widgets-From-Tree_thumb.png)](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-12-Widgets-From-Tree.png)

You can see here that the widgets are set to pull the 3 nodes that make up Web Development, Our Team, and Our Culture. This is an example of still allowing editors to move around this section, maybe change the order of it, or even how many show up 1 vs. 2 vs. 3 of them. But the content is actually in Nodes in the content Tree. This allows for any other areas of the site to reuse this content.

![Kentico 12 Widgets From Tree Page Type](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-12-Widgets-From-Tree-Page-Type.png)

Changing the title of Web Development to Special Web Development is now easily possible in one location instead of possibly having to save and publish 3 pages that have 3 widgets that have this title. 

### DON'T: Forget about Content Personalization

Yes, that's right. It is amazing to me how easy it is to personalize widgets in Kentico MVC vs previous versions and even vs the portal engine. As long as you have Service Pack 1 as previously mentioned, this becomes an easy exercise. Please don't forget to show your users how to do this. Do remember it will take some work to [hook up activity tracking the right way in MVC](https://docs.kentico.com/k12sp/on-line-marketing-features/configuring-and-customizing-your-on-line-marketing-features/configuring-activities/enabling-activity-tracking-on-mvc-sites) though. The Kentico docs actually say it best, so I am not going to repeat every step here.

> **[https://docs.kentico.com/k12sp/on-line-marketing-features/managing-your-on-line-marketing-features/personalizing-widgets-in-mvc](https://docs.kentico.com/k12sp/on-line-marketing-features/managing-your-on-line-marketing-features/personalizing-widgets-in-mvc)**

My favorite aspect of this when I give other developers and end client demos. I always personalize the landing page hero image to be something funny, like me collapsed on the floor after doing a crossfit workout... At least it makes me smile every time. 

![Kentico Widget Personalization](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-Widget-Personalization.png)

### DON'T: Allow the Wild Wild West of Widget Placement in Sections

If you create a massive amount of widgets you don't want to open up Editable Areas to become a garbled mess of everything possible under the sun. Typically you are creating widgets that fill a need and are reusable, but reusable around a certain amount of scenarios, not everything. For instance a landing page may have the need for Hero widgets, Content Sections or Bands widgets, and maybe a Form widget. But if you have developed Poll widgets, YouTube Video Player widgets, Search Box widgets, Related Products widgets, etc. etc., you might not want every single one of those on the marketing landing page. 

This is where [limiting widgets allowed in an editable areas](https://docs.kentico.com/k12sp/developing-websites/page-builder-development/creating-pages-with-editable-areas-in-mvc#CreatingpageswitheditableareasinMVC-Limitingwidgetsallowedinaneditablearea) comes into play. It's at the code level, but configuring the allowedWidgets object and passing it to the EditableArea's allowedWidgets parameter allows you say which widgets go into which planned scenarios. Do not be lazy and ignore this setting! Trust me.

The following EditableArea tells the Kentico MVC Page Builder that only a TextWidget and an ImageWidget can appear on the home page view in **~/Views/Home/Index.cshtml** on the Dancing Goat MVC starter site.

<pre style="font-family:Consolas;font-size:13px;color:gainsboro;background:#1e1e1e;"> <span style="color: gainsboro;"><span style="color:black;background:#ffffb3;">@</span>Html<span style="color:#b4b4b4;">.</span>Kentico()<span style="color:#b4b4b4;">.</span>EditableArea(
    <span style="color:#d69d85;">"area2"</span>,
    defaultSectionIdentifier: <span style="color:#d69d85;">"DancingGoat.TwoColumnSection"</span>,
    allowedWidgets: <span style="color:#569cd6;">new</span>[] { <span style="color:#d69d85;">"DancingGoat.General.TextWidget"</span>, <span style="color:#d69d85;">"DancingGoat.HomePage.ImageWidget"</span> }
)</span></pre>

### DO: Use Dependency Injection for CurrentPageRetreiver

I have had two or three developers start their own widgets from scratch and get to the point where they need to reference the page that the widget is being hosted on in the Content Tree. Again if you grab a simple widget as a starting point, you may not realize that the system has a nice shortcut for you to do this. It is called the **CurrentPageRetreiver** and through DI Kentico's API will pretty much just give it to you as long as you know about it.

![Kentico 12 CurrentPageRetriever](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-Widget-GetPage.png)

In the screenshot above (yeah, I went screenshot because I wanted the intellisense popup on the **GetPage method**),  you can see that the Retriever is being injected into the constructor of the **ArticlesWidgetController.cs** from DancingGoat. That simple line of code will return the **TreeNode** of the page the widget is placed on. Pretty neat right? No reason to try and figure it out on your own. The system just does it for you. So don't go try inventing any wheels on your own. 

### DON'T: Ignore Widget Property Editors

Normal widget properties show up as a modal and input form when you click the gear icon in the upper right blue bar of a widget. That's pretty standard stuff. But with inline property editors you can make changes right in the widget itself without having to have the modal pop up and reload the page. There are actually two ways to create them, again the docs do the best job of illustrating it (I'm saving this topic for a future deep dive blog post, that's the reason I am not going into it here). People do tend to forget about them though.

> **[https://docs.kentico.com/k12sp/developing-websites/page-builder-development/developing-widgets-in-mvc/creating-inline-editors-for-widget-properties](https://docs.kentico.com/k12sp/developing-websites/page-builder-development/developing-widgets-in-mvc/creating-inline-editors-for-widget-properties)**

![Kentico Widget Inline Property Editor](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-Widget-Inline-Property-Editor.png)

The above Testimonial widget has a nice inline editor property to change the color from red to blue to grey right on click. It's a great example.

### DO: Use the MVC Page Templates Feature 

Another amazing feature of Service Pack 1 for the Kentico MVC Page Builder. I absolutely love this for being able to create new layout variants without the need to developers. This is the part you work on after you have your widgets setup. The ability to save the page as a template (content and all) is a killer feature. Do not confuse this feature with the old school Portal Engine Page Templates however. They are much different / better. The Dancing Goat site has the feature in it quite nicely.

The [Kentico Learning Kit for MVC](https://github.com/KenticoInternal/LearningKit-Mvc) (which is used in the Kentico 12 MVC training) has the best examples for how to create your own MVC Page Templates without trying to figure out the entire Dancing Goat sample setup. It shows that you need a Layout, a View, and a Template Registration (via **RegisterPageTemplate**) of the custom Page Template that you want to create. Now you only need to do this if you want editable properties that appear in the Page Template Property editor. The power here is that this is a full Layout, so it can be fully different branding than the MVC site but yet still control able by Marketers (and not break the rest of the site).  

![Kentico 12 MVC Learning Kit Page Template](https://www.mcbeev.com/getmedia/cb12d61c-b085-493c-ad97-7e7b221ab390/Kentico-12-MVC-Learning-Kit-Page-Template.png.aspx?width=784&height=603)

Notice the orange button that appears at the bottom of the Page tab when in edit mode. That opens up properties you can add to the whole template. Typical examples would be Show Title, Show logo, Theme name, Show Menu, etc. etc. Once you have your widgets placed, you can save the template from the top right area of the screen (the grey button with the 3 black dots). Then other people can start from your "saved templates".

![Kentico 12 MVC Learning Kit Page Template New Page](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-12-MVC-Learning-Kit-Page-Template-New.png)

### DO: Refer to and Use the Kentico EMS MVC Components Repo

Kentico has done a great job of releasing more selectors and components for the Kentico Page Builder and Form Builder at [https://github.com/Kentico/ems-mvc-components](https://github.com/Kentico/ems-mvc-components). Why are these important you might ask? Well the answer to that question is that instead of having a blank text to enter in a URL, Alias Path, or Image Path in your standard widget property, you can use the fancy **Page Selector** or **Media Library Selector** that Kentico has already created. This makes it much nicer for your editors.

Again instead of a text box that you can type into that looks like:

![Kentico Widget Simple Property](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-Widget-Simple-Property.png)

You can get a full Selector to choose a page from the Content Tree, and it will return the right path:

![Kentico Widget Page Selector Property](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-Widget-Page-Selector-Property.png)

The same is true for Media Library selectors.

### DON'T: Create widgets in MVC Areas. May lead to Unexpected Behavior.

The Kentico docs actually spell this out, but I thought it was worth repeating. Actually in my opinion [Areas in MVC](https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/areas?view=aspnetcore-3.1) are a little evil. That opinion could raise a bit of a religious debate, but I feel that if you have many areas your solution explorer becomes a maze, and it can get hard to find what you are looking for. Kentico states that the very specific _unexpected behavior_ could happen. Just don't do it folks. 

![Don't use Areas with MVC Widgets](https://www.mcbeev.com/MBV/media/uploads/2020/Kentico-Widgets-MVC-Areas.png)

### DO: Consider Using AI Driven Recommendations Through Recombee

The Kentico MVC Widget for [Recombee](https://www.recombee.com/) was built by the Kentico team and is available on [GitHub](https://github.com/Kentico/ems-mvc-module-recombee). It showcases a PoC integration of Kentico EMS and Recombee Artificial Intelligence Powered Recommender as a Service. Yes, that is a fancy title. But recommending related products on a product detail page or personalized product cards on a home page is becoming more of a norm for websites these days. Kentico EMS does a great job of tracking the context of who is looking at which pages, tracking behavior, and being able to use personalization variants that marketers setup ahead of time for known personas or segments. The key there though is "ahead of time". This widget uses the API from Recombee to personalize and recommend on the fly. Kentico has a full blog post on the [integration between Kentico and Recombee](https://www.kentico.com/blog/artificial-intelligence-(ai)-is-here-to-help-you-with-product-recommendations) if you are really interested. Just watch out for a few [known issues](https://github.com/Kentico/ems-mvc-module-recombee/issues).

[![Recombee AI Powered Recommendations](https://www.mcbeev.com/MBV/media/uploads/2020/Recombee.png)](https://www.recombee.com/)

Using this widget would be a quick way to add in some Machine Learning / Artificial Intelligence into your solution, especially since there is a free plan you could start out with. The main benefit to me is that you could save your marketing or product teams time of having to manually relate products or upsell / cross-sell promotions and have them automatically show up. Any time savings on content curation is most likely welcome in the current state of world events.  I haven't actually used Recombee yet personally. However, I have seen it in use in a few demos and think it has good potential to really work in an e-commerce scenario or product heavy site scenario.

### Conclusion

This article was intended to provide guidelines for best practices with Kentico 12 MVC Page Builder and developing Kentico MVC widgets. If you have a best practice in your development cycles and I missed it, please let me know via the comments in this blog post and I will add it. Until next time, stay safe out there!