> ## Documentation Index
> Fetch the complete documentation index at: https://docs.global-e.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Restricted and forbidden products

Global-e supports country-level **restricted** and **forbidden** products. Depending on configuration, you can:

* Exclude restricted or forbidden products from search results and suggestions.
* Prevent shoppers from purchasing restricted or forbidden products for the selected shipping country.

Restriction data is imported from Global-e through the **GlobaleProducts** job (`/Browsing/RecentProductCountryS`) and stored on each product:

| Custom attribute | Meaning |
| - | - |
| `geIsForbidden` | Product is forbidden (`true` / `false`) |
| `geRestrictedCountries` | Comma-separated ISO country codes where the product is restricted (for example `AU,UA`) |

See [GlobaleProducts](/globale-products-sfcc) for job setup and [Metadata](/metadata-sfcc) for attribute definitions.

By default, restricted and forbidden products are **not** excluded from search results or suggestions.

To exclude them from search, configure a dedicated promotion in Business Manager (below). For best performance on suggestions, set the promotion ID and use **Product Search Model** promotion product type.

## Search exclusion implementation

Search filtering is implemented in `int_globale/cartridge/scripts/globale/helpers/searchHelpers.js`:

```javascript theme={null}
/**
 * Returns Searchable Products Promotion
 * @returns {dw.campaign.Promotion|null} - Searchable Products Promotion
 * @example
 * In the example below, the exclusion will be done by using the Promotion ID,
 * for example SearchableProducts_AU - will be applied only for Australia,
 * where all Restricted or Forbidden products will be added in 'Qualifying Products' => 'Excluding products',
 * so the promotion will have qualifying products but won't have any discounted products,
 * thus we can filter the search results but the promotional callout message won't be displayed on storefront.
 */
function getSearchableProductsPromotion() {
    var globaleHelpers = require('*/cartridge/scripts/helpers/globaleHelpers');
    var geAppContext = require('*/cartridge/scripts/factories/globale/geAppContextMgr').getAppContext();
    var searchableProductsPromotionId = globaleHelpers.getPreference(globaleHelpers.preferenceKeys.geSearchableProductsPromotionId);
    var searchableProductsPromotion = null;

    // Check if the current country is operated by Global-e
    if (geAppContext.country.isOperated() && searchableProductsPromotionId) {
        var PromotionMgr = require('dw/campaign/PromotionMgr');
        var collections = require('*/cartridge/scripts/util/globale/collections');
        searchableProductsPromotionId = searchableProductsPromotionId
            .replace(/\{country\}/ig, geAppContext.country.getCode())
            .replace(/\{currency\}/ig, geAppContext.currency.getCode());
        var applicablePromotions = PromotionMgr.getActiveCustomerPromotions().getProductPromotions();
        if (applicablePromotions && applicablePromotions.length > 0) {
            searchableProductsPromotion = collections.find(applicablePromotions, function (promotion) { return (promotion.ID === searchableProductsPromotionId); });
        }
    }

    return searchableProductsPromotion;
}

/**
 * Apply searchable products promotion.
 * This function applies a promotion to the given product search model.
 * If the promotion is available, it sets the promotion ID and product type.
 *
 * @param {dw.catalog.SearchModel} apiProductSearch - The search model to apply the promotion to.
 * @returns {dw.catalog.SearchModel} The updated search model with the promotion applied.
 */
function applySearchableProductsPromotion(apiProductSearch) {
    // Retrieve the searchable products promotion
    var searchableProductsPromotion = getSearchableProductsPromotion();

    // If a promotion is available, apply it to the search model
    if (searchableProductsPromotion) {
        var ProductSearchModel = require('dw/catalog/ProductSearchModel');

        // Set the promotion ID and product type
        apiProductSearch.setPromotionID(searchableProductsPromotion.ID);
        apiProductSearch.setPromotionProductType(ProductSearchModel.PROMOTION_PRODUCT_TYPE_QUALIFYING);
    }

    // Return search model
    return apiProductSearch;
}
```

### SFRA

SFRA search uses `int_globale_sfra/cartridge/scripts/helpers/searchHelpers.js`, which delegates to the core helper above.

**searchHelpers**

