# Custom recommendation rendering

You can use existing controllers to render [recommendations](https://doc.ibexa.co/en/latest/recommendations/raptor_integration/recommendation_blocks/index.md) outside the Page Builder. The controllers responsible for rendering block recommendations on the front-end are independent and can be used to render recommendations for specific strategies.

Each controller can be used to retrieve and display recommendations within a Twig template as follows:

```
{{ render(controller('<Controller name>', {
    'limit': limit,
    'template': '@ibexadesign/<your_template_path>.html.twig',
    '<another_parameter>': parameter_value
})) }}
```

The controllers are placed in the `Ibexa\Bundle\ConnectorRaptor\Controller\Block` namespace.

Each controller always requires these two parameters:

- **limit** – the number of recommendations to render
- **template** – the path to the template

Any other required parameters are specific to each controller and are detailed in the **Parameters** column of the table below:

| Block name                                                                                                                                                                                                                                 | Controller                                                      | Parameters                                                                              | Recommendation item type |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------ |
| [Content that have been seen along with the item category](https://doc.ibexa.co/projects/userguide/en/5.0/personalization/raptor_integration/raptor_recommendation_blocks/#content-that-have-been-seen-along-with-the-item-category-block) | `ContentBasedOnProductCategoryBlockController` `::showAction()` | `categoryId` (integer), `limit` (integer), `template` (string)                          | Content                  |
| [Most popular content](https://doc.ibexa.co/projects/userguide/en/5.0/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-content-block)                                                                         | `PopularContentBlockController` `::showAction()`                | `limit` (integer), `template` (string)                                                  | Content                  |
| [Most popular products](https://doc.ibexa.co/projects/userguide/en/5.0/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-products-block)                                                                       | `PopularItemsBlockController` `::showAction()`                  | `showInStock` (boolean), `limit` (integer), `template` (string)                         | Product                  |
| [Most popular products in category](https://doc.ibexa.co/projects/userguide/en/5.0/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-products-in-category-block)                                               | `PopularItemsInCategoryBlockController` `::showAction()`        | `categoryId` (integer), `showInStock` (boolean), `limit` (integer), `template` (string) | Product                  |
| [Other customers have also seen](https://doc.ibexa.co/projects/userguide/en/5.0/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-seen-block)                                                     | `SimilarItemsBlockController` `::showAction()`                  | `productCode` (string), `showInStock` (boolean), `limit` (integer), `template` (string) | Product                  |
| [Other customers have also seen this content](https://doc.ibexa.co/projects/userguide/en/5.0/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-seen-this-content-block)                           | `SimilarContentBlockController` `::showAction()`                | `contentId` (integer), `limit` (integer), `template` (string)                           | Content                  |
| [Other Customers Have also Purchased block](https://doc.ibexa.co/projects/userguide/en/5.0/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-purchased-block)                                     | `OtherCustomersAlsoPurchasedBlockController` `::showAction()`   | `productCode` (string), `limit` (integer), `template` (string)                          | Product                  |
| [Personalized content recommendations](https://doc.ibexa.co/projects/userguide/en/5.0/personalization/raptor_integration/raptor_recommendation_blocks/#personalized-content-recommendations-block)                                         | `UserContentRecommendationsBlockController` `::showAction()`    | `limit` (integer), `template` (string)                                                  | Content                  |
| [The Personal Shopping Assistant](https://doc.ibexa.co/projects/userguide/en/5.0/personalization/raptor_integration/raptor_recommendation_blocks/#the-personal-shopping-assistant-block)                                                   | `UserItemRecommendationsBlockController` `::showAction()`       | `productCode` (string), `showInStock` (boolean), `limit` (integer), `template` (string) | Product                  |
| [User's item history](https://doc.ibexa.co/projects/userguide/en/5.0/personalization/raptor_integration/raptor_recommendation_blocks/#users-item-history-block)                                                                            | `UserItemHistoryBlockController` `::showAction()`               | `showInStock` (boolean), `limit` (integer), `template` (string)                         | Product                  |

Each template receives a `recommendations` Twig variable, which is a list with either [`Ibexa\Contracts\ProductCatalog\Values\ProductInterface`](https://doc.ibexa.co/en/latest/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-ProductInterface.html) instances for product recommendations or [`Ibexa\Contracts\Core\Repository\Values\Content\Content`](https://doc.ibexa.co/en/latest/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Content.html) instances for content recommendations.

Two generic templates are provided and can be used in `./templates/themes/<theme>` directory:

- `@ibexadesign/ibexa/recommendations/_content_list.html.twig` for content items:

```
{% if recommendations is not empty %}
    {% for content in recommendations %}
        {% set location = content.contentInfo.mainLocation %}
        {% if location %}
            <p><a href="{{ ibexa_path(location) }}">{{ ibexa_content_name(content) }}</a></p>
        {% else %}
            <p>{{ ibexa_content_name(content) }}</p>
        {% endif %}
    {% endfor %}
{% endif %}
```

- `@ibexadesign/ibexa/recommendations/_product_list.html.twig` for products:

```
{% if recommendations is not empty %}
    <ul>
        {% for product in recommendations %}
            <li><a href="{{ ibexa_path(product) }}">{{ product.name }}</a></li>
        {% endfor %}
    </ul>
{% endif %}
```

To fetch recommendations for the remaining modules, you need to [create a custom controller](https://doc.ibexa.co/en/latest/templating/queries_and_controllers/controllers/index.md) and use a method from [`Ibexa\Contracts\ConnectorRaptor\Recommendations\RecommendationsServiceInterface`](https://doc.ibexa.co/en/latest/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorRaptor-Recommendations-RecommendationsServiceInterface.html).

Use this method to display recommendations on any page, for example, on a specific product page, as shown below:
