Implementing API Rate Limits in Your App

Implement API rate limit

This is a complementary blog post to a video from theShopifyDevs YouTube channel. This is the third post from a four-part series created by Zameer Masjedee, a Solutions Engineer with Shopify Plus.

In the first part of this series,An Introduction to Rate Limits, we covered what exactly an API rate limit is, and how Shopify uses theleaky bucket algorithm. We followed up with a second post,API Rate Limits and Working with GraphQL, to explore the many benefits of GraphQL.

In this post, I'll take all the principles introduced to you in the first two parts of this series, and apply them in a practical application in a development store. First, I'll walk you through what you’ll need to get started. Then, I'll teach you how to make some key real-time requests to the Shopify API.

By the end of this article you'll have a practical understanding of how to make real requests to the Shopify API and how to responsibly consume your rate limit without running into any errors.

Note:All images in this article are hyperlinked to the associated timestamps of the YouTube video, so you can click on them for more information.

What you’ll need to get started

今天,我们要带一些practi最好的ces and ideas we previously learned and implement them, all while employing some essential business logic. All this will be done in an application that we're going to be working on for a development store. I’ll be using VS Code but feel free to use whatever IDE you like working in.

Our example use case

In the example store that I’ve created, we have a bunch of products that are all associated with a commodity. They're gold bracelets, and as we know, the price of gold fluctuates. In our development store, we create products whenever orders come in, so we need to ensure that we're charging the right amount for them. As the price of gold changes, the price of our products also needs to change. There will be recurring time intervals where we have to take the entire product catalog and update the prices based on the most recent price of gold on the market.

There are a few steps we need to take to achieve this goal. First, we’re going to use a Node application to take a look at the products in my shop that might be impacted by an adjustment in the price of gold. Then, we’re going to implement some best practices in order to update those prices. We’re going to do all this in a way that respects the API rate limit and ensures your app isn't getting throttled.

Before we proceed, If you're new to GraphQL, I'd highly recommend checking out the GraphQL video series on theShopifyDev’s YouTube Channelby my good friend Chuck Kosman. He walks you through all of those elements, including aliases, variables, and anything that I discuss in this post that might be unfamiliar. You can watch the first video of his series below, or readour accompanying tutorial.

We're using GraphQL to control our variables, and itsrequestpackage to be able to make some requests pretty simply.

For this tutorial, I'm not going to build an official Shopify app. That would mean going through theapp CLI tooland configuring it that way. We ultimately just want to test it out to see what it would look like if we did have this business logic in our application.

How to retrieve product information

The first thing that we're going to do is make a request. This is demonstrated in the below highlighted query to Shopify.

Implement API rate limit: screenshot taken from Youtube video that shows a request to retrieve the first 200 products that match the query.

The requestproducts(first: 200, query: “tag:gold”)is requesting to retrieve the first 200 products that match our query. In this case, we’re interested in any product that has been tagged asgold. We’re also asking for theidof those products. This is an easy way for us to identify the relevant products out of the entire catalog.

We’re interested in adjusting the price, and we know that the price in Shopify lives on thevariant, so we need to take a look at thevariantassociated with that product. Finally, we’re going to issue a request for theIDandweight, because that's what we're going to use to calculate the new price. We need theweightto determine what to charge going forward.

Another thing to note is that I'm cheating a little bit in the above example when I sayvariants(first: 1). I know that every single one of my products only has a single variant, because that's how I've set up my store. You might have to play around with a larger number and take a look to see if products have more than one variant. We support up to 100 variants on Shopify, and that would result in some pagination, as you're building a more nested query. For our purposes,variants(first: 1)工作很好。

Implement API rate limit: gif made made from timestamped Youtube video

