---
title: Personalize widget 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).

## Add content personalization

After our changes the widgets are working again. However, we have the opportunity to make them even better.

If we implement [content personalization](https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/content-personalization.md), we can allow editors to show different featured articles to visitors who are members of certain contact groups, based on what is more relevant to them.

> **Info:** To give you an idea of what we are implementing, here is what the process of personalizing widgets looks like for editors:
>
> 🎬 [Video](https://www.youtube.com/embed/d8qAOj4XdMY?si=5HgNgPVTqqFPKdLK\&amp;start=133)

Navigate to the **Contact groups** application in the Xperience admin, and define a new contact group with placeholder values for its name and description.

Now, [define a new personalization condition type](https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/content-personalization/develop-personalization-condition-types.md) in the _TrainingGuides.Web/Features/Personalization_ folder that allows editors to select a contact group and evaluates whether the current contact is in that group.

```csharp title="IsInContactGroupConditionType.cs"
using CMS.ContactManagement;
using CMS.DataEngine;
using TrainingGuides.Web.Features.Personalization;
using Kentico.PageBuilder.Web.Mvc.Personalization;
using Kentico.Xperience.Admin.Base.FormAnnotations;
using Kentico.Xperience.Admin.Base.Forms;

[assembly: RegisterPersonalizationConditionType(
    "TrainingGuides.Web.Features.Personalization",
    typeof(IsInContactGroupConditionType),
    "Is in contact group",
    Description = "Evaluates if the current contact is in one of the contact groups.", IconClass = "icon-app-contact-groups", Hint = "Display to visitors who match at least one of the selected contact groups:")]

namespace TrainingGuides.Web.Features.Personalization;

/// <summary>
/// Personalization condition type based on contact group.
/// </summary>
public class IsInContactGroupConditionType : ConditionType
{
    /// <summary>
    /// Selected contact group code names.
    /// </summary>
    [ObjectSelectorComponent(PredefinedObjectType.CONTACTGROUP,
    Label = "Contact groups",
    Order = 0,
    MaximumItems = 0)]
    public IEnumerable<ObjectRelatedItem> SelectedContactGroups { get; set; } = [];

    /// <summary>
    /// Evaluate condition type.
    /// </summary>
    /// <returns>Returns <c>true</c> if implemented condition is met.</returns>
    public override bool Evaluate()
    {
        var contact = ContactManagementContext.GetCurrentContact();

        if (contact == null)
        {
            return false;
        }

        if (SelectedContactGroups == null || !SelectedContactGroups.Any())
        {
            return contact.ContactGroups.Count == 0;
        }

        return contact.IsInAnyContactGroup(SelectedContactGroups.Select(c => c.ObjectCodeName).ToArray());
    }
}
```

Rebuild the solution and access the page builder tab. Now you can define a different featured article that displays for members of your contact group.

🎬 [Video](https://docs.kentico.com/docsassets/modules/personalize-widget-content/personalization.mp4)
