Custom loyalty program rule not applied to tier upgrade after points accumulation

We deployed a custom rule in the loyalty program to handle tier upgrades based on a combination of points and purchase frequency. The rule should upgrade customers to Gold tier when they reach 5000 points AND make at least 10 purchases in 90 days. Standard tier rules work fine, but our custom rule doesn’t trigger. Points accumulate correctly, purchase count is tracked, but customers stay in Silver tier even after meeting both criteria.

public class CustomTierUpgradeRule extends AbstractLoyaltyRule {
    @Override
    public boolean evaluate(LoyaltyContext context) {
        int points = context.getCustomerPoints();
        int purchases = context.getPurchaseCount(90);
        return points >= 5000 && purchases >= 10;
    }
}

The rule is registered in the system and shows up in the loyalty rule configuration UI. We’ve verified the rule registration in the backend, but it’s simply not being evaluated during tier assessment. What could cause custom rules to be skipped during tier evaluation?

I’ll address all three focus areas that are likely causing your issue:

Rule Registration: Your custom rule needs proper registration beyond just showing up in the UI. Verify these registration aspects:

  1. Spring Bean Registration - your rule must be registered as a Spring bean:
@Component("customTierUpgradeRule")
@LoyaltyRule(type = "TIER_UPGRADE", priority = 100)
public class CustomTierUpgradeRule extends AbstractLoyaltyRule {
  1. Rule Configuration Entry - check loyalty-rules-config.xml contains:
<rule id="customTierUpgrade"
      class="CustomTierUpgradeRule"
      enabled="true"
      evaluationTrigger="POINTS_CHANGE,PURCHASE_COMPLETE"/>
  1. Tier Definition Link - the Gold tier definition must reference your custom rule in the tier progression rules.

Rule Engine Logs: Enable detailed rule engine logging to diagnose the issue. Add to your logging configuration:


log4j.logger.com.sap.cx.loyalty.rule.engine=DEBUG
log4j.logger.com.sap.cx.loyalty.evaluation=TRACE

Then check logs for these specific patterns:

  • “Evaluating rule: customTierUpgradeRule” - confirms rule is being invoked
  • “Rule evaluation result: false” - shows your rule is running but returning false
  • “Skipping rule: customTierUpgradeRule, reason: […]” - indicates why rule is being skipped

Most commonly, you’ll see “Context data not available” which leads to the next point.

Tier Evaluation: The tier evaluation process has specific data requirements. Your current implementation has a critical flaw - getPurchaseCount(90) is likely returning 0 or null because the purchase data isn’t loaded in the evaluation context by default.

Fix this by implementing a custom context enricher:

@Component
public class TierEvaluationContextEnricher implements LoyaltyContextEnricher {
    @Override
    public void enrich(LoyaltyContext context) {
        String customerId = context.getCustomerId();
        int purchaseCount = purchaseService.getRecentPurchaseCount(customerId, 90);
        context.setAttribute("purchase_count_90", purchaseCount);
    }
}

Then modify your rule:

@Override
public boolean evaluate(LoyaltyContext context) {
    int points = context.getCustomerPoints();
    Integer purchases = (Integer) context.getAttribute("purchase_count_90");
    if (purchases == null) {
        logger.warn("Purchase count not available in context for customer {}",
                    context.getCustomerId());
        return false;
    }
    return points >= 5000 && purchases >= 10;
}

Also ensure tier evaluation is triggered correctly. Register an event listener:

@EventListener
public void onPointsUpdate(PointsAccumulatedEvent event) {
    tierEvaluationService.evaluateTierForCustomer(event.getCustomerId());
}

Finally, verify your rule’s execution by adding explicit logging in the evaluate method and checking that both conditions are being evaluated with the correct values. The rule engine logs will show you the exact data state when evaluation occurs, which is crucial for debugging why the tier upgrade isn’t happening.


This draft is based on general SAP Customer Experience (SAP CX) knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.

First thing to check - is your custom rule properly registered with the loyalty engine’s rule chain? Custom rules need to be explicitly added to the tier evaluation sequence. Check the loyalty configuration to ensure your rule is included in the evaluation order.

I see the rule listed in the tier evaluation configuration, priority is set to 100. Should it be higher or lower? Also, is there a specific event that should trigger the evaluation, or does it happen automatically when points are updated?

“Confirmed this resolves the tier upgrade issue—adding @LoyaltyRule(type = "TIER_UPGRADE") alongside the Spring bean registration in loyalty-rules-config.xml finally triggered our custom rule correctly.”

Priority 100 should be fine. The issue is likely with event triggering. Tier evaluation doesn’t happen automatically on every points update - it’s triggered by specific events. You need to ensure your custom rule is listening to the right events. Check if PointsAccumulatedEvent and PurchaseCompletedEvent are configured to trigger tier re-evaluation. Also, verify that your rule’s evaluate method is actually being called by adding debug logging.

I suspect the problem is with how you’re retrieving the purchase count. The getPurchaseCount(90) method might not be working as expected in the evaluation context. Have you checked what value is actually being returned? In my experience, context data needs to be pre-loaded before the rule evaluation starts, otherwise you get stale or null values. You might need to implement a custom context provider that fetches this data upfront.

Check the rule engine logs specifically. There’s usually detailed logging about which rules are evaluated and why they pass or fail. Look for entries related to your CustomTierUpgradeRule class. The logs should show if the rule is being skipped entirely or if it’s evaluating to false.

Beyond the logging, make sure your rule class is properly annotated. Custom loyalty rules need specific annotations to be recognized by the rule engine. Also verify that the rule is compiled and deployed to the correct location in the classpath.