```javascript theme={null}
/**
 * Set search configuration values
 *
 * @param {dw.catalog.ProductSearchModel} apiProductSearch - API search instance
 * @param {Object} params - Provided HTTP query parameters
 * @return {dw.catalog.ProductSearchModel} - API search instance
 * @param {Object} httpParameterMap - Query params
 */
function setupSearch(apiProductSearch, params, httpParameterMap) {
    var searchHelpers = require('*/cartridge/scripts/globale/helpers/searchHelpers');
    var originalApiProductSearch = originalSetupSearch(apiProductSearch, params, httpParameterMap);

    return searchHelpers.applySearchableProductsPromotion(originalApiProductSearch); // apply searchable products promotion
}
```

In SFRA, product suggestions are filtered in `int_globale_sfra/cartridge/models/search/suggestions/product.js` when a searchable-products promotion is active:

```javascript theme={null}
/**
 * Get Image URL
 *
 * @param {dw.catalog.Product} product - Suggested product
 * @return {string} - Image URL
 */
function getImageUrl(product) {
    var imageProduct = product;
    if (product.master) {
        imageProduct = product.variationModel.defaultVariant;
    }
    return imageProduct.getImage(IMAGE_SIZE).URL.toString();
}

/**
 * Compile a list of relevant suggested products
 *
 * @param {dw.util.Iterator.<dw.suggest.SuggestedProduct>} suggestedProducts - Iterator to retrieve
 *                                                                             SuggestedProducts
 *  @param {number} maxItems - Maximum number of products to retrieve
 *  @return {Object[]} - Array of suggested products
 */
function getProductsWithRestrictions(suggestedProducts, maxItems) {
    var product = null;
    var products = [];

    while (suggestedProducts.hasNext() && products.length < maxItems) {
        product = suggestedProducts.next().productSearchHit.product;
        var geProduct = geProductMgr.get(product);
        if (!geProduct.isGeRestricted(geAppContext.country.getCode())) {
            products.push({
                name: product.name,
                imageUrl: getImageUrl(product),
                url: URLUtils.url(ACTION_ENDPOINT, 'pid', product.ID)
            });
        }
    }

    return products;
}

/**
 * @constructor
 * @classdesc ProductSuggestions class
 *
 * @param {dw.suggest.SuggestModel} suggestions - Suggest Model
 * @param {number} maxItems - Maximum number of items to retrieve
 */
function ProductSuggestions(suggestions, maxItems) {
    base.call(this, suggestions, maxItems);

    if (getSearchableProductsPromotion()) {
        var productSuggestions = suggestions.productSuggestions;
        this.products = getProductsWithRestrictions(productSuggestions.suggestedProducts, maxItems);
    }
}
```

### SiteGenesis

SiteGenesis search uses `int_globale_sitegenesis/cartridge/scripts/models/SearchModel.js`:

```javascript theme={null}
initializeProductSearchModel: {
    value: function () {
        var searchHelpers = require('*/cartridge/scripts/globale/helpers/searchHelpers');
        var apiProductSearch = this.super.initializeProductSearchModel.apply(this.super, Array.prototype.slice.call(arguments));
        // apply searchable products promotion
        apiProductSearch = searchHelpers.applySearchableProductsPromotion(apiProductSearch);

        return apiProductSearch;
    }
}
```

SiteGenesis suggestions are filtered in `int_globale_sitegenesis/cartridge/scripts/search/SearchSuggest.js`:

