---
schema_version: "1"
id: 6c9fff5847838f14ae151be56f9153be5e01c993df4c8ac9498e76981ed10b78
title: Custom Rules for Product Readiness
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/commerce-cloud/salesforce-commerce/guides/d2c-commerce/b2b-b2c-comm-custom-readiness-rules.md
canonical_url: https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/b2b-b2c-comm-custom-readiness-rules.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 65a602dd04f604ee979f5cc02c733ac7343921a308bdfea16193ffc0e53da88b
products:
  - B2B Commerce Developer Guide
  - Salesforce APIs
---
# Custom Rules for Product Readiness

Merchandisers can run Product Readiness on their catalogs to ensure that all products in a catalog are storefront ready. By default, Product Readiness uses a rule set that contains criteria based on SKUs, images, categories, and descriptions. If the default Product Readiness rule set doesn’t fit your organization’s needs, create a custom rule set to determine what criteria a product must fit to be considered ready.

Use an APEX class to create a rule set, and then activate the Readiness.ProductEvaluator. After the rule set is enabled, an admin must rebuild the index.

A custom rule can’t be added to the default rule set. If a custom rule set is enabled, it replaces the default rule set.

ProductScore records are associated with productIds as a measure of Product Readiness. If there are no score details returned for a given product, the score record is deleted. This rule allows for obsolete product scores to be deleted if the rules no longer return scores for these cases.

## Example

```nolang
public class ProductReadinessDescriptionEvaluator implements Readiness.ProductEvaluator {

    // return true for the rule to run
    public boolean isActive() {
        return true;
    }

    // return a list of Readiness.ProductScoreDetail which will become the product readiness score
    public List<Readiness.ProductScoreDetail> evaluateReadiness(Readiness.ProductEvaluationContext productContext) {
        // example implmentation which checks for a description and a price
        Set<ID> productIds = productContext.ProductIds;
        List<Readiness.ProductScoreDetail> scores = new List<Readiness.ProductScoreDetail>();

        List<Product2> products = [SELECT
              id, description
              FROM  Product2
              WHERE
              id IN : productIds];

        for (Product2 product : products) {
            scores.add(new Readiness.ProductScoreDetail(
                product.Id,
                'Description Length',
                String.isBlank(product.description) ? 0 : 100,
                'Product does not have a Description.'));

            List<PricebookEntry> entries = [SELECT id FROM PricebookEntry WHERE Product2Id = :product.Id];
            Integer pricebookScore = (entries.size() == 0) ? 0 : 100;
            scores.add(new Readiness.ProductScoreDetail(
                product.Id,
                'Price',
                pricebookScore,
                'Product must have a price.'));
        }

        return scores;
    }
}
```
