From creating videos and optimizing images, to uploading photos and editing 3D models, Shopify apps manage media for all sorts of reasons. If you're developing an app that allows merchants or customers to interact with media, it's likely you'll need to implement a feature for uploading media files.
I recently started working on an app to bulk manage collection images, and discovered there were many factors to consider, but most of the development work went into handling uploads. There are a number of steps to implement, including accepting files, storage, and validation. Not to mention upload performance.
With any app, allowing users to upload files is generally complicated. There’s a whole host of concerns, and if the file is simply being passed along to an API, it can feel like inefficient double handling.
While exploring the Shopify Developer documentation, the Admin GraphQL API revealed a convenient feature: developers can generate temporary URLs that are capable of receiving files directly from users—eliminating the double handling.
"Developers can generate temporary URLs that are capable of receiving files directly from users—eliminating the double handling."
This means the app doesn’t need to deal with files and the uploads don’t travel as far. It’s a huge win for the app and the user experience. In this article, we’re going to look at the four steps to create an app that allows a user to upload media files directly to Shopify.
Building an upload feature into your app
In this example I'll create a process to upload and associate images with collections, but the same general approach could be applied to other media types, such as video, or 3D model files.
If you’d prefer to skip straight to the finished code, you can find the completed React project in this GitHub repo, or you can view the commits to see each step in detail. Otherwise, let's dive into a high level overview of each step in the process.
1. Setting up the basics
We can get started by using the Shopify App CLI to bootstrap a Node.js app. The Shopify App CLI creates an app in your partner account, generates a skeleton React project (with a Rails or Node.js backend), and starts a server with ngrok.
The app can then be installed into a development store, and you can access the app from the store admin. The Shopify App CLI tool can also be used to populate your development store with sample products, which we'll need for creating collections that our uploaded images can be applied to.
"The drop zone component allows merchants to upload files by dragging and dropping files into an area on a page, or activating a button."
The next step is to list the stores' collections and add a Polaris drop zone component for each collection. The drop zone component allows merchants to upload files by dragging and dropping files into an area on a page, or activating a button.
![Upload files graphql react: GIF of the drop zone component that allows merchants to upload files by dragging and dropping files into an area on a page](https://cdn.shopify.com/s/files/1/0533/2089/files/upload-files-graphql-react.gif?v=1622559408)
Depending on how your app may be using file uploads, you can customize the drop zone element to accept only specific file types, or trigger the file dialog from an action somewhere else on the page.
When using the drop zone element, ensure that you're following best practices and inform merchants when a file can’t be uploaded, and provide feedback once the file has been dropped and uploading begins.
You might also like: Getting Started with GraphQL.
2. Preparing the mutations
By default, the app generated by the Shopify App CLI includes Apollo Client, a GraphQL client complete with state management. This will allow us to use GraphQL to query store data and modify objects. If you're unfamiliar with GraphQL and how it can be used on Shopify to retrieve and work with data, I recommend you check out our developer documentation on GraphQL.
We’ll need to use two GraphQL mutations: stagedUploadsCreate
to generate a temporary URL for our images, and collectionUpdate
to actually update the collection’s image property on Shopify’s side.
The mutations need to be wrapped in the gql
function which will parse them into query documents.
The useMutation
hook returns a function that we can call when we’re ready to execute a specific mutation.
You might also like: API Rate Limits and Working with GraphQL.
3. Generate the temporary URL
Once a user drops a file onto the drop zone component, we can request a temporary URL by executing stagedUploadsCreate
. The mutation expects an input
describing the file. Since we’re using a drop zone component, we have access to the file object to pull the name, type, and size.
It's also worth noting here that this mutation accepts an array and can generate multiple URLs at once. For my example, the drop zone has been configured to only allow a single file. The response includes a temporary URL along with parameters used for authentication.
You might also like: Faster Retrieval of Shopify Metafields with GraphQL.
4. Prepare a form and commence uploading
Now that we have the URL and authentication parameters we can create a new form, append each parameter, and append the file itself. The actual upload of the image file is initiated with Fetch.
Assuming we receive an OK response, the upload was successful. The final step is to tell Shopify to use this new image by executing collectionUpdate
, which expects a collection ID and any properties which have changed (in this case: the collection image).
To test that we've set all this up correctly, you can upload an image via the app, and when you navigate to the Collections area of the admin, you'll see the image has been applied to a collection. If you’re displaying a collection image preview in your app, the change will be reflected immediately thanks to Apollo Client’s state management.
You might also like: How to Build a Shopify App: The Complete Guide.
Use GraphQL to upload files for better app performance
While it’s not always possible to send a file directly to Shopify, using this approach where it makes sense can improve the performance of your app and reduce the distance files travel. The GraphQL Admin API also creates opportunities for apps to manage more types of media like videos and 3D models.
This technique demonstrates how different features of the Admin GraphQL API can be used in conjunction with Polaris components to implement functionality for your app. There's a wealth of functionality to explore in this API that can be used when developing your apps.
What do you think about how to upload files using GraphQL and React? Let us know in the comments below!