Skip to content

Load additional data for the Storefront with App Scripts

Load additional data for the Storefront with App Scripts

If your app needs additional data in your customized Storefront templates, you can load that data with app scripts and make it available to your template.


Note that app scripts were introduced in Shopware and are not supported in previous versions.


The app script data loading expands on the general composite data loading concept of the storefront. For each page that is rendered, a hook is triggered, giving access to the current page object. The page object gives access to all the available data, lets you add data to it, and will be passed directly to the templates.

For a list of all available script hooks that can be used to load additional data, take a look at the script hook reference.


Note that all hooks that were triggered during a page rendering are also shown in the Symfony toolbar. This may come in handy if you are searching for the right hook for your script.

For example, if you want to enrich a storefront detail page with additional data, you just set it within a custom app script and attach it to the page object.

// Resources/scripts/product-page-loaded/my-example-script.twig
{% set page = %}
{# @var page \Shopware\Storefront\Page\Product\ProductPage #}

{# the page object if you access to all the data, e.g., the current product #}
{% do page.product ... %}

{% set myAdditionalData = {
    'example': 'just an example'
} %}

{# it also lets you add data to it, that you can later use in your Storefront templates #}
{% do page.addArrayExtension('swagMyAdditionalData', myAdditionalData) %}

In your Storefront templates, you can read the data again from the page object:

// Resources/views/storefront/page/product-detail/index.html.twig
{% sw_extends '@Storefront/storefront/page/product-detail/index.html.twig' %}

{% block page_product_detail %}
    <h1>{{ page.getExtension('swagMyAdditionalData').example }}</h1>
    {{ parent() }}
{% endblock %}

Loading data

To load data stored inside Shopware, you can use the read features of the Data Abstraction Layer. Therefore, in every hook that may be used to load additional data, the repository service is available.

The repository service provides methods to load exactly the data you need:

  • search() to load complete entities
  • ids() to load only the ids of entities, if you don't need all the additional information of the entities
  • aggregate() to aggregate data if you don't need any data of individual entities but are only interested in aggregated data

All those methods can be used in the same way. First, you pass the entity name the search should be performed on. Next, you pass the criteria that should be used.

{% set mediaEntities ='media', criteria) %}

Search criteria

The search criteria define how the search is performed and what data is included. The criteria object that is used inside the app scripts behaves and looks the same as the JSON criteria used for the API.

So please refer to that documentation to get an overview of what features can be used inside a criteria object.

Search Criteria

The criteria object can be assembled inside scripts as follows:

{% set criteria = {
    'ids': [ 'id1', 'id2' ],
    'associations': {
        'manufacturer': {},
        'cover': {},
    'filter': [
        { 'type': 'equals', 'field': 'active', 'value': true },
} %}

{% set matchedProducts ='product', criteria) %}

repository and store services

Besides the repository service, a separate store service is also available that provides the same basic functionality and the same interface.

The store service is available for all "public" entities (e.g. product and category) and will return a Storefront optimized representation of the entities. This means that, for example, SEO related data is resolved for products and categories, loaded over the store service, but not over the repository service. Additionally, product prices are only calculated using the store service.


The store service only loads "public" entities. This means that the entities only include ones that are active and visible for the current sales channel.

One major difference is that when using the repository service, your app needs read permissions for every entity it reads, whereas you don't need additional permissions for using the store service (as that service only searches for "public" data).

Refer to the App Base Guide for more information on how permissions work for apps.

The repository service exposes the same data as the CRUD-operations of the Admin API, whereas the store service gives access to the same data as the Store API.

For a full description of the repository and store service, take a look at the services reference.

Adding data to the page object

There are two ways to add data to the page object, either with the addExtension() or the addArrayExtension() methods. Both methods expect the name under which the extension should be added as the first parameter. Under that name, you can later access the extension in your Storefront template with the page.getExtension('extensionName') call.


Note that the extension names need to be unique. Therefore always use your vendor prefix as a prefix for the extension name.

The second argument for both methods is the data you want to add as an extension. The addExtension method needs to be a Struct, meaning you can only add PHP objects (e.g., the collection or entities returned by the repository service) directly as extensions. If you want to add scalar values or add more than one struct in your extension, you can wrap your data in a JSON-like twig object and use the addArrayExtension method.

In your scripts that would look something like this:

{% set products ='product', criteria) %}

{# via addExtension #}
{% do page.addExtension('swagCollection', products) %}
{% do page.addExtension('swagEntity', products.first) %}

{# via addArrayExtension #}
{% set arrayExtension = {
    'collection': products,
    'entity': products.first,
    'scalar': 'a scalar value',
} %}
{% do page.addArrayExtension('swagArrayExtension', arrayExtension) %}

You can access the extensions again in your Storefront templates like this:

{# via addExtension #}
{% for product in page.getExtension('swagCollection') %}
{% endfor %}

{% set product = page.getExtension('swagEntity') %}

{# via addArrayExtension #}
{% for product in page.getExtension('swagArrayExtension').collection %}
{% endfor %}

{% set product = page.getExtension('swagArrayExtension').entity %}

<h1>{{ page.getExtension('swagArrayExtension').scalar }}</h1>


Note that you can add extensions not only to the page object but to every struct. Therefore you can also add an extension, e.g., to every product inside the page.