31
loading...
This website collects cookies to deliver better user experience
storefront access token
which is available on the Shopify admin section of your app. To authenticate a request, pass this in the header of your API calls:headers: {
"Content-Type": "application/graphql",
"X-Shopify-Storefront-Access-Token": process.env.SHOPIFY_STOREFRONT_ACCESS_TOKEN,
}
Before we go any further, it's worth mentioning that the Storefront APIs are completely GraphQL based. There's no REST alternative so all the sample snippets we'll use here will be in GraphQL.
{
products(first:5) {
edges {
node {
id
}
}
}
}
products
field. Without any arguments, this will return all the products available in your store. However, we've specified that we want only the first 5 products by providing the first
argument to the products
query.Next.js
or Nuxt.js
? what would it look like. In my case, I'm working on a Gridsome project, so i'll go into the gridsome.server.js
file and write this Query:const fetch = require("node-fetch");
module.exports = function(api) {
api.loadSource(async actions => {
const query = `{
products(first: 10) {
edges {
node {
id
handle
description
title
images(first: 1) {
edges {
node {
src
altText
}
}
}
}
}
}
}`;
const response = await fetch(process.env.SHOPIFY_STORE_URL, {
method: "post",
headers: {
"Content-Type": "application/graphql",
"X-Shopify-Storefront-Access-Token":
process.env.SHOPIFY_STOREFRONT_API_TOKEN
},
body: query
})
.then(res => res.json())
.then(data => console.log(data));
});
};
variants
, collections
, etc., depending on your needs. I've kept it minimal to keep the snippets neat and readable. You can find the rest of this file here if you'd like a more comprehensive look.Collection
and pass the product data into the Collection like this:const collection = actions.addCollection({
typeName: "Product"
});
for (const product of productData) {
collection.addNode({
id: product.id,
title: product.title,
handle: product.handle,
description: product.description,
images: product.images.edges[0].node.src,
altText: product.images.edges[0].node.altText
});
}
this.$page.product
. This way, we can use it in all the places we need it within the Gridsome app.{
node(id: "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzMTA2NzM0MzA=") {
id
... on Product {
title
}
}
}
{
"data": {
"node": {
"id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzMTA2NzM0MzA=",
"title": "Aged Gruyeye"
}
}
}
Add To Cart
on your site).id
of the selected product and its quantity
. Consider this mutation:const { postToShopify } = require("./postToShopify");
// Create a cart with a single item
exports.createCartWithItem = async ({ itemId, quantity }) => {
try {
const response = await postToShopify({
query: `
mutation createCart($cartInput: CartInput) {
cartCreate(input: $cartInput) {
cart {
id
createdAt
updatedAt
lines(first:10) {
edges {
node {
id
quantity
merchandise {
...
}
}
}
}
estimatedCost {
totalAmount {...}
subtotalAmount {...}
totalTaxAmount {...}
totalDutyAmount {...}
}
}
}
}
`,
variables: {
cartInput: {
lines: [
{
quantity,
merchandiseId: itemId
}
]
}
}
});
return response;
} catch (error) {
console.log(error);
}
};
postToShopify
import is, it's a utility function we use to make requests to Shopify, also available here.Here's something I missed that took a while to figure out. The product id
i.e the itemId
in the snippet above is not the product's ID (product.node.id
) as you'd think. Instead, it's the ID of the selected product variant. If the product has no variants, the variants
field will still be available in the product data with one item. And you can access it with product.variants[0].node.id
. This is the ID you should be adding to the cart (or using to create a cart).
cartId
which is returned in the first call to create a cart,id
of the product you're adding to the cart andquantity
.cartId
:const { postToShopify } = require("./postToShopify");
exports.addItemToCart = async ({ cartId, itemId, quantity }) => {
try {
const shopifyResponse = postToShopify({
query: `
mutation addItemToCart($cartId: ID!, $lines: [CartLineInput!]!) {
cartLinesAdd(cartId: $cartId, lines: $lines) {
cart {
id
lines(first: 10) {
edges {
node {
id
quantity
merchandise {
...
}
}
}
}
estimatedCost {
totalAmount {...}
subtotalAmount {...}
totalTaxAmount {...}
totalDutyAmount {...}
}
}
}
}
`,
variables: {
cartId,
lines: [
{
merchandiseId: itemId,
quantity
}
]
}
});
return shopifyResponse;
} catch (error) {
console.log(error);
}
};
cartId
variable and then add the selected product to it as a line item. Again, the snippet is truncated so the whole file is available here.lineId
) of the line item (product variant) you want to get rid of and the ID of the cart (cartId
) you want to remove it from and it'll be done. Here's how:const { postToShopify } = require("./postToShopify");
exports.removeItemFromCart = async ({ cartId, lineId }) => {
try {
const shopifyResponse = await postToShopify({
query: `
mutation removeItemFromCart($cartId: ID!, $lineIds: [ID!]!) {
cartLinesRemove(cartId: $cartId, lineIds: $lineIds) {
cart {
id
lines(first: 10) {
edges {
node {
id
quantity
merchandise {
...
}
}
}
}
estimatedCost {
totalAmount {}
subtotalAmount {}
totalTaxAmount {}
totalDutyAmount {}
}
}
}
}
`,
variables: {
cartId,
lineIds: [lineId]
}
});
return shopifyResponse;
} catch (error) {
console.log(error);
}
};
lineId
specified in the request from the cart whose cart ID equals the cartId
specified in the request.Here's the live site I built in this process to give you a general idea of how it all works together.
If you're keen on getting your hands on the source code, it's also available here on Github