Storefront API Learning Kit
About this repo | How to use this repo | Contribute to this repo | Getting started | Example queries
About this repo
This repo provides example queries demonstrating how to use Shopify's GraphQL Storefront API. Downloading the Storefront API insomnia collection package, gives you access to a complete set of sample queries for use in the Insomnia http client. The Insomnia desktop app comes with rich GraphQL features, including automatic schema fetching and autocomplete, which are extremely valuable in learning a new API.
How to use this repo
To import the Insomnia package, first download the latest collection (you'll need to save the raw JSON file).
From the Insomnia Dashboard screen, click Create
, followed by clicking File
. Select the file you downloaded.
If you don't want to download the Insomnia package, the query examples are listed out below.
Getting started
Introduction
This learning kit provides a set of common GraphQL queries and mutations used with the Shopify Storefront API.
If not already familiar with GraphQL, or Shopify APIs, please consult the Shopify GraphQL learning kit https://shopifypartnerblog.myshopify.com/blogs/blog/shopify-graphql-learning-kit
The Shopify Storefront API gives you full creative control to customize your customers' buying experience.
With the Storefront API you can access several Shopify resource types with the following access scopes:
- Read products, variants, and collections.
- Read and modify customer details.
- Read and modify checkouts.
- Read store content like articles, blogs and comments.
- Read subscription selling plans.
- Read and modify cart objects.
Unlike the Admin API, the Storefront API is an unauthenticated API. Any data exposed by the Storefront API can be seen by any visitor to the store. Only use the Storefront API when you're comfortable with that risk and the data that is being exposed. Risk can be mitigated by only providing access scopes required. For a complete list of access scopes consult Shopify documentation at https://shopify.dev/api/usage/access-scopes#unauthenticated-access-scopes
Access to the Storefront API can be granted by a merchant via a public sales channel, or by creating a Headless channel in your Shopify Admin. For simplicity of this tutorial, we'll create a Headless channel in the Shopify Admin. The process to add the Headless channel is documented in the next section titled "Installing the Headless Channel ".
Documentation for accessing the Storefront API using the Headless channel can be found here
The home of Storefront API-related developer documents and tutorials can be found at https://shopify.dev/api/storefront
Installing the headless channel
To start using the Storefront API you'll need to enable access by installing the Headless channel on your store. To install, you can follow the directions outlined here or get it from the Shopify App Store.
Installing the Headless Channel from Shopify Admin
- From your Shopify admin, click Sales channels.
- Click Recommended sales channels.
- In the Picked for you modal, scroll to the Build custom storefronts section.
- Within the Headless: Build your own commerce stack card, click Add.
- Click Add sales channel.
- Click Create storefront.
Configure your environment variables
Environment variables are JSON key-value pairs that allow you to refer to values without having to write them out every time.
For the tutorial, three environment variables will be utilized.
base_url
will be the Shopify store being connected to.
- If your store is mydevstore.myshopify.com, enter “mydevstore.myshopify.com” here.
api_version
is the Storefront API version used for the API requests.
- This can be changed to an earlier version or unstable depending on your use case.
storefront_access_token
is used to populate the X-Shopify-Storefront-Access-Token request header.
- This is the Public access token associated with the Storefront you created in the "Installing the Headless Channel" section.
Making your first request
You should see at the top of the frame that we're using the "base_url" and "api_version" to build out the address for the endpoint. You can also click the "Headers" tab at the top to see the "storefront_access_token" being used. Hovering over environment variables should show you the value that will be substituted into the request. If you don’t see your values, ensure you have the right environment selected.
Once you've confirmed these three fields are set in your environment, try running the shop query below. If the Storefront API access token has been configured correctly, you should get your shop’s info returned.
query getShopDetails{
shop {
name
primaryDomain{
host
url
}
paymentSettings{
currencyCode
acceptedCardBrands
enabledPresentmentCurrencies
}
}
}
Example queries
Metafields metaobjects
Expose metafield to SFAPI
Metafields allow merchants to store additional information for Shopify resources including:
- Products
- Collections
- Customers
- Blogs
- Pages
- Shop
- Discounts
- Draft Orders
- Locations
- Orders
- Product Images
- Product Variants
For a complete list please consult https://shopify.dev/api/admin-graphql/2022-10/enums/MetafieldOwnerType
Unlike the Admin API, metafields must first be made visible to the Storefront API. To make metafields visible to the Storefront API use the Shopify Admin API mutation metafieldStorefrontVisibilityCreate.
Ensure you are calling the Admin API https://shopify.dev/api/admin-graphql#endpoints with valid Admin API credentials https://shopify.dev/api/admin-graphql#authentication when exposing metafields to the Storefront API.
For more information on the metafieldStorefrontVisibilityCreate mutation consult the Shopify Admin API doc https://shopify.dev/docs/admin-api/graphql/reference/metafields/metafieldstorefrontvisibilitycreate
For a complete Storefront API metafield reference please consult the metafield tutorial at https://shopify.dev/tutorials/retrieve-metafields-with-storefront-api#expose-metafields-to-the-storefront-api
mutation createMetafieldStorefrontVisibility(
$input: MetafieldStorefrontVisibilityInput!
) {
metafieldStorefrontVisibilityCreate(input: $input) {
metafieldStorefrontVisibility {
id # MetafieldStorefrontVisibility record id
key # Key must be unique within this namespace on this resource
ownerType
namespace
updatedAt
}
userErrors {
field
message
}
}
}
variables
{
"input": {
"key": "drying_instructions",
"namespace": "garment_care",
"ownerType": "COLLECTION"
}
}
Retrieve metafields
Once a metafield has been exposed it can be retrieved using the Storefront API. In order to retrieve a single metafield, specify the namespace and key arguments. To query for a list of metafields pass the identifiers argument again specifying namespace and key For more information please consult https://shopify.dev/custom-storefronts/products-collections/metafields#step-2-retrieve-metafields
The following example retrieves a specific metafield and a list of metafields that match the supplied namespace and key and collection id. Ensure that you've added a value to any metafields you wish to query back by updating it using Admin API https://shopify.dev/apps/metafields/manage-metafields#step-3-update-a-metafield
query getCollectionMetaField(
$id: ID!
$namespace: String!
$key: String!
$another_namespace: String!
$another_key: String!
) {
collection(id: $id) {
metafield(namespace: $namespace, key: $key) {
key
namespace
value
id # metafield id
}
}
collection(id: $id) {
metafields(
identifiers: [
{ namespace: $namespace, key: $key },
{ namespace: $another_namespace, key: $another_key }
]
) {
key
namespace
value
id # metafield id
}
}
}
variables
{
"id": "gid://shopify/Collection/288378781858",
"namespace": "garment_care",
"key": "wash_temperature",
"another_namespace": "bakery",
"another_key": "ingredients-new"
}
Retrieve storefront visibilities
To retrieve a list of MetafieldStorefrontVisibility records use the metafieldStorefrontVisibilities query available on the Admin API and return a list of exposed metafield records.
Ensure you are calling the Admin API https://shopify.dev/api/admin-graphql#endpoints with valid Admin API credentials https://shopify.dev/api/admin-graphql#authentication when retrieving a list of MetafieldStorefrontVisibility records. For a complete reference please consult https://shopify.dev/api/admin-graphql/2022-10/queries/metafieldStorefrontVisibilities#top
query getMetafieldStorefrontVisibilities($first: Int!, $namespace: String!) {
metafieldStorefrontVisibilities(first: $first, namespace: $namespace) {
edges {
node {
id # Metafield visibility record id
namespace
key
createdAt
}
}
}
}
variables
{
"first": 5,
"namespace": "garment_care"
}
Delete storefront visibilities
If you no longer need to access a metafield with the Storefront API, you can hide it again by using the GraphQL Admin API to delete the MetafieldStorefrontVisibility record that you created. The metafieldStorefrontVisibilityDelete mutation requires the visibility record of the metafield you wish to hide from the Storefront API. The metafield will no longer be accessible through the Storefront API.
Ensure you are calling the Admin API https://shopify.dev/api/admin-graphql#endpoints with valid Admin API credentials https://shopify.dev/api/admin-graphql#authentication when deleting a MetafieldStorefrontVisibility record. For a complete reference please consult https://shopify.dev/api/admin-graphql/2022-10/mutations/metafieldStorefrontVisibilityDelete
mutation deleteMetafieldStorefrontVisibilities($id: ID!) {
metafieldStorefrontVisibilityDelete(id: $id) {
deletedMetafieldStorefrontVisibilityId # The visibility record of the metafield hidden from Storefront API
userErrors {
field
message
}
}
}
variables
{
"id": "gid://shopify/MetafieldStorefrontVisibility/1684242594"
}
Retrieve metaobjects
Metaobjects are custom data structures introduced with version 2023-01 that your app can define and create to store your app's information. Similar to metafields, they can be associated with a Shopify resource such as a product or a collection. However, they can also exist on their own. Metaobjects provide you with a way to create resources that Shopify doesn't offer out of the box.
In order to query metaobjects with the Storefront API you must first create a metaobject definition using the Admin API with the metaobjectDefinitionCreate mutation and create a corresponding metaobject using the Admin API mutation metaobjectCreate. For more information consult Shopify Admin API docs at https://shopify.dev/api/admin-graphql/2023-01/mutations/metaobjectDefinitionCreate and https://shopify.dev/api/admin-graphql/2023-01/mutations/metaobjectCreate
When creating a new metaobject definition to create new associated metaobjects that you want to access using Storefront API, be sure to set "access" for the "storefront" property to "PUBLIC_READ". For more information about the MetaObjectDefinitionCreateInput please see https://shopify.dev/api/admin-graphql/2023-01/mutations/metaobjectDefinitionCreate#field-metaobjectdefinitioncreateinput-access Ensure you are calling the Admin API https://shopify.dev/api/admin-graphql#endpoints with valid Admin API credentials https://shopify.dev/api/admin-graphql#authentication
The following example returns a list of the first ten metaobjects for a given type from the Storefront API. As well as type, which is a required argument, either first or last must be passed. Other optional arguments include reverse and sortKey which determines whether to sort the returned list by "id", "type", "updated_at", or "display_name". For more information consult Storefront API documentation at https://shopify.dev/api/storefront/2023-01/queries/metaobjects
query getMetaObjects(
$type: String!,
$sortKey: String,
$first: Int,
$reverse: Boolean
){
metaobjects(
type: $type,
sortKey: $sortKey,
first: $first,
reverse: $reverse
) {
edges {
node {
id
fields {
key
value
}
handle
updatedAt
type
}
}
}
}
variables
{
"type": "Product_Highlights",
"sortKey": "id",
"first": 10,
"reverse": true
}
Retrieve metaobject
The following example retreives a single metaobject by a given metaobject id. For more information consult Storefront API documentation at https://shopify.dev/api/storefront/2023-01/queries/metaobject
query getMetaObject($id: ID!) { # A metaobject can be retrieved by handle or id
metaobject(id: $id) {
id
type
updatedAt
handle
fields {
key
value
type
}
fields {
key
value
type
}
}
}
variables
{
"id": "gid://shopify/Metaobject/819214"
}
International pricing
Get available countries and currencies
To present pricing in local currency enable the market of the passed in country context within Markets. If the country is not enabled in Markets the currency of the active localized experience will be the store's default currency.
To present a localized language experience enable it from Markets. If an alternate language is not enabled for the passed in country context, the active language will be the store's default.
query getCountriesAndCurrencies($country: CountryCode) @inContext(country: $country) {
localization {
language{ #The language of the active localized experience.
isoCode
name
}
availableCountries {
currency {
isoCode
name
symbol
}
isoCode
name
unitSystem
}
country { #The currency of the active localized experience.
currency {
isoCode
name
symbol
}
isoCode
name
unitSystem
}
}
}
variables
{
"country": "FR"
}
Get product prices
query allProducts($country: CountryCode) @inContext(country: $country) {
products(first: 1) {
edges {
node {
title
variants(first:1) {
edges {
node {
title
price {
amount
currencyCode #active local currency
}
}
}
}
}
}
}
}
variables
{
"country": "CA"
}
Get price ranges for products
query getProductPriceRanges($country: CountryCode) @inContext(country: $country) {
products(first: 1) {
edges {
node {
title
priceRange {
minVariantPrice {
amount
currencyCode #active local currency
}
maxVariantPrice {
amount
currencyCode
}
}
compareAtPriceRange {
minVariantPrice {
amount
currencyCode #active local currency
}
maxVariantPrice {
amount
currencyCode
}
}
}
}
}
}
variables
{
"country": "CA"
}
Get customer orders
query getcustomerOrders($customerAccessToken: String!, $country: CountryCode)@inContext(country: $country) {
customer(customerAccessToken: $customerAccessToken) {
orders(first:10) {
edges {
node {
totalPrice {
amount
currencyCode # store's currency
}
lineItems(first:10) {
edges {
node {
originalTotalPrice {
amount
currencyCode # store's currency
}
variant {
price {
amount
currencyCode # active local currency
}
}
}
}
}
}
}
}
}
}
variables
{
"customerAccessToken": "customerAccessToken",
"country": "FR"
}
Create cart in local context
Generates a cart in the currency and language of the context passed in. Requires that the country passed be enabled in Markets and that the language passed in is enabled for that market.
mutation cartCreate($cartInput: CartInput!, $country: CountryCode, $language: LanguageCode)@inContext(country: $country, language: $language){
cartCreate(input: $cartInput) {
userErrors {
code
message
}
cart {
id
checkoutUrl #URL for cart in local currency and language passed in
lines(first: 50) {
edges {
node {
id
merchandise {
... on ProductVariant {
title
product {
title
}
id
quantityAvailable
}
}
}
}
}
cost {
subtotalAmount {
amount #active local currency
currencyCode
}
totalAmount {
amount #active local currency
currencyCode
}
}
}
}
}
variables
{
"cartInput": {
"lines": [
{
"quantity": 3,
"merchandiseId": "gid://shopify/ProductVariant/42485059584162"
},
{
"quantity": 1,
"merchandiseId": "gid://shopify/ProductVariant/42790980223138"
}
]
},
"country": "US",
"language": "ES"
}
Local pickup
Get pickup availability for variants
Before sending this request, please make sure your app has unauthenticated_read_product_pickup_locations scope, and store pick up has been enabled. For all the requirements please check this dev doc: https://shopify.dev/custom-storefronts/products-collections/local-pickup#requirements
You can also use "id" to replace "handle" as argument to query product.
query getStoreAvailability($handle: String! $name: String! $value:String!) {
product(handle:$handle) {
variantBySelectedOptions(selectedOptions: {name: $name, value: $value}) {
storeAvailability(first: 1) {
edges {
node {
available
pickUpTime
location {
name
}
}
}
}
}
}
}
variables
{
"handle": "Orange",
"name": "Weight",
"value": "2 lb"
}
Get nearest pickup locations
This query will return the first 5 shop locations that support in-store pickup. The near
parameter is used to sort results based on proximity to the provided location. Results could also be sorted by city, location id, or location name by using CITY, ID, or NAME respectively as the sortKey.
query getNearestPickupLocations($location: GeoCoordinateInput!) {
locations(near:$location, first: 5, sortKey: DISTANCE) {
edges {
node {
id
name
address {
formatted
}
}
}
}
}
variables
{
"location": {
"latitude": 45.4553,
"longitude": -75.6973
}
}
Get preferred pickup location availability
Before sending this request, please make sure your app has unauthenticated_read_product_pickup_locations scope.
This query will return in-store pickup locations that have the product stocked, sorted by proximity to a buyers preferred store pickup location. The buyer's preferred pickup location is passed as the preferredLocationId
argument.
query getPreferredStoreAvailability ($preferredLocationId: ID, $handle: String!,$selectedOptions: [SelectedOptionInput!]!)@inContext(preferredLocationId: $preferredLocationId) {
product(handle: $handle) {
variantBySelectedOptions(selectedOptions: $selectedOptions) {
storeAvailability(first: 1) {
edges {
node {
available
pickUpTime
location {
name
}
}
}
}
}
}
}
variables
{
"preferredLocationId": "gid://shopify/Location/65607794710",
"handle": "Orange",
"selectedOptions": {
"name": "Weight",
"value": "1 lb"
}
}
Collections
Get collections
Simple query to return the first 10 collections in the shop.
Since a shop can contain multiple collections, pagination is required.
query getCollections {
collections(first: 10) {
edges {
cursor
node {
id
handle
}
}
pageInfo {
hasNextPage
hasPreviousPage
}
}
}
Get collection by handle
Simple query to return details from a collection object by passing the collection.handle as an argument.
query getCollectionByHandle($handle: String!) {
collection(handle: $handle) {
id
title
description
}
}
variables
{
"handle": "all"
}
Get collection by id
Query that returns details from a collection object by passing the collection.id as an argument.
query getCollectionById($id: ID!) {
collection(id: $id) {
title
description
handle
}
}
variables
{
"id": "gid://shopify/Collection/1"
}
Get products in collection
This query returns data from a single collection, specified by the handle.
The data returned in the product connection can be used to display a page of products.
The products
connection requires pagination in this query, since collections can contain a large number of products.
This query includes the sortKey
argument on the products connection, this returns products in the order specified by the sortKey
Products can contain multiple images, so the images
connection requires pagination.
Since products can contain multiple variants, we've asked the products connection to return price ranges.
In this example we only want to display 1 image per product, so we're only asking for first:1
query getProductsInCollection($handle: String!) {
collection(handle: $handle) {
id
title
products(first: 50, sortKey: BEST_SELLING) {
edges {
node {
id
title
vendor
availableForSale
images(first: 1) {
edges {
node {
id
url
width
height
altText
}
}
}
priceRange { # Returns range of prices for a product in the shop's currency.
minVariantPrice {
amount
currencyCode
}
maxVariantPrice {
amount
currencyCode
}
}
}
}
}
}
}
variables
{
"handle": "all"
}
Get all metafields for namespace in collection
Uses the collectionByHandle
query to specify a collection by passing the handle.
Identifiers are used to identify the metafields associated with the resource matching the supplied list of namespaces and keys.
The metafields
connection is using the namespace
argument to return only metafields in a specific namespace.
Since collections can have a large number of metafields in a given namespace, pagination is required on the metafields
connection.
By default, the Storefront API can't read metafields. To make specific metafields visible in the Storefront API, you need to create a MetafieldStorefrontVisibility record.
For more information please consult #https://shopify.dev/custom-storefronts/products-collections/metafields
query getCollectionMetafieldsByNamespace($handle: String! $namespace: String!) {
collection(handle: $handle) {
id
metafields(identifiers: [{ namespace: $namespace, key: $key }]) {
key
namespace
value
id
}
}
}
variables
{
"handle": "all",
"namespace": "global"
}
Filter products in collection
You can use the Storefront API to filter products in a collection using product filters.
This functionality lets you build a desired customer experience on a storefront, such as the ability to narrow down the search results that you display to customers.
Products in collections can be filtered by type, vendor, variant options, price, stock and metafield value.
Please note there are requirements to using product filters in collections here - https://shopify.dev/custom-storefronts/products-collections/filter-products#requirements
In the following example, products in the collection that have the "shoes" product type are returned.
Further examples of product filters can be found in the above documentation.
query getProductsOfProductTypeInCollection($handle: String!, $value: String!) {
collection(handle: $handle) {
handle
products(first: 10, filters: { productType: $value }) {
edges {
node {
handle
productType
}
}
}
}
}
variables
{
"handle": "filterable-collection",
"value": "shoes"
}
Products
Get 3 products and 3 variants
This query gets the products connection, which is available from the QueryRoot, and asks for the first 3 products. It selects edges, the node, and fields from each of the returned product objects. Since products also have a variants connection, we repeat a similar process to get information on the first 3 variants on each of those products.
query getProductsAndVariants {
products(first: 3) {
edges {
cursor
node {
id
title
description
handle
variants(first: 3) {
edges {
cursor
node {
id
title
quantityAvailable
price {
amount
currencyCode
}
}
}
}
}
}
}
}
Get product by handle
This query gets a single product connection, available from the QueryRoot, that matches the handle "my-test-product". As only one product connection will be returned, we don't need to specify edges, node, or cursor. This query can also be used to get a product by id by replacing (handle: $handle) with (id: $id)
query getProductByHandle {
product(handle: "my-test-product") {
id
title
description
variants(first: 3) {
edges {
cursor
node {
id
title
quantityAvailable
price {
amount
currencyCode
}
}
}
}
}
}
Get product recommendations
This query gets a single product connection, available from the QueryRoot, that matches the base64-encoded id of the product. As only one product connection will be returned, we don't need to specify edges, node, or cursor.
query getProductRecommendations {
productRecommendations(productId: "gid://shopify/Product/123456789") {
id
title
description
variants(first: 3) {
edges {
cursor
node {
id
title
quantityAvailable
price {
amount
currencyCode
}
}
}
}
}
}
Get product selling plans
This query gets the first 30 products, the first 5 selling plan groups associated with them, and the first 5 selling plans within the groups. We use fragments to return the price adjustments for each selling plan.
query getProductSellingPlans {
products(first: 30) {
pageInfo {
hasNextPage
hasPreviousPage
}
edges {
cursor
node {
id
title
sellingPlanGroups(first: 5) {
pageInfo {
hasNextPage
hasPreviousPage
}
edges {
cursor
node {
appName
name
options {
name
values
}
sellingPlans(first: 5) {
pageInfo {
hasNextPage
hasPreviousPage
}
edges {
cursor
node {
id
description
recurringDeliveries
priceAdjustments {
adjustmentValue {
... on SellingPlanPercentagePriceAdjustment {
adjustmentPercentage
}
... on SellingPlanFixedAmountPriceAdjustment {
adjustmentAmount {
amount
currencyCode
}
}
... on SellingPlanFixedPriceAdjustment {
price {
amount
currencyCode
}
}
}
orderCount
}
options {
name
value
}
}
}
}
}
}
}
}
}
}
}
Get product media
This query gets 3 products and their media; we use a fragment here to specify the fields that we want to return for each possible media type. You cannot retrieve media for product variants with the Storefront API, only products. You cannot upload media, add media to a product, or delete media with the Storefront API, use the Admin API for these tasks. https://shopify.dev/tutorials/manage-product-media-with-admin-api#retrieve-product-media-by-using-the-storefront-api
query getProductMedia {
products(first: 3) {
edges {
cursor
node {
id
title
description
media(first: 10) {
edges {
node {
mediaContentType
alt
...mediaFieldsByType
}
}
}
}
}
}
}
fragment mediaFieldsByType on Media {
...on ExternalVideo {
id
host
originUrl
}
...on MediaImage {
image {
url
}
}
...on Model3d {
sources {
url
mimeType
format
filesize
}
}
...on Video {
sources {
url
mimeType
format
height
width
}
}
}
Get product tags
Returns product tags. This query requires the unauthenticated_read_product_tags scope, more info can be found here: https://shopify.dev/api/usage/access-scopes
query getProductTags {
productTags(first:10) {
edges{
node
}
}
}
Get product types
Returns product types. This query requires the unauthenticated_read_product_listings scope, more info can be found here: https://shopify.dev/api/usage/access-scopes
query getProductTypes {
productTypes(first: 10) {
edges{
node
}
}
}
Customers
Create an access token
The Storefront API allows access to a customer’s addresses, orders and metafields. To access customers, an app must have unauthenticated_read_customers access scope.
To query a customer, a customerAccessToken is required. This is obtained via the customerAccessTokenCreate mutation which exchanges a user’s email address and password for an access token.
mutation customerAccessTokenCreate($input: CustomerAccessTokenCreateInput!) {
customerAccessTokenCreate(input: $input) {
customerAccessToken {
accessToken
expiresAt
}
customerUserErrors {
code
field
message
}
}
}
variables
{
"input": {
"email": "[email protected]",
"password": "HiZqFuDvDdQ7"
}
}
Get customer orders
To query a customer, a customerAccessToken is required. This is obtained via the customerAccessTokenCreate mutation which exchanges a user’s email address and password for an access token.
query getCustomerOrders($customerAccessToken: String!){
customer(customerAccessToken: $customerAccessToken) {
id
orders(first:3) {
edges {
node {
orderNumber
}
}
}
}
}
variables
{
"customerAccessToken": "d794063da4e26c9b1a8d7b77bdfd6862"
}
Get customer metafields
To query a customer, a customerAccessToken is required. This is obtained via the customerAccessTokenCreate mutation which exchanges a user’s email address and password for an access token.
By default, the Storefront API can't read metafields. To make specific metafields visible in the Storefront API, you need to create a MetafieldStorefrontVisibility record. See metafields/expose_metafield_to_SFAPI query for more details: # https://github.com/Shopify/storefront-api-learning-kit/tree/main/examples/05_collections/05_get_all_metafields_for_namespace_in_collection
If you would like to know more regarding metafields, check out this dev doc #https://shopify.dev/tutorials/retrieve-metafields-with-storefront-api#expose-metafields-to-the-storefront-api
Identifiers are used to identify the metafields associated with the resource matching the supplied list of namespaces and keys.
To know more about metafields, please navigate to metafields directory of this repo to get more information.
query CustomerMetafields($customerAccessToken: String!, $identifiers: [HasMetafieldsIdentifier!]!){
customer(customerAccessToken: $customerAccessToken) {
id
email
metafields (identifiers:$identifiers) {
id
key
value
namespace
type
}
}
}
variables
{
"customerAccessToken": "7cd6d36137f41d57bb8e85ae0d178d60",
"identifiers": [
{
"namespace": "Membership",
"key": "VIP level"
},
{
"namespace": "Membership",
"key": "startDate"
},
{
"namespace": "note",
"key": "preference"
}
]
}
Update customer
To query a customer, a customerAccessToken is required. This is obtained via the customerAccessTokenCreate mutation which exchanges a user’s email address and password for an access token.
mutation customerUpdate($customerAccessToken: String!, $customer: CustomerUpdateInput!) {
customerUpdate(customerAccessToken: $customerAccessToken, customer: $customer) {
customer {
id
}
customerAccessToken {
accessToken
expiresAt
}
customerUserErrors {
code
field
message
}
}
}
variables
{
"customerAccessToken": "d794063da4e26c9b1a8d7b77bdfd6862",
"customer": {
"phone": "+61401425227"
}
}
Create customer
This mutation will create a customer account with password for the customer to login.
mutation createCustomerAccount($input: CustomerCreateInput!) {
customerCreate(input: $input) {
customer {
id
email
firstName
lastName
phone
}
customerUserErrors {
code
field
message
}
}
}
variables
{
"input": {
"acceptsMarketing": true,
"email": "[email protected]",
"firstName": "John",
"lastName": "Smith",
"password": "qwerty12345",
"phone": "+64213444048"
}
}
Activate customer
Once a customer account is created, an email will be sent to the customer with the account activation url. This mutation will use the activationToken from the activation url to active the customer account. You can also use the activation url directly to activate the customer account. See customerActivateByUrl mutation https://shopify.dev/api/storefront/2023-01/mutations/customerActivateByUrl
mutation activateCustomerAccount($id: ID!, $input: CustomerActivateInput!) {
customerActivate(id: $id, input: $input) {
customer {
id
email
firstName
lastName
phone
}
customerAccessToken {
accessToken
expiresAt
}
customerUserErrors {
code
field
message
}
}
}
variables
{
"id": "gid://shopify/Customer/5820694691862",
"input": {
"activationToken": "da48cbd301e7c31a9d5dca03fcf5cdb6-1671054502",
"password": "qwerty12345"
}
}
Recover customer
This mutation will send a email to customer to reset password of the customer account.
Note that this mutation is throttled by IP. if you are using authenticated access, you can pass a Shopify-Storefront-Buyer-IP header to enable the IP based throttling that will protect your app from any single user, such as a bot, consuming too much capacity.
mutation recoverCustomerAccount($email: String!) {
customerRecover(email: $email) {
customerUserErrors {
code
field
message
}
}
}
variables
{
"email":"[email protected]"
}
Reset customer
This mutation is used to reset the customer account password. After sending recoverCustomerAccount request, the customer will receive an email with an account recovery url for resetting customer account. This url will include the customer id and resetToken. You can also use the url directly to reset the customer account. See customerResetByUrl mutation https://shopify.dev/api/storefront/2022-10/mutations/customerResetByUrl
mutation resetCustomerAccount($id: ID!, $input: CustomerResetInput!) {
customerReset(id: $id, input: $input) {
customer {
id
email
firstName
lastName
phone
}
customerAccessToken {
accessToken
expiresAt
}
customerUserErrors {
code
field
message
}
}
}
variables
{
"id": "gid://shopify/Customer/5820694691862",
"input": {
"password": "12345qwerty",
"resetToken": "2279f05aebbb8319553e46f2b71c88c7-1671131136"
}
}
Create customer address
To query a customer, a customerAccessToken is required. This is obtained via the customerAccessTokenCreate mutation which exchanges a user’s email address and password for an access token.
This request will create a new address that appends to the current address array of the customer record.
mutation customerAddressCreate($customerAccessToken: String!, $address: MailingAddressInput!) {
customerAddressCreate(customerAccessToken: $customerAccessToken, address: $address) {
customerUserErrors {
code
field
message
}
customerAddress {
id
}
}
}
variables
{
"customerAccessToken": "7cd6d36137f41d57bb8e85ae0d178d60",
"address": {
"lastName": "Smith",
"firstName": "Mary",
"address1": "123 Test Street",
"province": "ON",
"country": "Canada",
"zip": "M5T1G4",
"city": "Toronto"
}
}
Manage a cart
Create a cart with one line item
This mutation creates a cart and returns information about the cart to ensure it's correct (id, lines, product variant id, etc) as well as some information about the cart you may want (e.g. cost, subtotalAmount, totalTaxAmount, totalDutyAmount). The checkoutUrl object contains the url of the checkout for the created cart
mutation createCart($cartInput: CartInput) {
cartCreate(input: $cartInput) {
cart {
id
createdAt
updatedAt
checkoutUrl
lines(first: 10) {
edges {
node {
id
merchandise {
... on ProductVariant {
id
}
}
}
}
}
attributes {
key
value
}
cost {
totalAmount {
amount
currencyCode
}
subtotalAmount {
amount
currencyCode
}
totalTaxAmount {
amount
currencyCode
}
totalDutyAmount {
amount
currencyCode
}
}
}
}
}
variables
{
"cartInput": {
"lines": [
{
"quantity": 1,
"merchandiseId": "gid://shopify/ProductVariant/123"
}
],
"attributes": {
"key": "cart_attribute_key",
"value": "This is a cart attribute value"
}
}
}
Query a cart
Query a cart by id and return some of the cart's objects. See documentation here for comprehensive list: https://shopify.dev/api/storefront/latest/queries/cart
query cartQuery($cartId: ID!) {
cart(id: $cartId) {
id
createdAt
updatedAt
checkoutUrl
lines(first: 10) {
edges {
node {
id
quantity
merchandise {
... on ProductVariant {
id
}
}
attributes {
key
value
}
}
}
}
attributes {
key
value
}
cost {
totalAmount {
amount
currencyCode
}
subtotalAmount {
amount
currencyCode
}
totalTaxAmount {
amount
currencyCode
}
totalDutyAmount {
amount
currencyCode
}
}
buyerIdentity {
email
phone
customer {
id
}
countryCode
}
}
}
variables
{
"cartId": "gid://shopify/Cart/50b74bf9dc2bc7a410053b5ffb31ba51"
}
Update line items
This mutation is used to add a product variant of the same type to the cart. In the below example, the quantity of the variant (in variables.json) is increased and the id and quantity are returned to confirm they are correct.
mutation updateCartLines($cartId: ID!, $lines: [CartLineUpdateInput!]!) {
cartLinesUpdate(cartId: $cartId, lines: $lines) {
cart {
id
lines(first: 10) {
edges {
node {
id
quantity
merchandise {
... on ProductVariant {
id
}
}
}
}
}
cost {
totalAmount {
amount
currencyCode
}
subtotalAmount {
amount
currencyCode
}
totalTaxAmount {
amount
currencyCode
}
totalDutyAmount {
amount
currencyCode
}
}
}
}
}
variables
{
"cartId": "gid://shopify/Cart/50b74bf9dc2bc7a410053b5ffb31ba51",
"lines": {
"id": "gid://shopify/CartLine/7b9ed49f-830e-4142-9c81-e7f8249863ad?cart=50b74bf9dc2bc7a410053b5ffb31ba51",
"quantity": 3
}
}
Update buyer identity
cartBuyerIdentityUpdate is used to associate customer info with a cart and is used to determine international pricing. The below example is updating the buyerIdentity and returning the info (email, phone, delivery address preferences) to ensure that it updated correctly
mutation updateCartBuyerIdentity($buyerIdentity: CartBuyerIdentityInput!, $cartId: ID!) {
cartBuyerIdentityUpdate(buyerIdentity: $buyerIdentity, cartId: $cartId) {
cart {
id
buyerIdentity {
email
phone
deliveryAddressPreferences {
... on MailingAddress {
address1
city
country
firstName
lastName
}
}
}
}
userErrors {
field
message
}
}
}
variables
{
"buyerIdentity": {
"countryCode": "CA",
"deliveryAddressPreferences": [
{
"deliveryAddress": {
"address1": "123 Fake St.",
"city": "Toronto",
"company": "Shopify",
"country": "Canada",
"firstName": "Alice",
"lastName": "Bob",
"province": "ON"
}
}
],
"email": "[email protected]"
},
"cartId": "gid://shopify/Cart/684d5f8c6e463f6057e77c15e34082f0"
}
Retrieve checkout url
Query gets cart by id and returns the cart's checkoutURL. That url directs you to the web checkout flow. More info here: https://shopify.dev/custom-storefronts/checkout/create#shopify-web-checkout
query checkoutURL($cartId: ID!) {
cart(id: $cartId) {
checkoutUrl
}
}
variables
{
"cartId": "gid://shopify/Cart/50b74bf9dc2bc7a410053b5ffb31ba51"
}
Update cart discount codes
This mutation updates the discount codes applied to a given cart and returns the cart id and discountCodes' 'code' and 'applicable' fields
mutation updateCartDiscountCodes($cartId: ID!, $discountCodes: [String!] ) {
cartDiscountCodesUpdate(cartId: $cartId, discountCodes: $discountCodes) {
cart {
id
discountCodes{
code
applicable
}
cost {
totalAmount {
amount
currencyCode
}
subtotalAmount {
amount
currencyCode
}
totalTaxAmount {
amount
currencyCode
}
totalDutyAmount {
amount
currencyCode
}
}
}
userErrors {
field
message
}
}
}
variables
{
"cartId": "gid://shopify/Cart/50b74bf9dc2bc7a410053b5ffb31ba51",
"discountCodes": [
"10_OFF"
]
}
Update cart attributes
Updates the attributes of a given cart. Cart attributes are used to store info that isn't included in the existing cart fields. The variables for this mutation provide an example of such a use case i.e. "attributes": { "key": "gift_wrap", "value": "true" } The key/value can be passed as an object or objects in an array, but in either case the update overwrites the existing attributes.
mutation updateCartAttributes($attributes: [AttributeInput!]!, $cartId: ID!) {
cartAttributesUpdate(attributes: $attributes, cartId: $cartId) {
cart {
id
attributes{
key
value
}
}
userErrors {
field
message
}
}
}
variables
{
"attributes": {
"key": "gift_wrap",
"value": "true"
},
"cartId": "gid://shopify/Cart/50b74bf9dc2bc7a410053b5ffb31ba51"
}
Update cart note
Updates cart note, returns cart id and note. Notes are similiar to cart attributes in that they contain additional info about an order. However, notes can be a string whereas attributes require key/value pairs.
mutation updateCartNote($cartId: ID!) {
cartNoteUpdate(cartId: $cartId) {
cart {
id
note
}
userErrors {
field
message
}
}
}
variables
{
"cartId": "gid://shopify/Cart/50b74bf9dc2bc7a410053b5ffb31ba51",
"note": "This is a test note"
}
Remove cart lines
Remove lines from existing cart. Use the cost, subtotal, etc or userError message to confirm that the correct line has been removed. The userError message will let you know if the line in the request does not exist.
mutation removeCartLines($cartId: ID!, $lineIds: [ID!]!) {
cartLinesRemove(cartId: $cartId, lineIds: $lineIds) {
cart {
id
lines(first: 10){
edges
{
node{
quantity
merchandise{
... on ProductVariant {
id
}
}
}
}
}
cost {
totalAmount {
amount
currencyCode
}
subtotalAmount {
amount
currencyCode
}
totalTaxAmount {
amount
currencyCode
}
totalDutyAmount {
amount
currencyCode
}
}
}
userErrors {
field
message
}
}
}
variables
{
"cartId": "gid://shopify/Cart/50b74bf9dc2bc7a410053b5ffb31ba51",
"lineIds": [
"gid://shopify/CartLine/7b9ed49f-830e-4142-9c81-e7f8249863ad?cart=50b74bf9dc2bc7a410053b5ffb31ba51"
]
}
Add cart lines
This mutation adds lines to existing cart, returns the quantity and product id. This mutation also accepts sellingPlanId
mutation addCartLines($cartId: ID!, $lines: [CartLineInput!]!) {
cartLinesAdd(cartId: $cartId, lines: $lines) {
cart {
id
lines(first: 10){
edges
{
node{
quantity
merchandise{
... on ProductVariant {
id
}
}
}
}
}
cost {
totalAmount {
amount
currencyCode
}
subtotalAmount {
amount
currencyCode
}
totalTaxAmount {
amount
currencyCode
}
totalDutyAmount {
amount
currencyCode
}
}
}
userErrors {
field
message
}
}
}
variables
{
"cartId": "gid://shopify/Cart/e623277ec9e65c98f583268f06900ce7",
"lines": {
"merchandiseId": "gid://shopify/ProductVariant/40993523892280",
"quantity": 3
}
}
Shop content
Get shop policies
The ShopPolicy object represents a policy that a merchant has configured for their store, such as their refund or privacy policy.
This query displays the different shop policies that can be returned using the Storefront API.
query getShopPolicies {
shop {
privacyPolicy {
id
body # Policy text, maximum size of 64kb.
title
}
refundPolicy {
id
body
title
}
shippingPolicy {
id
body
title
}
termsOfService {
id
body
title
}
subscriptionPolicy {
id
body
title
}
}
}
Get blog by handle
The blog object is an blog published to the online store channel.
Each store can have multiple blogs, and each blog can have many articles (blog posts).
This query fetches a specific blog by it's handle and returns the blog along with it's associated articles.
Blogs are meant to be used as a type of magazine or newsletter for the shop, with content that changes over time.
If your shop needs a static page (such as an "About Us" page), we recommend that you use a Page instead.
query getBlogByHandle($handle: String!) {
blog(handle: $handle) {
id
title
articles(first: 5) {
edges {
node {
id
title
}
}
}
}
}
variables
{
"handle": "my-blog"
}
Get page by handle
The page object represents a custom page on the online store.
Shopify merchants can create pages to hold static HTML content such as an 'About Us' page.
This simple query fetches a page by it's handle and returns the title and description of the page, complete with HTML formatting.
query getPageByHandle($handle: String!) {
page(handle: $handle) {
id
title
body # The description of the page, complete with HTML formatting.
}
}
variables
{
"handle": "my-page"
}