Fetching API data on the storefront
You can build and customize GraphQL queries to display ecommerce data on your storefront, such as products and shopping cart information. In this guide, you will find the basic concepts and steps to implement this in your FastStore project.
caution
When building your storefront with FastStore, you must not send requests to APIs other than the FastStore API. If you need to access other data not available in the native FastStore API schema, you must do this by extending the GraphQL schema. Otherwise, site performance may be compromised and lead to 504
timeout errors.
Before you start​
Before getting to work on your code, there are some concepts you should be familiar with when it comes to the FastStore API.
The FastStore API extends the data layer of your preferred static site generation framework (e.g., Next.js, Gatsby), including data from an ecommerce platform. Because of that, ecommerce information is queried for a given page only when that page is built.
This means that updating a given product's information on your ecommerce platform does not automatically update the information displayed on a previously built product page. Whenever you wish to update the information displayed on your website according to your ecommerce platform data, you should redeploy your website, which will trigger page re-generation.
We also recommend that you take the time to learn more about data fetching in the context of the framework you are using, by checking the corresponding article:
Best practices for fetching data​
Site performance tends to get worse as more API requests are made by a page. Because of this, the best practices for fetching data on your storefront involve getting precisely the data you need with the minimum number possible of requests to the FastStore API. The sections below go over what you can do to minimize the API requests of your pages.
Fetch only the data you need​
GraphQL allows you to customize your query to get precisely the data you need, which reduces the data returned from the requests. Double-check your queries to make sure they are not over-fetching.
This also means that you must be mindful of the data brought into your query by GraphQL fragments. Use them only when they do not include unnecessary data.
Do not send requests to other APIs​
If you need data that is not available on the native FastStore GraphQL schema, check the root object.
The GraphQL root object represents the top-level object returned to a query. You can see what data is available in the root object by adding logs or using a GraphQL IDE.
If the root object also lacks the information you need, you must extend the FastStore GraphQL schema instead of adding other requests to your page.
Avoid custom API Routes​
We do not recomend using Next.js API Routes other than the ones already built in the FastStore starters.
If you do use this type of function, you must be mindful to always check which ones are actually running and remove the ones that are not.
To see what API Routes are running in your project, you can run the command yarn build
at the root of your project and check the log. Then, check the directory src/pages/api
of your project and remove functions that are not running or are not included in the starter you used.
Fetching ecommerce data​
There are three main steps to building your page code to fetch data from the FastStore API:
Below you can see more details about each step along with code examples.
1. Building a query​
First, you need to know what API data you want to use on your page and how to structure a GraphQL query to get it. It is a good idea to check the FastStore API reference on queries. You can also use a GraphQL IDE to build and test queries to make sure it works as expected.
Once you have your query structure, you can pass that as a variable on your code by using the gql
tag, like in the example below.
import { gql } from '@faststore/graphql-utils'
...
const query = gql`
query ProductPageQuery($slug: String!) {
product(locator: [{ key: "slug", value: $slug }]) {
seo {
title
description
canonical
}
brand {
name
}
sku
name
description
}
}
`
Queries must be declared in this way on each page on which you wish to use their data. To reuse query snippets across multiple files, you may use GraphQL fragments. In the example below you can see an SEO fragment being used to build the same query as the example above.
Declaring the fragment:
import { gql } from '@faststore/graphql-utils'
...
export const fragment = gql`
fragment ProductSeoFragment_product on StoreProduct {
seo {
title
description
canonical
}
}
`
Using the fragment, on the same file or a different one:
import { gql } from '@faststore/graphql-utils'
...
const query = gql`
query ProductPageQuery($slug: String!) {
product(locator: [{ key: "slug", value: $slug }]) {
...ProductSeoFragment_product
brand {
name
}
sku
name
description
}
}
`
Building queries on Gatsby​
If you are building queries on a store that uses Gatsby, keep in mind that you must also use the graphql
tag in some contexts. Using graphql
causes the query to be processed by Gatsby, while gql
does not. Because of that, as a general rule, use graphql
for queries that should be run during the page build and gql
for the rest.
Also, some queries may not run properly during the build. If you run into that issue, try using gql
.
See in the following example how the queries in the Next.js base store product page and the corresponding page of the Gatsby base store compare to each other.
- Next.js
- Gatsby
import { gql } from '@faststore/graphql-utils'
...
const query = gql`
query ServerProductPageQuery($slug: String!) {
product(locator: [{ key: "slug", value: $slug }]) {
id: productID
seo {
title
description
canonical
}
brand {
name
}
sku
gtin
name
description
breadcrumbList {
itemListElement {
item
name
position
}
}
image {
url
alternateName
}
offers {
lowPrice
highPrice
priceCurrency
offers {
availability
price
priceValidUntil
priceCurrency
itemCondition
seller {
identifier
}
}
}
isVariantOf {
productGroupID
}
...ProductDetailsFragment_product
}
}
`
import { graphql } from 'gatsby'
import { gql } from '@faststore/graphql-utils'
...
export const querySSG = graphql`
query ProductPageQuery {
site {
siteMetadata {
title
description
titleTemplate
siteUrl
}
}
}
`
export const querySSR = gql`
query ServerProductPageQuery($slug: String!) {
product(locator: [{ key: "slug", value: $slug }]) {
id: productID
seo {
title
description
canonical
}
brand {
name
}
sku
gtin
name
description
breadcrumbList {
itemListElement {
item
name
position
}
}
image {
url
alternateName
}
offers {
lowPrice
highPrice
priceCurrency
offers {
availability
price
priceValidUntil
priceCurrency
itemCondition
seller {
identifier
}
}
}
isVariantOf {
productGroupID
}
...ProductDetailsFragment_product
}
}
`
2. Importing the generated query​
Once you have declared your query on the page code, you can trigger the generation of your query types by running this command:
yarn generate
caution
Whenever you make changes to your declared queries you must regenerate the types with the command above. Otherwise, you will not be able to use the data.
Then you must import the types generated, like in this example:
import { gql } from '@faststore/graphql-utils'
import type { ProductPageQueryQuery } from '@generated/graphql'
...
const query = gql`
query ProductPageQuery($slug: String!) {
product(locator: [{ key: "slug", value: $slug }]) {
## Query fields
}
}
`
info
Note that, like in this example, the auto-generated query types names are formed by adding the word "Query" to the end of the query name you declared.
3. Using the data​
Having built a query and imported the generated type, you can effectively destructure and use the API data in your page function, like in the example:
...
type Props = ProductPageQueryQuery
function Page({ product }: Props) {
const { seo } = product
const title = seo.title
const description = seo.description
...
}
...
Complete code example​
After completing the steps described above, your code should look like the example below.
info
It is also a good idea to see how data fetching is implemented in pages from FastStore starters, such as:
import { gql } from '@faststore/graphql-utils'
import type { ProductPageQueryQuery } from '@generated/graphql'
...
type Props = ProductPageQueryQuery
function Page({ product }: Props) {
const { seo } = product
const title = seo.title
const description = seo.description
...
}
...
const query = gql`
query ProductPageQuery($slug: String!) {
product(locator: [{ key: "slug", value: $slug }]) {
seo {
title
description
canonical
}
brand {
name
}
sku
name
description
}
}
`