Customize customer eligibility

Advanced license required

Features described on this page require the Xperience by Kentico Advanced license tier.

You can extend the customer eligibility system by adding custom eligibility options (e.g., “Premium members”, “Loyalty tier members”) that appear alongside the built-in options in the promotion form. This example targets members with a specific member role – see the linked page for role setup.

Customization involves two components connected by a shared string identifier:

  1. Options provider (IPromotionCustomerEligibilityOptionsProvider) – adds custom options to the Target customers field in the admin UI with a string identifier (e.g., "premium-members").
  2. Eligibility validator (IPromotionCustomerEligibilityValidator) – evaluates the stored eligibility value at runtime and decides whether the buyer is eligible.

When a store manager selects your custom option and saves the promotion, the system stores the string identifier (e.g., "premium-members") on the PromotionInfo record. During price calculation, the framework reads this stored value and passes it to the validator chain. Your validator matches on the same string value and runs the custom eligibility logic.

Customer eligibility customization flow

Add custom eligibility options

Implement IPromotionCustomerEligibilityOptionsProvider to extend and filter the available customer eligibility options in the promotion admin form. The GetOptions method receives the current set of options and the promotion type, allowing you to add new options or filter existing ones per promotion type.

C#
Custom eligibility options provider

                     public class PremiumMemberEligibilityOptionsProvider
                         : IPromotionCustomerEligibilityOptionsProvider
                     {
                         // Defines a custom eligibility value
                         public static readonly PromotionCustomerEligibility PremiumMembersOnly =
                             new PromotionCustomerEligibility("premium-members");
                     
                         public IEnumerable<PromotionCustomerEligibilityOption> GetOptions(
                             IEnumerable<PromotionCustomerEligibilityOption> options,
                             PromotionType promotionType)
                         {
                             // Adds the custom option to the existing built-in options
                             return options.Append(
                                 new PromotionCustomerEligibilityOption(PremiumMembersOnly, "Premium members only"));
                         }
                     }

Register the provider in the DI container:

C#
Program.cs

                     // Registers the custom eligibility options provider in the DI container
                     [assembly: RegisterImplementation(
                         implementedType: typeof(IPromotionCustomerEligibilityOptionsProvider),
                         implementation: typeof(PremiumMemberEligibilityOptionsProvider))]

Validate custom eligibility

Implement IPromotionCustomerEligibilityValidator using the decorator pattern to handle your custom eligibility values. The default validator returns false for unknown values, so your implementation handles custom values and delegates to the inner (default) validator for built-in values.

In this example, the validator injects IHttpContextAccessor and uses ClaimsPrincipal.IsInRole() to check whether the current buyer has the required member role. This works because ASP.NET Identity adds role claims to the ClaimsPrincipal when you configure role management.

C#
Custom eligibility validator (decorator)

                     public class PremiumMemberEligibilityValidator
                         : IPromotionCustomerEligibilityValidator
                     {
                         private readonly IPromotionCustomerEligibilityValidator baseValidator;
                         private readonly IHttpContextAccessor httpContextAccessor;
                     
                         public PremiumMemberEligibilityValidator(
                             IPromotionCustomerEligibilityValidator baseValidator,
                             IHttpContextAccessor httpContextAccessor)
                         {
                             // The base validator instance decorated with premium eligibility checks
                             this.baseValidator = baseValidator;
                             this.httpContextAccessor = httpContextAccessor;
                         }
                     
                         public async Task<PromotionCustomerEligibilityValidationResult> Validate(
                             PromotionCustomerEligibility eligibility,
                             BuyerIdentifier buyerIdentifier,
                             CancellationToken cancellationToken)
                         {
                             // Handles the custom "premium-members" eligibility value
                             if (eligibility == PremiumMemberEligibilityOptionsProvider.PremiumMembersOnly)
                             {
                                 bool isPremium = CheckPremiumRole();
                     
                                 return new PromotionCustomerEligibilityValidationResult
                                 {
                                     IsEligible = isPremium
                                 };
                             }
                     
                             // Delegates to the default validator for built-in values
                             return await baseValidator.Validate(
                                 eligibility, buyerIdentifier, cancellationToken);
                         }
                     
                         private bool CheckPremiumRole()
                         {
                             System.Security.Claims.ClaimsPrincipal? user =
                                 httpContextAccessor.HttpContext?.User;
                     
                             if (user?.Identity?.IsAuthenticated != true)
                             {
                                 return false;
                             }
                     
                             // Checks if the current member has the "codesamples.premium" role
                             return user.IsInRole("codesamples.premium");
                         }
                     }

Register the validator as a decorator of the IPromotionCustomerEligibilityValidator type:

C#
Program.cs

                     // Registers the custom validator as a decorator in the DI container
                     [assembly: RegisterImplementation(
                         implementedType: typeof(IPromotionCustomerEligibilityValidator),
                         implementation: typeof(PremiumMemberEligibilityValidator))]

Result

The admin UI now shows the custom eligibility option for premium members.

Customer eligibility configuration

For a promotion to apply, it must pass this general eligibility check and the check in its corresponding IsApplicable implementation.