The above shows that we’re making a request,graphQLClient.request, with our straightforwardquery. We’re going to capture those results(catch((error) => console.log(error))and print them onto our console,console.log(JSON.stringify(queryData, undefined, 2)).

Let’s take a look at what happens when I execute this query:

Implement API rate limit: gif taken from timestamped Youtube video

You can see that the request yielded 200 different products. If we run another request for 10 products, it will yield 10 products. It's important to understand that the response we get starts with theproductskey in JSON, and then we get ouredges.

Implement API rate limit: giff taken from time stamped Youtube video

Each of theseedgesrepresents theobjector thenodethat we're interested in, which happens to be aproduct. For each of thesenodes, we have theidand thevariantss that are also associated with thatproduct. This is the information I need to be able to implement my app.

How to identify the API rate limit of your app

We know from the previous tutorials that there are costs associated with making a query or issuing updates. When doing so, we want to be able to get a sense of how much room we have left in our API rate limit. Shopify will provide this information to you in the form of an extension to your response. The only thing is, we aren’t necessarily able to grab it with the original library above by making a standard request, so we’ll have to issue arawRequest.

Issuing arawRequestto capture metadata and available rate limit

Below our standard request, we have an additional form.

Implement API rate limit: Giff taken from timestamped Youtube video

This form uses therawRequestinput, which makes the exact same request with the samequery, but with some additional information. Instead of getting just a data set back, we're also getting theextensions,headers,errors, andstatuses that are part of that request.

In this example, I'm making the exact same request as above, but also capturing and printing out the available rate limit after this request goes through.

When we issue that request:

Implement API rate limit: Screenshot image take from time stamped Youtube video showing an issued request

We see that we have 958 rate limit points available, in addition to the data we’re capturing. Recall that our bucket fills up at 1,000 points, so we have a lot of room left.

Updating your products with individual mutations

The next step we want to take in our process is to update theseproducts. To do so, we’ll make a mutation for each of these products individually.

Remember that when working with GraphQL, you’re charged one point for every nested property or data field that you're capturing. On the other hand, running a mutation costs 10 points, meaning each of these different products is going to cost 10 rate limit points.

You can see how if I'm going to be making a number of requests, I would run through 958 rate limit points pretty quickly.

Recall that we’ve requested our data. The next thing that we’re going to want to do is action it. We want to take every single one of the productIds that are returned, and run them with a mutation on them. I need to be able to fetch theproductIdfrom the request.

How are we going to do that?

You might also like:An Introduction to Rate Limits

Step 1: Indexing into your array by defining a new variable

We see that our request outputs anarrayof differentJSONobjects, so we could index into that array. We’re going to do so by defining a new variable.

Implement API rate limit: gif taken from Youtube video

I'm going to call itconst边缘= data.products.edges. I could even call thisconst productedges = data.products.Edges. That submits a request to look at all that data, which comprises an entireobject, includingproducts, and thenedges.

Step 2: Building out ourforloop

Now, what we want to do is loop through each one of theseedges so that we can access eachproductindependently. We do that by writing aforloop.

(让边缘= 0;边缘< productEdges.length;edge++)

Thisforloop allows us to index into each of the individualarrays that we get back. But there’s some particular data that we need. So, under ourforloop we’re going to write the following code:

const productId = productEdges[edge].node.id

This is saying that I want theproductIdwhich is actually equal to (=) ourproductEdges. Then I need to index into thenodekey, and then theidkey.

The next thing we’re requesting is thevariantId, written in the following code:

const variantId = productEdges[edge].node.variants.edges[0].node.id

This is saying that similarly, we're going to requestproductEdges, nest again into thenode, but this time intovariantsandedges as well. Keep in mind thatedges is still anarray.

Ideally, this request would be paginated over a couple of different options, but remember I’m cheating and I know that we only have a singlevariant, so I'm going to go and grab the first one,[0]. Finally, we’re going to go into thenodeto get theid.

The request forvariantWeightlooks similar to the request forvariantId. It’ll look something like this:

const variantWeight = productEdges[edge].node.variants.edges[0].node.weight

Implement API rate limit: screenshot take from timestamped Youtube video

Now we’ve written in all of our specifications. This allows us to access all the different data points that I know from my objects I wouldn't need to actually implement the mutation. Next, we’re going to look at how to update the price of the new product.

How to update your products prices

There are a few steps involved in responsibly updating the prices of your products, which are outlined below.

First we want to update the price of the product. Updating the price of the product looks like this:

Implement API rate limit: giff made from time stamped Youtube video

This is basically saying thatupdatedPriceis equal to (=) the weight (variantWeight) of the product multiplied by (*) how much it weighs (goldPricePerGram).

We’re actually going to fix it to two decimal points (toFixed(2)), representing cents, because Shopify expects a double in terms of the data type in the request input.

Linking the mutation to yourforloop

Next we’re going to have to pull up the mutation to update the price of a product. For simplicity's sake I’ve copied that, so I'm going to insert it into our function and ourforloop.

Implement API rate limit: gif taken from timestamped youtube video

Now I’ve created a variable calledproductUpdateMutation, and I know that within Shopify, this mutation is calledproductUpdate. It expects an input field of typeProductInput. It will also return to us theidof theproductthat's been updated, because that's what we're requesting.

Fantastic. There we have the mutation.

Creating theproductInputobject

The next thing we need to do is create the input. We can actually take a look in ourproductInputdocumentation更多信息在这看什么s like. It outlines all the different input fields that we can get access to, including theid,metafields orpublications.

For this example, all we’re interested in is thevariants,[ProductVariantIntput ! ]because that's where the price lives.

Implement API rate limit: Gif made of user navigating the shopify API documentation

Thedocumentationtells us that we’re going to have to provide anid, avariants key, and then the properties associated with the productvariant. That's going to be anotherid, this time thepricekey.

Let’s take a shot at implementing this.

Writing yourproductInput

Implement API rate limit: giff taken from timestamped Youtube video

We’ll create an input,const productInput =. Then we'll insert anid: productID,and then we're also going to havevariants. Now,variantis actually anarraybecause there are multiple and each of them are a map of their own.

So we’ll putid: variantId,in that map, and alsoprice: updatedPricefor this particular edge or product, because we're looping through them all, as outlined above.

Every time we're calculating ourupdatedPricehere, it's for one particular product and we have that captured within ourproductInput.

Now we have everything we need to be able to execute this mutation, which is fantastic!

You might also like:How to Build a Shopify App: The Complete Guide.

The final step: calling your mutation

The last thing we want to do is to go ahead and call this mutation. Doing so looks something like this:

Implement API rate limit: giff taken from time stamped Youtube video

To call it, we’re going to sayconstant mutationData =I'm going to synchronously wait for the response of the GraphQL client (await graphQLClient.).

Then we’re going to make a standard request,request(productUpdateMutation, productInput)..

We also want to be able to catch and log any errors that might happen,catch((error)=> console.log(error)).

Before running that, you might also want to log the stringified version of themutationData. The extra parameters help with formatting and keeping things clean by adding some white space around the new lines. The code for that looks like this:

console.log(JSON.stringify(mutationData, undefined, 2))

We’ve followed theproductInputformat laid out in the documentation, however it all needs to be nested within a map, where we specify that it is indeed an input. Otherwise there is confusion around that component. So we’ll just add that in like below:

Implement API rate limit: giff taken from timestamped Youtube video

Once you’ve done that, save and hitrun. You should expect to see theforloop going through each one of thoseproducts and making anupdateto theprice. This is what your terminal should look like:

Implement API rate limit: Screenshot taken from video of successfully looping code

Success! It's looping through each of our products, retrieving the values, and then it's making that update. We’re also seeing no errors and getting ourproductIdback, so that’s fantastic.

Where do we go from here?

现在我们缺少什么?到目前为止,我们不知道much rate limit we still have available when making these requests. We have no idea when we might run into an error. So stay tuned for the next post in this series, where you’ll learn how to capture information, optimize, and responsibly use your app's rate limit.

Grow your business with the Shopify Partner Program

Learn more