End-to-End Guide: Headless checkout flow with the GraphQL Storefront API
The BigCommerce GraphQL Storefront API lets server-side and browser-side clients manage product, cart, and checkout objects to build storefront features. The GraphQL Storefront API can solve the same use cases as our REST Management API's cart and checkout features, but makes it easier to build headless storefront applications. Developers using the GraphQL Storefront API can spend less time focusing on API interactions and more time building the shopper experience.
This end-to-end guide describes how to work with shopper interactions on headless storefronts. These steps let you build shopping experiences where the purchase funnel is mainly powered by the GraphQL Storefront API, from catalog browsing through checkout. The examples walk you through critical capabilities that fit many headless use cases.
You can use the GraphQL Storefront API playground to run the example queries in this guide. To access your store's GraphQL Storefront API playground, sign in to your store (opens in a new tab), and navigate to Settings > API > Storefront API Playground.
Prerequisites
To complete the guide, you need the following:
- BigCommerce sandbox store (opens in a new tab)
- Familiarity with creating a channel and a site
Accessing the GraphQL Storefront API
You can make requests to the GraphQL Storefront API in a server-to-server context. Typically, server-side API clients should use customer impersonation tokens to authenticate requests to the GraphQL Storefront API. Frontend API clients that primarily serve static sites with no sign-in capabilities can use storefront tokens. However, server-to-server requests can use storefront tokens as well. This guide describes creating and using customer impersonation tokens to authenticate and use the GraphQL Storefront API.
Create a customer impersonation token
A customer impersonation token lets you conduct actions for any shopper, in the context of their account. Customer impersonation tokens are sensitive, and you must not expose them publicly. To generate a customer impersonation token, send a request to the Create a customer impersonation token endpoint.
You can make customer impersonation token-authenticated requests by specifying the customer ID as the value of the X-BC-Customer-Id
header when making requests to the GraphQL Storefront API endpoint. For an example that uses the X-BC-Customer-Id
header, see this guide's section on Querying product data.
Typically, there is no need to use a customer impersonation token in the GraphQL Storefront API playground. Using the playground with a customer impersonation token is solely an example in this guide.
POST https://api.bigcommerce.com/stores/{{STORE_HASH}}/v3/storefront/api-token-customer-impersonation
X-Auth-Token: {{ACCESS_TOKEN}}
Accept: application/json
Content-Type: application/json
{
"channel_id": 1,
"expires_at": 1602288000
}
In the playground, add the customer impersonation token to the Headers tab as follows. Ensure that you leave a space between Bearer
and the customer impersonation token.
{
"Authorization": "Bearer {customer impersonation token}"
}
Querying product data
The GraphQL Storefront API lets you retrieve product data from a store. The following example demonstrates how to query a simple product using the GraphQL Storefront API. Pricing and visibility response values can vary based on the customer. For more information and examples, see the Guide to working with products.
When possible, use the following best practices for queries to the GraphQL Storefront API.
- Query fewer than 50 resources at a time.
- Limit query complexity.
- Limit pagination.
- Employ security practices and limit scope.
- Cache data to avoid repeat fetching of data that hasn't changed.
GET https://store.example.com/graphql
Authorization: Bearer {{CUSTOMER_IMPERSONATION_TOKEN}}
Accept: application/json
X-Bc-Customer-Id: 123
# This query retrieves one product.
query SingleProduct ($entityId: Int) {
site {
product(entityId: $entityId) {
id
entityId
name
sku
description
prices {
price {
value
currencyCode
}
}
}
}
}
Creating a cart
BigCommerce's GraphQL Storefront API provides the same cart and checkout objects as the REST Storefront API. Pricing and visibility response values can vary based on the customer. The following example shows how to create a new cart by adding a simple product.
Make note of one of the cart's entityId
displayed in the response. You will need to use it in later steps.
POST https://store.example.com/graphql
Accept: application/json
Authorization: Bearer {{CUSTOMER_IMPERSONATION_TOKEN}}
X-Bc-Customer-Id: 123
# Creates a new cart, adding a simple product.
mutation createCartSimple($createCartInput: CreateCartInput!) {
cart {
createCart(input: $createCartInput) {
cart {
entityId
lineItems {
physicalItems {
name
quantity
}
digitalItems {
name
quantity
}
giftCertificates {
name
}
customItems {
name
quantity
}
}
}
}
}
}
Add cart line items
To add a new line item to the existing cart, add the cart ID to the input variables or the mutation will fail.
POST https://store.example.com/graphql
Authorization: Bearer {{CUSTOMER_IMPERSONATION_TOKEN}}
X-Bc-Customer-Id: 123
mutation addCartLineItems($addCartLineItemsInput: AddCartLineItemsInput!) {
cart {
addCartLineItems(input: $addCartLineItemsInput) {
cart {
entityId
}
}
}
}
Get a checkout
The following query example shows how to display the contents of a checkout.
You can access cart and checkout details in the same request as other information. The cart ID is the same as a checkout ID.
GET https://store.example.com/graphql
Authorization: Bearer {{CUSTOMER_IMPERSONATION_TOKEN}}
X-Bc-Customer-Id: 123
query getCheckout($entityId: Int) {
site {
checkout(entityId: $entityId) {
entityId
billingAddress {
...CheckoutBillingAddressFields
}
shippingConsignments {
...CheckoutShippingConsignmentFields
}
order {
entityId
}
shippingCostTotal {
...MoneyFields
}
giftWrappingCostTotal {
...MoneyFields
}
handlingCostTotal {
...MoneyFields
}
taxTotal {
...MoneyFields
}
taxes {
...CheckoutTaxFields
}
subtotal {
...MoneyFields
}
grandTotal {
...MoneyFields
}
createdAt {
utc
}
updatedAt {
utc
}
customerMessage
outstandingBalance {
...MoneyFields
}
coupons {
...CheckoutCouponFields
}
promotions {
...CheckoutPromotionFields
}
}
}
}
fragment CheckoutConsignmentAddressFields on CheckoutConsignmentAddress {
...CheckoutAddressFields
}
fragment CheckoutBillingAddressFields on CheckoutBillingAddress {
entityId
...CheckoutAddressFields
}
fragment CheckoutAddressFields on CheckoutAddress {
firstName
lastName
email
company
address1
address2
city
stateOrProvince
stateOrProvinceCode
countryCode
postalCode
phone
customFields {
entityId
... on CheckoutAddressCheckboxesCustomField {
valueEntityIds
}
... on CheckoutAddressDateCustomField {
date {
utc
}
}
... on CheckoutAddressMultipleChoiceCustomField {
valueEntityId
}
... on CheckoutAddressNumberCustomField {
number
}
... on CheckoutAddressPasswordCustomField {
password
}
... on CheckoutAddressTextFieldCustomField {
text
}
}
}
fragment CheckoutShippingConsignmentFields on CheckoutShippingConsignment {
entityId
address {
...CheckoutConsignmentAddressFields
}
availableShippingOptions {
...CheckoutAvailableShippingOptionFields
}
selectedShippingOption {
...CheckoutSelectedShippingOptionFields
}
coupons {
...CheckoutCouponFields
}
shippingCost {
...MoneyFields
}
handlingCost {
...MoneyFields
}
lineItemIds
}
fragment CheckoutAvailableShippingOptionFields on CheckoutAvailableShippingOption {
entityId
description
type
imageUrl
cost {
...MoneyFields
}
transitTime
isRecommended
}
fragment CheckoutSelectedShippingOptionFields on CheckoutSelectedShippingOption {
entityId
description
type
imageUrl
cost {
...MoneyFields
}
transitTime
}
fragment MoneyFields on Money {
value
currencyCode
}
fragment CheckoutCouponFields on CheckoutCoupon {
entityId
code
couponType
discountedAmount {
...MoneyFields
}
}
fragment CheckoutTaxFields on CheckoutTax {
name
amount {
...MoneyFields
}
}
fragment CheckoutPromotionFields on CheckoutPromotion {
banners {
entityId
type
locations
text
}
}
Add a checkout billing address
This mutation adds a billing address to an existing checkout.
POST https://store.example.com/graphql
Authorization: Bearer {{CUSTOMER_IMPERSONATION_TOKEN}}
X-Bc-Customer-Id: 123
mutation addCheckoutBillingAddress($addCheckoutBillingAddressInput: AddCheckoutBillingAddressInput!) {
checkout {
addCheckoutBillingAddress(input: $addCheckoutBillingAddressInput) {
checkout {
entityId
}
}
}
}
Add a checkout shipping consignment
This mutation adds a shipping consignment to an existing checkout.
Make a note of a shipping consignment's entityId
and the desired shipping option's entityId
returned from your request. You will need to use these in later steps.
POST https://store.example.com/graphql
Authorization: Bearer {{CUSTOMER_IMPERSONATION_TOKEN}}
X-Bc-Customer-Id: 123
mutation addCheckoutShippingConsignments($addCheckoutShippingConsignmentsInput: AddCheckoutShippingConsignmentsInput!) {
checkout {
addCheckoutShippingConsignments(input: $addCheckoutShippingConsignmentsInput) {
checkout {
entityId
shippingConsignments {
entityId
availableShippingOptions {
entityId
}
selectedShippingOption {
entityId
}
}
}
}
}
}
Select checkout shipping option
This mutation adds a selected shipping to an existing checkout.
POST https://store.example.com/graphql
Authorization: Bearer {{CUSTOMER_IMPERSONATION_TOKEN}}
X-Bc-Customer-Id: 123
mutation selectCheckoutShippingOption($selectCheckoutShippingOptionInput: SelectCheckoutShippingOptionInput!) {
checkout {
selectCheckoutShippingOption(input: $selectCheckoutShippingOptionInput) {
checkout {
entityId
}
}
}
}
Complete checkout
Completing a checkout creates an incomplete order until you process the payment. For PCI compliance-related reasons, the GraphQL Storefront API does not handle payments. You must use the Payments API to process payments. The payments workflow includes the following three steps:
- Fetch available payment methods
- Create a payment access token by either requesting one with the following mutation or using the REST Payments API
- Capture payment
POST https://store.example.com/graphql
Authorization: Bearer {{CUSTOMER_IMPERSONATION_TOKEN}}
X-Bc-Customer-Id: 123
mutation completeCheckout($completeCheckoutInput: CompleteCheckoutInput!) {
checkout {
completeCheckout(input:$completeCheckoutInput) {
orderEntityId
paymentAccessToken
}
}
}
Resources
GraphQL Storefront API
- Storefront tokens
- Querying within a BigCommerce storefront
- Create a cart using a simple product
- Add cart line items
- Add checkout billing address
- Add a checkout shipping consignment
- Select checkout shipping option
- Complete checkout