Storefront Setup
Storefront API Setup
With our data set up, its now time to work with our frontend, which utilizes the Storefront API. Let's start by checking if our data is accessible.
If you've just completed the Use the Admin API tutorial path, it may take a few minutes for the API to start returning products. You can still proceed with this chapter.
Storefront API
To access the Storefront API and retrieve product data, use the following URL structure: https://{{tenant-space}}.storefront.api.scayle.cloud/v1/products?shopId={SHOP_ID}
.
- Tenant Space: This variable is essential for accessing your specific storefront data. You can find it within your SCAYLE Panel URL. For example, if your SCAYLE Panel URL is
https://acme-live.panel.scayle.cloud/
, thenacme-live
is your tenant space. - Shop ID: The Shop ID is crucial and should correspond to the ShopCountry ID. To find yours, navigate to
Shops > My Shop
in the SCAYLE Panel. Make you've selected the correct country.
You'll be brought to a new screen, where you'll be able to find your Shop Country ID.
Test URL
To test accessing your products via the Storefront API, use a URL structured like this: https://acme-live.storefront.api.scayle.cloud/v1/products?shopId=10001
. This URL incorporates your tenant space (acme-live
) and the Shop ID (10001
) to fetch product data for your specific shop.
Setup the Storefront API SDK & Query Products
Base Setup
To fetch products using the Storefront API, you'll need to create a new file in your project. Name this file src/008_fetchProducts.js
.
const backbone = require("@aboutyou/backbone");
require("dotenv").config();
async function fetchProducts() {
const client = new backbone.BapiClient({
host: `https://${process.env.TENANT_SPACE}.storefront.api.scayle.cloud/v1/`,
shopId: process.env.SHOP_ID,
auth: {
type: "token",
token: process.env.STOREFRONT_API_TOKEN,
},
});
}
fetchProducts();
For this task, we'll use Storefront API SDK, to interact with the Storefront API. To begin, you'll need to install this new dependency. Open your terminal, navigate to your project's root directory, and execute the following command to install the Storefront API SDK:
pnpm install @aboutyou/backbone
In addition to the SDK, your code will require two important constants: SHOP_ID
and STOREFRONT_API_TOKEN
.
- ShopID: To set up the
SHOP_ID
, add it to your.env
file within your project. You can find instructions on obtaining the correct Shop ID here. This ID is crucial for identifying your specific shop instance when making API requests. - STOREFRONT_API_TOKEN: This token is necessary for authenticating your requests to the Storefront API. You should secure this token and store it in your
.env
file to easily reference it in your API calls.
TENANT_SPACE=XXXXX-YYYYY
ADMIN_API_TOKEN=XXXXX
SHOP_ID={YOUR_SHOP_ID}
Storefront API Key
To obtain your Storefront API Key, follow these steps in the SCAYLE Panel:
- Go to Shops section.
- Select My Shop.
- Navigate to the Storefront tab.
- Click on API Keys.
- Create a new token.
This token is required for authenticating requests to the Storefront API, and ensures secure access to your shop's data. Once generated, securely store this key in your .env
file as STOREFRONT_API_TOKEN
to easily reference it in your API calls.
After generating your Storefront API token, copy it and add it to your project's .env
file. Format the entry as follows:
TENANT_SPACE=XXXXX-YYYYY
ADMIN_API_TOKEN=XXXXX
SHOP_ID={YOUR_SHOP_ID}
STOREFRONT_API_TOKEN={YOUR_STOREFRONT_API_TOKEN}
Query Products
try {
const products = await client.products.query();
console.log("Fetched products", products);
} catch (error) {
console.error("Unable to fetch products", error);
}
Response
When you query the Storefront API, the response will include two critical components: pagination
and entities
.
- Pagination: Provides information about the current page, total pages available, and the number of items per page. It's crucial for handling large sets of data by navigating through pages in your application.
- Entities: Contains the actual data fetched from the API, such as product details. Initially, you might notice that the entities returned do not include all the data you previously set up. This is expected behavior, as default queries may only fetch a subset of available data for efficiency.
In the following sections, we will explore how to retrieve more detailed information from your entities, ensuring that you can access all the relevant data you have configured for your products. This will involve adjusting your API requests to include additional fields or parameters as needed.
{
"pagination": {
"current": 4,
"total": 4,
"perPage": 100,
"page": 1,
"first": 1,
"prev": 1,
"next": 1,
"last": 1
},
"entities": [
{
"id": 16,
"isActive": true,
"isSoldOut": false,
"isNew": false,
"createdAt": "2024-02-15T16:59:30+00:00",
"updatedAt": "2024-02-15T16:59:31+00:00",
"indexedAt": "2024-02-16T15:18:54+00:00",
"firstLiveAt": "2024-02-15T16:59:30+00:00",
"masterKey": "THS1235-master",
"referenceKey": "THS1235",
"images": [{ "hash": "images/80e9e4f5bec4b42bd431b3ee4a27dd9c.jpg" }],
"customData": {}
},
{
"id": 15,
"isActive": true,
"isSoldOut": false,
"isNew": false,
"createdAt": "2024-02-15T16:59:30+00:00",
"updatedAt": "2024-02-15T16:59:31+00:00",
"indexedAt": "2024-02-16T15:18:54+00:00",
"firstLiveAt": "2024-02-15T16:59:30+00:00",
"masterKey": "THS1236-master",
"referenceKey": "THS1236",
"images": [{ "hash": "images/d6abf85c58c7e596f12efc3d50ba27ce.jpg" }],
"customData": {}
},
{
"id": 14,
"isActive": true,
"isSoldOut": false,
"isNew": false,
"createdAt": "2024-02-15T16:59:30+00:00",
"updatedAt": "2024-02-15T16:59:32+00:00",
"indexedAt": "2024-02-16T15:18:54+00:00",
"firstLiveAt": "2024-02-15T16:59:30+00:00",
"masterKey": "THS1234-master",
"referenceKey": "THS1234",
"images": [{ "hash": "images/681449e893a536911ca06ad18426a7c4.jpg" }],
"customData": {}
},
{
"id": 13,
"isActive": true,
"isSoldOut": false,
"isNew": false,
"createdAt": "2024-02-15T16:59:30+00:00",
"updatedAt": "2024-02-15T16:59:31+00:00",
"indexedAt": "2024-02-16T15:18:54+00:00",
"firstLiveAt": "2024-02-15T16:59:30+00:00",
"masterKey": "THS1237-master",
"referenceKey": "THS1237",
"images": [{ "hash": "images/8869144bcbff3bc49cc980de873310ea.jpg" }],
"customData": {}
}
]
}
Common Errors
fetch failed | There is either a typo in the Storefront URL or the Storefront is not properly setup. |
---|---|
Unable to fetch products FetchError: Failed to fetch https://acme-live.storefront.api.scayle.cloud/v1/products?with=attributes%2Cvariants%2Cimages.attributes%3Alegacy%28false%29%2Ccategories%3Aproperties%28%29&shopId=100011 . 400 Bad Request | ⚠️ |
Full Code
const backbone = require("@aboutyou/backbone");
require("dotenv").config();
async function fetchProducts() {
const client = new backbone.BapiClient({
host: `https://${process.env.TENANT_SPACE}.storefront.api.scayle.cloud/v1/`,
shopId: process.env.SHOP_ID,
auth: {
type: "token",
token: process.env.STOREFRONT_API_TOKEN,
},
});
try {
const products = await client.products.query();
console.log("Fetched products", products);
} catch (error) {
console.error("Unable to fetch products", error);
}
}
fetchProducts();
Advanced Queries using the Storefront API
Let's adjust our previous code src/008_fetchProducts.js
and retrieve the data we set up previously. We will also try to filter our results.
Specify data you want to receive
Taking our very basic query, we can adjust it to receive more data.
For example, if we want to receive the color Attribute Group, we can pass the following:
try {
const products = await client.products.query({
with: {
attributes: {
withKey: ["color"],
},
},
});
console.log("Fetched products", products);
} catch (error) {
console.error("Unable to fetch products", error);
}
Even in JavaScript files, Visual Studio Code (VSCode) provides query hints due to TypeScript support in the SDK. This feature improves coding by offering auto-completion, type checks, and guidance on methods and properties, ensuring alignment with expected data structures and API calls.
Response
To receive variants, update your API query to include the following data:
try {
const products = await client.products.query({
with: {
attributes: {
withKey: ["color"],
},
variants: {
attributes: {
withKey: ["size"],
},
},
},
});
console.log("Fetched products", products);
} catch (error) {
console.error("Unable to fetch products", error);
}
Filtering Products
Let's imagine we want to show only blue shirts to the user.
First, let's figure out what category ID shirts have.
In the SCAYLE Panel, navigate to Shops > My Shop > Products > Categories
.
Let's also double check which attribute values we have by going to Settings > Attributes > Select "Color" > Attributes
.
In this shop, we only have blue and gray shirts.
With this knowledge, we can now create a query:
try {
const products = await client.products.query({
with: {
attributes: {
withKey: ["color"],
},
variants: {
attributes: {
withKey: ["size"],
},
},
},
where: {
categoryId: 8,
attributes: [
{
type: "attributes",
key: "color",
values: [4], // ID of color "white"
},
],
},
});
console.log("Fetched products", products);
} catch (error) {
console.error("Unable to fetch products", error);
}
You should now have an understanding of how to query your data using the Storefront API. For more in-depth examples and explanations, see our Onboarding guide.
In the next chapter, you'll learn how to work with the Storefront.
Storefront Boilerplate Setup
By now, we've set up our shop and added products using the Admin API and the Storefront API. The purpose of the following chapter is to introduce you to the Storefront Boilerplate, which is a starter kit for creating a frontend for your shop. You'll learn how to set it up and start customizing your shop through a small project: adding a sustainability badge to products.
As with the previous chapters of this tutorial, the following steps are presented in a greatly simplified manner to enable you to quickly get to know SCAYLE and how to work with it. For a more in-depth introduction to the Storefront Boilerplate, refer to our Storefront Guide.
Project Setup
Accessing the storefront-boilerplate-nuxt-public repository
The source code for Storefront Boilerplate is stored in a private GitLab repository. You will need an access token to view this repository - get in touch with your SCAYLE Customer Success Manager if you don't have a token already.
With your access token, use the git clone
command to check out the source code:
git clone https://oauth2:{GITLAB_ACCESS_TOKEN}@gitlab.com/aboutyou/scayle/core-engine/storefront-unit/storefront-core/storefront-boilerplate-nuxt-public.git
Using Redis locally
Depending on the circumstances, using a Redis docker
image for the local setup might not be necessary or result in degraded performance. In this case, a locally installed version of redis
/ redis-server
is sufficient. You can find installation instructions for redis-server here.
Once installed, you can start it with the following command:
redis-server
Install Dependencies
Start by installing yarn:
npm install --global yarn
From the root of the project, let's jump to the template we want to use:
yarn install
Local HTTPS
To try out every feature Storefront Boilerplate offers, we need to setup our local https.
To generate a certificate and key, we recommend using the mkcert tool.
Follow the mkcert installation instructions (Github) and afterward run:
mkcert --key-file localhost.pem --cert-file localhost.crt localhost
After generating the local key and certificate file, add both to your .env
file as follows:
HTTPS_KEY=localhost.pem
HTTPS_CERT=localhost.crt
Your project will now be served on https://localhost:3000
.
If you try to start the project now, you'll run into a lot of errors, as we haven't set up our configuration properly yet.
In the next section, we'll do exactly that.
Configuration
Copy the .env file
If you're not already in templates/nuxt
, navigate to the directory:
cd templates/nuxt
There you can either copy the .env.example
cp .env.example .env
or use this template:
# Where to launch the server
BASE_URL=http://localhost:3000
# Where to find product and other images
NUXT_PUBLIC_CDN_URL='https://{TENANT_SPACE}.cdn.scayle.cloud/'
# Redis configuration for caching and session management
# Cache
NUXT_STOREFRONT_STORAGE_CACHE_PROVIDER=redis
NUXT_STOREFRONT_STORAGE_CACHE_HOST=localhost
NUXT_STOREFRONT_STORAGE_CACHE_PORT=6379
NUXT_STOREFRONT_STORAGE_CACHE_USERNAME=
NUXT_STOREFRONT_STORAGE_CACHE_PASSWORD=
NUXT_STOREFRONT_STORAGE_CACHE_TLS=false
# Session
NUXT_STOREFRONT_STORAGE_SESSION_PROVIDER=redis
NUXT_STOREFRONT_STORAGE_SESSION_HOST=localhost
NUXT_STOREFRONT_STORAGE_SESSION_PORT=6379
NUXT_STOREFRONT_STORAGE_SESSION_USERNAME=
NUXT_STOREFRONT_STORAGE_SESSION_PASSWORD=
NUXT_STOREFRONT_STORAGE_SESSION_TLS=false
# Storefront API configuration
NUXT_STOREFRONT_BAPI_HOST=https://{TENANT_SPACE}.storefront.api.scayle.cloud/v1/
NUXT_STOREFRONT_BAPI_TOKEN={STOREFRONT_API_TOKEN}
# Login/Registration Configuration
NUXT_STOREFRONT_OAUTH_API_HOST=https://{TENANT_SPACE}.auth.scayle.cloud
NUXT_STOREFRONT_OAUTH_CLIENT_ID={OAUTH_CLIENT_ID}
NUXT_STOREFRONT_OAUTH_CLIENT_SECRET={OAUTH_CLIENT_API_KEY}
# Checkout configuration
NUXT_STOREFRONT_STORES_{SHOP_ID}_CHECKOUT_USER={SHOP_ID}
NUXT_STOREFRONT_STORES_{SHOP_ID}_CHECKOUT_TOKEN=token_{SHOP_ID} # this only works on demo environments, your SCAYLE contact can give you real credentials
NUXT_STOREFRONT_STORES_{SHOP_ID}_CHECKOUT_SECRET=secret_{SHOP_ID} # this only works on demo environments, your SCAYLE contact can give you real credentials
NUXT_STOREFRONT_STORES_{SHOP_ID}_CHECKOUT_HOST=https://{TENANT_SPACE}.checkout.api.scayle.cloud
# HTTPS Configuration for local development
HTTPS_KEY=localhost.pem
HTTPS_CERT=localhost.crt
# Google Tag Manager Configuration
NUXT_PUBLIC_GTM_ID='GTM-123'
# Storyblok Configuration
NUXT_PUBLIC_STORYBLOK_ACCESS_TOKEN=SXHjiBBXemgHRENlt7kYrQtt # Ask your SCAYLE Contact for a test token
There is one other place where you will need these.
In the storefront.ts
find the shops
variable, and replace it with the following:
const shops = [
{
locale: 'de-DE',
path: 'de',
shopId: 10001,
currency: 'EUR',
},
]
Fill in the credentials
This section may look complex, but don't worry: we need to generate just one set of new credentials.
OAUTH_CLIENT_ID and OAUTH_CLIENT_API_KEY
These are the only new credentials we need.
In the SCAYLE Panel, navigate to Shops >Storefront > API Keys
, and create a new token under Customer Authentication API Keys:
Use Secret as OAUTH_CLIENT_API_KEY
and the Client ID as OAUTH_CLIENT_ID
TENANT_SPACE
You should already know your tenant space from the previous chapters of this tutorial.
As a refresher, if you know your SCAYLE Panel URL (for example: https://acme-live.panel.scayle.cloud/) you can easily determine your tenant space by taking the first part of the url (acme-live
in this example).
STOREFRONT_API_TOKEN
You can either reuse your token or setup a new one in the SCAYLE Panel by navigating to Shops > My Shop > Storefront > API Keys
.
SHOP_ID
You can reuse the one you created in the previous steps of this tutorial. If you need a reminder, here's how to create a new one:
For the Shop ID, it's important that you pass the ShopCountry
id.
In the SCAYLE Panel, navigate to Shops > My Shop
, then make sure that you select the correct Country.
You'll be brought to a new screen, where you can find your Shop Country ID.
Make sure that you've replaced all {PLACEHOLDERS}
. In the next section, it's time to start the application.
Start the Application
Start the application in development mode
If you're not already intemplates/nuxt
, navigate to the directory:
cd templates/nuxt
Then enter the standard Nuxt command:
yarn dev
and open the Storefront Boilerplate running under http://localhost:3000/
.
Troubleshooting & Debugging
Products not appearing in the frontend
This might be an issue with the cache.
To make sure to have the newest data, open a terminal and execute the following commands:
redis-cli
and once connected, execute:
FLUSHALL
Redis not started
Make sure that you've started your redis with:
redis-server
and that it doesn't throw any errors.
Something is undefined
yarn install
Breakpoints
If your'e using VSCode, breakpoints should work out of the box when using yarn dev
.
Nuxt offers this tutorial if you're still having trouble.
Nuxt Debugger
One of the great things about Nuxt is the Debugger. You can learn more about it here.