This is a complimentary blog post to a video from the ShopifyDevs YouTube channel. In this article, Chuck Kosman, a Launch Engineer at Shopify Plus, walks you through an introduction of using GraphQL with Shopify. We cover:
- What GraphQL is
- What tools you can use to get up and running with GraphQL
- A tutorial of making GraphQL requests against a client’s store
What is GraphQL?
Let's start by answering the question, what is GraphQL? If you were to go to GraphQL.org, you'd find this quote right at the top. GraphQL is described as, “A query language for APIs and a runtime for fulfilling those queries with your existing data.”
"GraphQL is described as, 'A query language for APIs and a runtime for fulfilling those queries with your existing data.'"
Query languages are expressive, highly structured ways to ask for data, and you might be familiar with them in the context of databases.
Here, we're talking about using query languages for an API. If we were to translate this into a more functional definition, you'd end up with something like this: “GraphQL is an expressive, structured way to ask for data from another application and the underlying system to fetch that data.”
You're probably familiar with RESTful APIs as a way to ask for data from another application. But GraphQL is really being hailed as the better REST. REST solved a lot of problems of its predecessors, but GraphQL is specifically designed to address some of the shortcomings of REST when it comes to modern applications. One of the principal problems with REST in modern applications is that they overfetch or underfetch. This means that in a single request, they either get too much data or they don't get enough.
Let’s use a restaurant, something that's long been used as an analogy for APIs, to explore these concepts a little further.
Build for the world’s entrepreneurs
Want to see more videos just like this? Subscribe to the ShopifyDevs YouTube channel. Get development inspiration, useful tips, and practical takeaways.
SubscribeThe ice cream analogy: exploring concepts relating to APIs
I'm going to use an ice cream shop as my restaurant here and I'm going to start with overfetching.
On Shopify, if I wanted to know something about an order, I would have to use this end point on the admin REST API, and when I plug in an order ID to it, I get everything I could ever want to know about a single order.
In terms of a restaurant or an ice cream shop specifically, this might be an ice cream truck that only has preconfigured sundaes on the menu that contain ingredients that you don't necessarily want and there's no combination that you really do want. The restaurant has put all of this time and effort into putting the toppings on and arranging things as they specified that they would. But, if there's something that your client doesn't like or need, then it's on you to remove those. This can be quite inefficient for both parties.
In contrast, underfetching is when you don't get enough data from a single request. This often comes up when you're looking for deeply nested data.
Here's an example in Shopify where I went to get at the metafields of a certain set of products. I first start by issuing a GET
request to all products. But that's not all the data that I really need.
Then I had to go use a different endpoint, plug in the IDs, and then finally get to the metafields that I want. You may have heard this characterized as the n+1
problem. I issued one request to get the entire list of products and then I have to issue n
number of requests to get at each resource that I'm interested in at the end. So in terms of our ice cream shop analogy, this might be something like where I get some ice cream and each time I want a topping, I have to pass the ice cream back and forth and I can only get one topic at a time.
Very inefficient, very inflexible.
You might also like: How to Get More App Downloads in the Shopify App Store.
Enter GraphQL. You supply the query language data that you would like along with your request and you get back only the data that you ask for. What's interesting here is you'll notice that I'm using a POST
request to this end point on the admin/API/GraphQL.json
, and along with it I'm supplying a body of this nested structure of data. This particular nested structure of data is a pseudocode example of asking for some fields on products by a particular product ID.
So in this case, let's say I only wanted to examine the title
, handle
, and then variants
fields belonging to products that I might be interested in. I could populate them in the ...
as shown below. What I get back ends up being only the data that I asked for.
In the context of our ice cream shop analogy, I would go up to the counter, I specify exactly what flavors and toppings I want, and I get exactly that in one efficient, flexible request.
Because I specify exactly what data I want in each request, it's clear to both the server, that which is filling the query, and the client, myself, my colleagues, and the rest of the application, what data is being used. This is very advantageous for clarity and moving fast. It enables rapid front end iteration because there's only one single endpoint. I don't have to juggle a bunch of different endpoints as a front end developer, and it's how I structure my request that dictates what data I get back, not what endpoints I have to call in sequence.
Lastly, you might be wondering, well, if there's only one endpoint, how do I know what I can even ask for?
This is really the heart beat of GraphQL, this transparent documentation of its capabilities through what's called a schema. We specifically call it a strongly-typed schema, meaning that the patterns of data that you get back are defined by underlying types. And so it's very clear, even as you're typing or formatting your request if you're making an error or not.
Ultimately, all of these things lead to a more efficient, powerful, and flexible successor to REST.
Tools to start making GraphQL requests with Shopify
Now that we know a little bit about what GraphQL is and how it compares to REST, let's start talking about the tools that you can use to start making GraphQL requests on Shopify.
It could be as simple as a cURL
request, but you'd miss out on this strongly-typed schema, one of the most powerful features of GraphQL. However, we can get that using something called the GraphiQL IDE or Integrated Development Environment. We have an implementation of this for both the GraphQL admin API and the storefront API. We'll talk about the distinction between those in a moment, but we're going to stick with the admin API implementation.
What you’ll need to get started
There is a piece of documentation called the Shopify Admin API GraphiQL Explorer. You can actually start playing around with it as read only right here in the documentation, but if you'd like to follow along in this tutorial, I'm going to suggest that you install Shopify's GraphiQL app.
You'll need a store to install this on, so if you don't already have a partner development store or a trial store, no worries. There's great documentation on exactly how to do this. If you need to get a store up and running on which to install it, there's another piece of documentation called Make Your First GraphQL Request in our Shopify dev tutorials.
And right at the top, there's only two steps that you need to follow of these three. One is creating a partner account. These are what folks in our ecosystem use to make merchant solutions. It's totally free.
With that partner account, you will create a development store or log into an existing one if you have one. We won't need this last part for our tutorials using GraphiQL, but you could optionally follow along here if you prefer to work with a standalone HTTP client. And we'll see what that looks like as well in a moment.
So if you don't have a store, get one, and I highly suggest populating some test data so that when you go to make queries, you're going to get some meaningful data back. You could stick with products and variants, but you can go as far as products, customers, and orders if you so desire. Those are kind of the big three.
The Shopify GraphQL Integrated Development Environment (IDE)
Anyway, I'm going to go back to this Shopify Admin API GraphiQL Explorer and I'm going to install it on a store that I already have set up. I'm going to say install Shopify's GraphiQL app following this link. I happen to have a store already, getting-started-with-graphql.myshopify.com
, and I'm going to select that from my browser's autocomplete here.
And this is where you're going to define what scopes this app has access to. If you know the store isn't being used for production, you can safely select all of the scopes. If this is already a production store, I highly suggest you use a development or test store instead, and be very careful, because this app can read and write. So be cautious in selecting your selected scopes.
For this tutorial, you'll really only need products in terms of what I'm going to show, so I'm going to say Select All because it makes things easier and I'm going to say Install. It's going to prompt me to say, “Do you want to grant this app all of these different scopes?” I'm going to say Yes.
Once it's finished installing, you'll see an interface like this, a left hand column with this shop name JSON formatted thing and this right-hand column that's blank for now. We'll be using this for the tutorial, but we'll flip back to other methods of working with GraphQL just for the time being.
You might also like: Faster Retrieval of Shopify Metafields with GraphQL.
The standalone HTTP client
You could also use, as I mentioned, a standalone HTTP client. The reason that we're using the GraphiQL IDE for this tutorial is we don't have to specify the endpoint. Fortunately, there's only one in GraphQL, that's one of its wonderful advantages.
But we don't also have to set up the headers either. I'll show you what those headers look like if this is your preferred method of working. You’ll need two headers. You'll need to spin up a private app and you'll need that app's password to pass in as the authentication token under this header name. You’ll also need to specify the content type as application/JSON
.
There is an application/GraphQL
that some folks get confused about. There are subtle differences and you'll usually want to use application/JSON
when working with a standalone HTTP client. If it doesn't work, switch to application/GraphQL
. If you need any more guidance on this, you forgot where the slide was, or you want to read this full-on, refer back to that Make Your FirstGraphQL Request piece of documentation. They cover using GraphiQL and in addition to that, they cover using a standalone HTTP client.
There's actually a really awesome blog post for a full tutorial on setting up one called insomnia. And there's a kit that comes with some preloaded queries that you can start using to get up and running right away. The headers that you'll need and some sample requests are detailed throughout this document. So this is an excellent resource to come back to after this tutorial.
We're going to walk through some elements of this, as well. Last but not least, if you start working at scale, the GraphQL IDE is not going to work for you, this is really just kind of a way to test things. And you wouldn't use a HTTP client to do things in production either, you'd build on a full-on app.
Working at scale: building with GraphQL client libraries
When you go to build a full-on app, I highly recommend looking into GraphQL client libraries. Because of the predictability that comes out of this strongly-typed schema of GraphQL, you can layer a lot of developer tools on top of that for rapid and awesome development. You may have heard of Apollo or Relay as popular client libraries, but there are others and it depends on what languages, frameworks, and platforms you're targeting.
"Because of the predictability that comes out of this strongly-typed schema of GraphQL, you can layer a lot of developer tools on top of that for rapid and awesome development."
I briefly touched on that there are two different APIs that you might work with using GraphQL. They are the admin APIs, both REST and GraphQL. Both are used for developing apps and integrations for the Shopify admin. It’s like extending the back office of Shopify, if you want to think of it that way. However the storefront API is for customer-facing purchase experiences, a very different purpose.
And we have software development kits or SDKs to target the web, Android, iOS, and even in-game experiences via Unity. In addition to the fact that GraphQL is the only one available
for storefront-to-storefront API, there are clearly advantages of using GraphQL over REST. In fact, there are certain things you can do using the GraphQL flavor of the admin API that you can't do on the REST API.
In other words, Shopify is really betting on GraphQL. We see the benefits of GraphQL in comparison to RESTful APIs.
What you can accomplish with GraphQL admin APIs
In the past, and continuing now and in the future, there will be certain things that you should expect you can only do on the GraphQL admin API. Some of those listed out here in chronological order of their release:
- There's a way to bulk adjust inventory on the GraphQL admin API that is many, many more times efficient than the REST API could ever be on the same operation. This is really good for inventory management at scale.
- The translations API is GraphQL only.
- Product media, so being able to not just do images but videos and 3D models, is GraphQL.
- Order editing, a long requested feature, is GraphQL only on the admin API.
- As of this post, the duties and taxes APIs and developer preview are GraphQL as well.
You should expect that there absolutely will be more features that will be only on GraphQL in the future. You can check these out on our developer changelog if you want to stay up to date with our Shopify API releases.
You might also like: GraphQL vs REST: How One Shopify Partner Increased Performance and Reliability.
Applying your knowledge: using GraphQL with Shopify
Now that we've got our tools in place, let's start making requests to our client’s Shopify store using the GraphiQL IDE. I'm going to flip over to my store here in the browser, right where I left off with the GraphiQL IDE installation and you should see something that looks a little bit like this:
The first thing I'm going to do here is actually going to format this a little bit more nicely, in order to make it look a little bit more like how folks tend to work with this:
{
shop {
name
}
}
You can see that the query language of GraphQL, even just from this starter example here, looks a little bit like a nested structure of JSON. I'm just going to press Play. This is how I'm going to say, “Send a request”, essentially to get at what I need. So I’m going to click Execute query, and what I get back is JSON with two properties.
One is called data
, and you'll notice that the structure of the data that comes back exactly mirrors the request format that I put in. So I have a shop
property, and the value of that property is an object, and that object has one key called "name"
that I've requested and it so happens that my shop name here is "Getting Started with GraphQL"
.
This extension is actually talking to us about how much this query costs. If you've worked with Shopify's APIs before, particularly the REST API, you know that there is a cap on how many requests you can issue at any given time and how fast those requests leak from this bucket. We call it a leaky bucket model.
GraphQL does have the same limitations, but it is through the cost of the query itself, not the call. The end result of this is that GraphQL ends up being way more efficient.
Remember that overfetching example? There's a lot of computation going on in the background of things that you may not necessarily need. GraphQL is computing the cost of what you requested just based on what you requested, so it is massively more efficient. What else can I query for here?
I can press Enter and start typing any letter, say C
for currency code. As soon as I do this, I get an autocomplete of the things that I can query for on shop
. I'll be more specific, they're not just things, we call them fields. A field is just the data that you're interested in.
The reason that GraphiQL can do this is because of this strongly-typed schema. It knows the capabilities of the API and it knows exactly what fields belong on which nodes. We'll talk about nodes in just a second here.
If I were to say, tell me about the currency code of the shop and I press play again, there I have currency, I have to set up the store in USD.
Beyond just typing in autocomplete, how do I know what the capabilities of this API are? What is this schema that we've been talking about that's strongly-typed? In this GraphiQL IDE and in standalone HTTP clients that have good GraphQL capabilities, you'll see something that either looks like docs, in this particular instance, or schema.
This tells me exactly what I can do, and it starts out a little bit mysterious at first if you're new to GraphQL.
There's two things I can do at the most basic level. I can:
- Read data, which is a query.
- I can make a mutation. A mutation is for writing operations.
Comparing this to CRUD architectures in REST, reading is all that a query does. Mutations are everything else; that's creating, updating, and deleting.
Querying data with GraphQL
Now, if I omit the word query
, I'm implicitly making a query. So if I actually type in query
here and press play, I'll get the same exact thing. We're making queries to start and we'll move on to mutations in a bit.
The next question becomes, “How do I know that shop
is something that I can get from the QueryRoot
?” In other words, my entry point into querying for data. That's the QueryRoot
.
I can explore the schema to get exactly that. A query always returns a type of QueryRoot
. If I click on QueryRoot
, there's a lot of information here. There's a lot of things I could query, and this is the schema. This is the thing that defines what I can and can't query
for. It's in alphabetical order. Let’s scroll all the way down to S for shop
. This is the schema's definition of shop
. It says, “Returns a shop
resource corresponding to the access token used in the request.” I haven't actually explicitly supplied an access token, that's kind of the beauty of using GraphiQL.
So, what does this mean when it comes to a schema? What does shop:shop!
mean?
It means that if I were to query for a shop
field, I will get a type
back as denoted by Shop
. That's how I know what fields I can query for underneath Shop
. The exclamation point means non-nullable, I have to get something back.
So, how do I know that name and currency code are available on Shop
?
If I click on the Shop
type, these are all the things that I can get on Shop
. If I were to scroll down, there's quite a lot. This is where I got currency code. What does currency code return? It returns a currency code type (CurrencyCode
). What does name
return? name
returns a string.
This is the power of GraphQL's strongly-typed schema and the tools that reside on top of it.
I can explore the scheme in real time to see exactly what I can get at. And I know exactly, very predictably what data I can and can't get and what format it's going to be as I explore around. For most purposes, you might use Shop
every now and then in production, but you want to start really digging into some of the data entities on the store.
Let’s do an example with products.
You might also like: The Shopify App CLI Tool: Build Apps Faster.
A query example with products
I'm going to structure my query as I go, and compare it to the schema just so
that you can see what's going on. I’ll also take a look at a visualization of how to mentally model these types related to one another in the schema.
I'm going to get rid of query
because getting rid of the word query
actually implicitly makes a query. Go ahead and get rid of everything, making sure to preserve the curly braces. I'm in QueryRoot
here, so I'm going to probably be interested in products
.
OK, so products
is a little bit more complicated.
I have the field products
and then I have this parentheses to say first
, after
, last
, before
, sortKey
, all this stuff. Eventually, it says I get returned a type called ProductConnection
.
There’s a lot of terminology here, so let's start from the ground up.
If I use products
here and autocomplete already knowing that products
is something I can query for on the QueryRoot
. I'm going to open the curly braces again. It's expecting something else here. Well, what do we want on products
?
Let's say, I wanted their title
. Oh, weird. As soon as I typed title
, that's not something that's coming up. So, what's going on here?
If I press play, the fields
title doesn't exist on product connection, thank you, strongly-typed schema. That’s awesome. But, it's something on ProductConnection!
called edges
pops up, and I get an array of [ProductEdge!]!
s. So, let’s just start with that, edges
. OK, that's going to have some fields on it, so I'll click on [ProductEdge!]!
to see what exactly that does.
There’s a cursor
and a node
and it seems like node
returns a product
type, so that's probably what I want. And then on node
, these are probably things you're more familiar with on product
types. Let’s say I just want the ID
and the title
.
I'll press play and I'm going to get an error: you must provide one of first or last
.
OK, so what does that mean? It's expecting something on products
to qualify first
or last
. Again, with strongly-typed schema, it's very informative.
What is first
or last
? Just like in REST, you can't get every single list product just by issuing the get all products endpoint, it's actually paginated. We use cursor based pagination at the recommendation of the GraphQL specification.
That aside, let's take a look at how to do this. To supply what's called an argument, so a qualifier on a request, you must open parentheses. It's actually already saying, “Here are the different ones that you can do”. I'm just going to do the simplest possible one of saying I want the first
. What is the first
? Well, I have to provide an integer. So I'm going to say I want the first 10 products. We’ll ignore the edges
and node
thing in the middle for now, but we'll get into it in just a moment.
If I press play, now we've got really interesting stuff. We have data
, which returns an object with the products
property. This, in turn, returns an object of edges
, which is an array of objects, each containing a node
object and eventually, the data that I requested. So I have just the ID
and the title
in each product.
How much does that cost? It costs 12 points.
What does that mean? Well, in GraphQL you have a maximum bucket size of 1,000 points and that replenishes at 50 points per second.
Contrast this to 40 API REST calls that you can have in a bucket on the RESTful API that regenerates at two calls per second. The net result: GraphQL is way more efficient than REST, even without all the other goodies on top of this.
GraphQL: exploring the terminology
Let’s come back to this weird edges
and node
terminology. What is that? When we talk about GraphQL, we're talking about, for the sake of the API, modeling your data as a graph, a visual representation of how different pieces of data connect to one another.
So, let's talk a little bit about GraphQL terminology and how it's going to help you navigate your work.
As soon as you start working with lists of things, you're going to run into edges
and node
s all the time. Let’s just back up a step and talk about what those are.
This is essentially a stripped down version of the query that I just wrote: both the code over here and a visual representation of what's going on. I'm entering at the QueryRoot
and attaching that QueryRoot
to our products. Those products have properties on them. I'm querying for title
. In graph theory, these individual entities are what we call nodes
and we call the relationships between entities edges
.
This is why when I go at the root level and I want to know about products
, I have to say, “Get me all of the relationships to products
.” I'm saying get me all of the edges
. Then, at the ends of those edges
, tell me about the entities at the ends of those edges
. Those are node
s.
You'll see all the time when you start working with plural requests, such as getting a list of things, you'll get in the habit of saying edges
, node
, and then getting the thing at the end.
Let’s take this a step further: deeply nested queries. We talked about underfetching before, so let's say I want all of the variants on these first 10 products as well. It just so happens that if I type the letter V
, variants
is something on here. There's a list of variants
that correspond to products
. I know that I'm going to have to say first
, so I'll just say 10 again arbitrarily.
That returns a list of edges
, and at the end of those edges
, there's the variant node
. Let’s say you want the ID
and the title
of those variants. I'll press play again. Awesome. Again, the structure of the data that comes back exactly mirrors the structure of the data how I requested it.
So, I have data and then products
comes back as an object and edges
as an array. Each node has the ID
in the title as requested and all of the variant information, but only what I requested: just the ID
and title
of each variant. I could extend this with price
and so on by looking at the schema to see what data is available on variants.
Just flipping back to this mental model, all that I've done is I've taken the same request and I've extended it a little bit.
Products have a relationship to variants and product nodes have a relationship to variant nodes. Any time there's a relationship in a graph model, we call that an edge. That’s the line between the two. Each product has some variants at the end of it. In this case, I'm only saying two, just for the sake of making the diagram a little bit shorter.
To go back to our visual depiction of what we did here by adding variants under products, we started here with getting the product nodes attached to this QueryRoot
.
We know that there's a relationship between variants
and products
. So inside of this product node, there is a variants
connection. And all that a connection means in GraphQL is a list of edges
. An edge
is a relationship between two nodes
. At the end of that edge
is the node
that has the fields in question that I want to get here.
These product nodes
are related to variant nodes
. The line represents an edge
and those variants
in turn have titles on them. So any time you see the word connections, just keep in mind you'll need to think of edges
and nodes
to abide by this underlying model for the API of what's actually going on.
You might also like: Developing Your First Shopify App: 4 Mistakes to Avoid.
Writing data with mutations in GraphQL
So, we've covered querying data. That's half of the equation. We also want to be able to write data.
This was a query, implicitly, if you leave out the word query
here right at the top, it's a query. We actually need to write the word mutation
.
If I back up through the schema all the way to the root, I can query
and I can make mutation
s. Let's investigate what types of mutation
s I can make. mutation
s, as we covered, cover everything for writing data. That's creating, canceling, updating, deleting.
The way that we name our mutation
s in Shopify is we talk about the thing that the mutation
is being made on to start and then the actual operation that's taking place there. Without scrolling alphabetically through this, I'm going to type in the letter P
. It knows and you can see there's productCreate
, productDelete
, and productUpdate
. So, I'm going to say productCreate
.
I can scroll through this schema on the right hand side alphabetically or I can hover over this with my mouse and then just click on this name down here, and it will quick-jump you to the definition of this mutation
, which is very handy.
Now, what's going on here? This is saying that when you make this mutation
, you'll get a ProductCreatePayload
back. There are a couple of arguments that are supplied as part of this mutation
. If you're familiar with the REST API, when you make a product
, the response is all the information you could ever want about that newly created product.
Just like with queries, I can specify only the data that I want back. I have to say product
first and then the stuff you'd expect, created at, description
, title
, and so forth. More important here are the arguments. This is saying that this product input type is not nullable by the exclamation point. So, I have to provide that. media
is an array of this non-nullable CreateMediaInput
type. However, the array itself is not non-nullable, so I don't have to provide that. In other words, all I need to provide is this ProductInput
.
As with all arguments, I'm going to open a set of parentheses. I'm going to format this as an object. I'm also going to create a title
on this product called "Awesome Product"
. I'm going to open up that mutation
to receive the ProductCreatePayload
, which has a field on it called product
. Inside of that product
is where I can get all the good stuff. I'm going to say I want the ID
and then just to make sure, I'm going to say I want the title
. I'll make this mutation
by pressing play and you'll notice the ID
if you've worked with the REST API before.
This is a little bit different, the ID
s are not interchangeable. GraphQL has its own set of ID
s to refer to nodes
. Don't try to use the ID
s interchangeably and indeed, I get "title": "Awesome Product"
back.
Going further with GraphQL
Congratulations! That's getting up and running with making both queries and mutations on a Shopify store with GraphiQL. So, where do you go from here to expand your knowledge set on GraphQL?
There are many fantastic resources out there on the web for learning about GraphQL. Some of them are published by Shopify and I've called out through this tutorial, notably our tutorial and making your first GraphQL request. This is an excellent resource to come back to, especially after watching this tutorial. The mutations and queries that you'll make in that tutorial are a little bit different, but the principles are the same.
"There are many fantastic resources out there on the web for learning about GraphQL."
Shopify's GraphQL learning kit is a great place to start if you want to get up and running with a standalone HTTP client. As part of that blog post, there's a discussion of GraphQL as well as a downloadable set of preconfigured insomnia queries and mutations to start working with against a store. You'll just have to populate a private app key.
If you're interested in the storefront API SDKs and how they can make working with the storefront API even faster. You can check out our Storefront API Tools Library.
I cannot understate how awesome the “how to GraphQL” set of tutorials are. They go much deeper than this particular tutorial does and there are great practical tutorials for working with certain frameworks, libraries, and languages. For example, if you're a React developer and you want to understand React and Apollo together, a very popular client library, there's a step-by-step tutorial on exactly how to do that.
It also never hurts to go to the official GraphQL site, which really lays out in very clear language the specification of GraphQL itself, a very helpful resource for moving forward.
Build for the world’s entrepreneurs
Want to see more videos just like this? Subscribe to the ShopifyDevs YouTube channel. Get development inspiration, useful tips, and practical takeaways.
Subscribe