```javascript theme={null}
/**
 * Compile a list of relevant suggested products
 *
 * @param {dw.util.Iterator.<dw.suggest.SuggestedProduct>} suggestedProducts - Iterator to retrieve
 *  SuggestedProducts
 *  @param {number} maxItems - Maximum number of products to retrieve
 *  @return {Object[]} - Array of suggested products
 */
function getProductsWithRestrictions(suggestedProducts, maxItems) {
    var suggestedProduct = null;
    var restrictedSuggestedProducts = [];

    while (suggestedProducts.hasNext() && restrictedSuggestedProducts.length < maxItems) {
        suggestedProduct = suggestedProducts.next();
        var geProduct = geProductMgr.get(suggestedProduct.productSearchHit.product);
        if (!geProduct.isGeRestricted(geAppContext.country.getCode())) {
            restrictedSuggestedProducts.push(suggestedProduct);
        }
    }

    return restrictedSuggestedProducts;
}

module.exports = function (searchPhrase, maxSuggestions) {
    var baseSuggesteModel = base(searchPhrase, maxSuggestions);

    if (baseSuggesteModel && baseSuggesteModel.product && baseSuggesteModel.product.available && getSearchableProductsPromotion()) {
        // Initialize the suggest model
        var suggestModel = new SuggestModel();

        // Set the search phrase and maximum number of suggestions to retrieve
        suggestModel.setSearchPhrase(searchPhrase);
        suggestModel.setMaxSuggestions(maxSuggestions);

        // Retrieve the productSearchHita
        if (suggestModel) {
            baseSuggesteModel.product.products = getProductsWithRestrictions(suggestModel.getProductSuggestions().suggestedProducts, maxSuggestions);
        }
    }

    return baseSuggesteModel;
};
```

## Site preference

Configure **Searchable Products Promotion ID** (`geSearchableProductsPromotionId`) in **Merchant Tools → Site Preferences → Custom Site Preference Groups → Global-e Settings**. Use `{country}` and `{currency}` placeholders in the promotion ID — the cartridge resolves them from `geAppContext` at runtime (for example `SearchableProducts_{country}_{currency}`).

## Promotion and campaign setup

The example below targets Australia via customer groups. Restricted and forbidden products are excluded from search for that market only. You can also scope one promotion to multiple Global-e operated countries using campaign customer groups.

1. Create a promotion in Business Manager (**Merchant Tools → Online Marketing → Promotions**). Use a **Product** promotion type; ID should match `geSearchableProductsPromotionId` (with or without placeholders).

2. Set **Qualifying products**: add all products to **Included Products 1**. In **Excluded Products 1**, choose the **Global-e RestrictedCountries** product custom attribute (`geRestrictedCountries`) and the country codes to exclude (for example `AU` for Australia). To also exclude **forbidden** products, add a second excluded-products condition on the **Global-e Is Forbidden** attribute (`geIsForbidden` = `true`) — `geRestrictedCountries` alone does not cover forbidden products.

   In this example, products with `AU` in `geRestrictedCountries` (plus any product with `geIsForbidden = true`) are excluded from search results for Australia.

3. Set **Discounted products**: remove **Included Products 1** and add all products to **Excluded Products 1** so no products receive a discount — this keeps PLP, PDP, and basket prices correct while filtering search.

4. Rebuild search indexes in Business Manager (**Merchant Tools → Search → Search Indexes** → rebuild product index).

Salesforce B2C Commerce ignores campaign configuration for promotions used with `ProductSearchModel.setPromotionID()`. Assign the promotion to a Global-e campaign and customer group (for example an Australian group) so filtering applies only in Global-e operated countries.

When the promotion ID contains `{country}` and `{currency}` placeholders, the cartridge resolves them automatically — a dynamic customer group on the campaign is not required:

```javascript theme={null}
searchableProductsPromotionId = searchableProductsPromotionId
    .replace(/\{country\}/ig, geAppContext.country.getCode())
    .replace(/\{currency\}/ig, geAppContext.currency.getCode());
```

If the promotion ID has no placeholders, use a dynamic customer group on the campaign instead.

## Disable purchase on PDP

By default, restricted or forbidden products appear on the PDP with an availability message. You can hide them or redirect shoppers — for example to the home page — using the Global-e product wrapper's `isGeRestricted(countryCode)` / `getGeRestrictionMessage(countryCode)` methods (from `int_globale/cartridge/models/globale/dw/product/decorators/geRestrictions.js`) in your Product controller.

### SFRA

Add customization in the SFRA Product controller route:

**Redirect to Home Page for Restricted and/or Forbidden products**

