Customize customer eligibility
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., “VIP customers”, “Loyalty tier members”) that appear alongside the built-in options in the promotion form.
Customization involves two components connected by a shared string identifier:
- Options provider (
IPromotionCustomerEligibilityOptionsProvider) – adds custom options to the Target customers field in the admin UI with a string identifier (e.g.,"vip"). - 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., "vip") 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.
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.
public class VipCustomerEligibilityOptionsProvider
: IPromotionCustomerEligibilityOptionsProvider
{
// Defines a custom eligibility value
public static readonly PromotionCustomerEligibility VipOnly =
new PromotionCustomerEligibility("vip");
public IEnumerable<PromotionCustomerEligibilityOption> GetOptions(
IEnumerable<PromotionCustomerEligibilityOption> options,
PromotionType promotionType)
{
// Adds the custom option to the existing built-in options
return options.Append(
new PromotionCustomerEligibilityOption(VipOnly, "VIP customers only"));
}
}
Register the provider in the DI container:
// Registers the custom eligibility options provider in the DI container
[assembly: RegisterImplementation(
implementedType: typeof(IPromotionCustomerEligibilityOptionsProvider),
implementation: typeof(VipCustomerEligibilityOptionsProvider))]
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.
public class VipCustomerEligibilityValidator
: IPromotionCustomerEligibilityValidator
{
private readonly IPromotionCustomerEligibilityValidator baseValidator;
public VipCustomerEligibilityValidator(
IPromotionCustomerEligibilityValidator baseValidator)
{
// The base validator instance decorated with VIP eligibility checks
this.baseValidator = baseValidator;
}
public async Task<PromotionCustomerEligibilityValidationResult> Validate(
PromotionCustomerEligibility eligibility,
BuyerIdentifier buyerIdentifier,
CancellationToken cancellationToken)
{
// Handles the custom "vip" eligibility value
if (eligibility == VipCustomerEligibilityOptionsProvider.VipOnly)
{
bool isVip = await CheckVipStatus(buyerIdentifier, cancellationToken);
return new PromotionCustomerEligibilityValidationResult
{
IsEligible = isVip
};
}
// Delegates to the default validator for built-in values
return await baseValidator.Validate(
eligibility, buyerIdentifier, cancellationToken);
}
private async Task<bool> CheckVipStatus(
BuyerIdentifier buyerIdentifier,
CancellationToken cancellationToken)
{
if (buyerIdentifier == null)
{
return false;
}
// Implements custom VIP check logic
// (e.g., checking a custom field on the customer record)
return await Task.FromResult(true);
}
}
Register the validator as a decorator of the IPromotionCustomerEligibilityValidator type:
// Registers the custom validator as a decorator in the DI container
[assembly: RegisterImplementation(
implementedType: typeof(IPromotionCustomerEligibilityValidator),
implementation: typeof(VipCustomerEligibilityValidator))]
Result
The admin UI now shows the VIP eligibility option.

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