---
title: Fetching Data from the App Server | Shopware Community Hub
description: >-
  Learn how to securely fetch data from your App Server and display it in the
  Shopware storefront.
canonical_url: 'https://hub.shopware.com/learn/unit/fetching-data-from-the-app-server'
---

# Fetching Data from the App Server

<LearningObjectives>

- **Fetch data** from the App Server **synchronously** in the storefront.
- Use **JWT-secured** requests with the **AppClient** service.
- **Compile** and **bundle** storefront JavaScript for Apps.
- **Display response data** from the App Server in the storefront.

</LearningObjectives>

# Fetching Data from the App Server

The Shopware storefront can communicate with the App Server in two main ways:

- **Asynchronous**: Via [Webhooks](https://developer.shopware.com/docs/guides/plugins/apps/webhook.html#webhook) Shopware notifies the App Server when events occur. The App Server then decides what to do.
- **Synchronous**: Via [Client-Side JavaScript Requests](https://developer.shopware.com/docs/guides/plugins/apps/clientside-to-app-backend.html) the storefront contacts the App Server API directly and waits for a response.

While Webhooks are robust and efficient, they are asynchronous. Sometimes we need data **on-demand** (synchronously). For example:

- Displaying data from the App Server directly in the storefront.
- Checking authentication with an external service before showing certain UI elements.

In this learning unit, we will **implement the synchronous approach**. The goal is to show customers customized stock data in the storefront, fetched directly from the App Server.

## Code-Along

To follow along, use this command within the ShopwareStoreTracker directory:

```bash
git checkout tags/fetching_data--start
```

## JWT Security

The communication between Shopware and the App Server is secured using [JWT (JSON Web Token)](https://www.jwt.io/introduction). For this to work, both Shopware and the external server must support JWT verification. A JWT ensures that the requests are authentic and cannot be faked by third parties.

A JWT consists of three parts:

- **Header**: Defines which the algorithm is used (e.g., HMAC-SHA256).
- **Payload**: Contains the actual data (e.g., shop ID, timestamp).
- **Signature**: It's the hash generated from the header + payload + a secret key.

The secret key is only known to Shopware and the App Server. The key point of JWT is that the payload is readable, but the signature makes it tamper-proof. If someone tries to change the payload (manipulation), the signature check will fail and the App Server will reject the request.

Without using the [AppClient class](https://github.com/shopware/shopware/blob/trunk/src/Storefront/Resources/app/storefront/src/service/app-client.service.ts), you would have to **fetch** a JWT (e.g., via `/app-system/{app-name}/generate-token`) and **attach** it to your requests manually. The `AppClient` automates this process.

For more information on JWT security, check out the Shopware Developer Documentation provides a good overview of the [JWT authentication process](https://developer.shopware.com/docs/guides/plugins/apps/clientside-to-app-backend.html#generate-json-web-token).

## Create a Storefront Plugin

To integrate our JavaScript code in the Shopware way, we will build a [storefront plugin](https://developer.shopware.com/docs/guides/plugins/plugins/storefront/add-custom-javascript.html). This gives us an object-oriented structure, making the code more modular and easier to maintain.

<Callout title="Storefront Plugin vs. Plugin" type="info">

Don't confuse a **storefront plugin** with a **plugin**:

- A **[storefront plugin](https://developer.shopware.com/docs/guides/plugins/plugins/storefront/add-custom-javascript.html)** is for client-side JavaScript logic.
- A **[plugin](https://developer.shopware.com/docs/guides/plugins/plugins/)** is a Shopware extension that changes global behavior in the backend and frontend.

</Callout>

<Callout title="Important Note for App Development" type="info">

For our needs, the setup is almost identical to [creating a Shopware storefront plugin](https://developer.shopware.com/docs/guides/plugins/plugins/storefront/add-custom-javascript.html). The only difference:

- In Apps, the path **`./src/Resources/app/storefront/src`** (not `./Resources/app/storefront/src` as in the plugin guide).
- You also need to reference the compiled JavaScript in your **`theme.json`** file.

</Callout>

### Storefront Plugin Basics

To get the storefront plugin working, we need two files, the `main.js` (**`[app_root]/Resources/app/storefront/src/main.js`**) and the actual storefront plugin file (**`[app_root]/Resources/app/storefront/src/stock-check/stock-check.plugin.js`**).

The `main.js` file is the entry point for our plugin. It registers the plugin with the storefront Plugin Manager.

```js
import StockCheck from './stock-check/stock-check.plugin.js';

const PluginManager = window.PluginManager;
PluginManager.register('StockCheck', StockCheck, '.product-detail-ordernumber');
```

<Callout title="Explaining the Parameters" type="info">

The meaning of the parameters of the `PluginManager.register()` are as follows:

1. The **first parameter** is the **name of the plugin**. This name is used to reference the plugin in the storefront.
2. The **second parameter** is the **JavaScript plugin class** that implements the plugin logic. You see in the example above that we imported the actual storefront plugin in the first line.
3. The **third parameter** is optional: A **CSS selector** that defines where the plugin should run.
   - If omitted, the plugin runs globally on every page.
   - If provided, the plugin only runs when the selector matches an element on the current page (e.g., a class name, an ID, or attribute).
   - This makes the selector parameter an **entry point** for the plugin.

</Callout>

The basic build of the storefront plugin file (**`[app_root]/Resources/app/storefront/src/stock-check/stock-check.plugin.js`**) is as the following:

```js
const { PluginBaseClass } = window;

export default class StockCheck extends PluginBaseClass {
    init() {
        console.log("Welcome to my App!");
    }
}
```

#### Compiling the Code

After writing the JavaScript files, it is necessary to compile them so that Shopware can load them in the storefront. Run the following commands in your Shopware root directory:

```bash
bin/build-storefront.sh
bin/console cache:clear
```

Check back to your `Resources/` folder. You should see that a new file has been automatically generated at `Resources/app/storefront/dist/storefront/js/shopware-store-tracker/shopware-store-tracker.js`:

![Generated JavaScript file](assets/generated-minified-storefront-js-file.png)

This file is the minified version of the JavaScript code you wrote. **It is the file that loads in the storefront**.

### Bundling Client-side JavaScript

In the App System, script files are loaded by explicitly referencing a JavaScript or TypeScript file within the `theme.json` configuration. These references are held under the `**script**` key, as shown:

```json
  "script": [
    "@Storefront",
    "app/storefront/dist/storefront/js/shopware-store-tracker/shopware-store-tracker.js"
  ],
```

<Callout title="Absence of Referenced File Can Cause Errors with Theme Compilation" type="warning">

As you can see, in the theme config, we are writing an explicit path to the generated file. It is always important to check that this file exists before we run `theme:compile`, otherwise we will encounter errors.

</Callout>

After updating the `theme.json`, run the following commands in your Shopware root directory:

```bash
bin/build-storefront.sh
bin/console cache:clear
```

Now reload your browser. If everything went well, you should see the message "Welcome to my App!" in the browser developer console:

![Welcome to my App message](assets/app-welcome-message.png)

## Preparing the Request (AppClient Setup)

In this step, we will connect the storefront to an existing endpoint on the App Server. Our goal is to **send a request and display the response data** in the storefront.

<Callout title="App Server Development" type="info">

In the previous course, you already created a simple controller endpoint on the App Server. Here, we will not go into specifics for creating a new Symfony Controller, but instead use an [existing one](https://github.com/ShopwareAcademy/ShopwareStoreTrackerBackend/blob/main/src/Controller/UploadController.php). This way, we can focus on the storefront side of things.

</Callout>

### Using the `AppClient` to Construct a Request

The stock data we want to display in the storefront is **provided by the App Server** lives at `localhost:8001/stores/list`. This endpoint can be accessed with a `GET` request. To get the data securely, we use the **AppClient** class. It takes care of the JWT authentication and prevents us from having to attach tokens manually.

#### Step 1: Import AppClient

Open your `stock-check.js` and import the class:

```js
import AppClient from 'src/service/app-client.service.ts';
```

#### Step 2: Log In With a Customer Account

Before the AppClient can request a JWT, you need to be logged in with a customer account in your local instance. If no customer is logged in, the App Server will reject the request because no JWT can be generated. The error looks like this:

![JWT Error](assets/jwt-error.png)

<Callout title="Why Is a Customer Login Required?" type="info">

In this example, the AppClient uses the **Store API context** of the currently logged-in user. The Store API issues JWTs based on this context, which is normally tied to a **customer session**.

That means: If no customer is logged in, there is no active Store API context and therefore no JWT can be generated.

This behavior is specific to the storefront context and used in this learning example.

Note: In production Apps, developers can also generate JWTs on the server side or implement their own custom authentication mechanism.

</Callout>

## Fetching Stock Data From the App Server

If we use the AppClient to request data from the `stock-status` endpoint on the App Server, our code reads something like this:

```js
// <plugin root>/src/Resources/app/storefront/src/example-plugin/example-plugin.plugin.js
const { PluginBaseClass } = window;
import AppClient from 'src/service/app-client.service.ts';

export default class StockCheck extends PluginBaseClass {
  client;
  productNumber;

  async init() {
    this.productNumber = this.el.innerText;
    if (!this.productNumber) {
      return;
    }

    this.client = new AppClient("ShopwareStoreTracker");
    await this.getStockData();
  }

  async getStockData() {
    const requestUrl = `http://localhost:8001/stock-status/${this.productNumber}`;
    const response = await this.client.get(requestUrl);
    console.log(await response.json());
  }
}
```

**Explaining the code:**

- The `init` method:
	- Creates an AppClient instance.
	- Extracts the product number from the URL.
	- Calls the `getStockData` method.
  
- The `getStockData` method:
	- Sends a secure GET request to the App Server.
	- Outputs the response in the browser console.

### Checking the App Server Response

To test the Plugin:

1. Open your local Shopware instance in the browser.
2. Navigate to a Product Detail Page.
3. Open the browser console and check the output (right-click -> inspect -> Console tab).

You should now see the response from the App Server printed in the console.

![App Server response in browser console](assets/browser-console-response-dump.png)

## Code-Along (end)

To see what the final result of this learning unit should look like, run the following command:

```bash
git checkout tags/fetching_data--end
```

<Callout title="Removing Working Changes" type="warning">

If you have local changes, you will need to run `git reset --hard HEAD` in the App directory. Be mindful that this command will destroy any local changes!

</Callout>

## Summary

In this learning unit, you learned how to fetch data securely from an App Server and display it in the storefront. Concretely, you now know how to:

- Create a storefront plugin with `main.js` and a storefront plugin file.
- Compile and bundle JavaScript via `bin/build-storefront.sh` and reference it in the `theme.json` file.
- Understand the role of JWT and why it is required for secure requests.
- Use the `AppClient` service to automatically attach JWT tokens.
- Fetch data from an App Server and display the response in the browser console.

In the next learning unit, you will build on this setup and extend the storefront plugin to display the stock data in the storefront.