```javascript theme={null}
/**
 * Global-e Product Show
 *
 * Merchant Customization: Add custom code to this route if you need custom behavior for
 * Restricted or Forbidden product on PDP page. For example, you could redirect international
 * customers to home page if they click on a restricted or forbidden product as shown in
 * the example below.
 * @example
 * var URLUtils = require('dw/web/URLUtils');
 * var ProductMgr = require('dw/catalog/ProductMgr');
 * var geProductMgr = require('{@literal *}/cartridge/scripts/factories/globale/dw/product');
 * var geAppContext = require('{@literal *}/cartridge/scripts/factories/globale/geAppContextMgr').getAppContext();
 * var apiProduct = ProductMgr.getProduct(req.querystring.pid);
 * var geProduct = geProductMgr.get(apiProduct);
 * // Restricted and Forbidden Products (the message function auto-selects the forbidden vs restricted text)
 * if (geAppContext.country.isOperated() && geProduct.isGeRestricted(geAppContext.country.getCode())) {
 *      res.redirect(URLUtils.url('Home-Show')); // redirect to home page
 *      next();
 * }
 */
```

### SiteGenesis

Add the same pattern in the SiteGenesis Product controller or pipeline:

**Redirect to Home Page for Restricted and/or Forbidden products**

```javascript theme={null}
/**
 * Global-e Product Show
 *
 * Merchant Customization: Add custom code to this route if you need custom behavior for
 * Restricted or Forbidden product on PDP page. For example, you could redirect international
 * customers to home page if they click on a restricted or forbidden product as shown in
 * the example below.
 * @example
 * var URLUtils = require('dw/web/URLUtils');
 * var ProductMgr = require('dw/catalog/ProductMgr');
 * var geProductMgr = require('{@literal *}/cartridge/scripts/factories/globale/dw/product');
 * var geAppContext = require('{@literal *}/cartridge/scripts/factories/globale/geAppContextMgr').getAppContext();
 * var apiProduct = ProductMgr.getProduct(params.pid.stringValue);
 * var geProduct = geProductMgr.get(apiProduct);
 * // Restricted and Forbidden Products (the message function auto-selects the forbidden vs restricted text)
 * if (geAppContext.country.isOperated() && geProduct.isGeRestricted(geAppContext.country.getCode())) {
 *      response.redirect(URLUtils.https('Home-Show')); // redirect to home page
 * }
 */
```

## Einstein product recommendations

If a shopper opens a recommended restricted or forbidden product, they see the restriction message on the PDP (or your custom redirect behavior) and cannot add the product to the basket.

### SFRA and SiteGenesis

To hide restricted or forbidden products from Einstein recommendations, update the templates that render recommendation slots per [SFCC product recommendations guidance](https://documentation.b2c.commercecloud.salesforce.com/DOC1/topic/com.demandware.dochelp/content/b2c_commerce/topics/einstein/b2c_dev_considerations_for_prod_recs.html?cp=0_9_3_9).

Example ISML fragment:

```xml theme={null}
<iscontent type="text/html" charset="UTF-8" compact="true"/>
<iscomment> should not be cached, the tiles are cached individually.</iscomment>
<isset name="geProductMgr" value="${require('*/cartridge/scripts/factories/globale/dw/product')}" scope="page" />
<isset name="geAppContext" value="${require('*/cartridge/scripts/factories/globale/geAppContextMgr').getAppContext()}" scope="page"/>
<isif condition="${slotcontent}">
    <div class="product-listing product-listing-1x4">
        <h2>${slotcontent.calloutMsg}</h2>
        <ul class="search-result-items tiles-container">
            <isloop items="${slotcontent.content}" var="product" begin="0" end="3">
                <isobject object="${product}" view="recommendation">
                    <isif condition="${geAppContext.country.isOperated() && geProductMgr.get(product).isGeRestricted(geAppContext.country.getCode())}"><iscontinue/></isif>
                    <li class="grid-tile">
                        <isinclude url="${URLUtils.url('Product-HitTile',
                            'pid', product.ID,
                            'showswatches', 'true',
                            'showpricing', 'true',
                            'showpromotion', 'true',
                            'showrating', 'true')}"/>
                    </li>
                </isobject>
            </isloop>
        </ul>
    </div>
</isif>
```

## Global-e checkout with restricted products

If a shopper reaches Global-e checkout with restricted or forbidden products in the basket, Global-e displays a restriction message and blocks checkout completion.
