Gatsby and Shopify Part 2
Add to favorites
Connect Shopify to Gatsby and display all products

Advanced React Hooks Handbook
1
Intro to Firebase
6:59
2
Firebase Auth
11:59
3
Firestore
10:51
4
Firebase Storage
6:40
5
Serverless Email Sending
10:02
6
Geocoding with Mapbox
9:24
7
Contentful Part 1
4:59
8
Contentful Part 2
8:52
9
Gatsby and Shopify Part 1
5:20
10
Gatsby and Shopify Part 2
13:21
11
Gatsby and Shopify Part 3
14:32
12
Creating Stripe Account and Product
5:18
13
Adding Stripe.js to React
5:54
14
Stripe Checkout Client Only
18:18
15
PayPal Checkout
31:21
Shopify setup
If you haven't already, I highly encourage you to follow the first part of this tutorial , where you'll learn how to setup a Shopify store, add products to your store, and get a password to connect your Gatsby website to Shopify.
Completed project code
You can find the completed project code on Github at https://github.com/stephdiep/gatsby-shopify-tutorial . You can also download the source files, but remember to add your own password and storeUrl in the .env file for the project to build successfully. You can view the live demo at https://gatsby-shopify-tutorial.netlify.app/.
Install the plugin
Next, we'll need to install the gatsby-source-shopify plugin. In the Terminal, run the following command.
npm install gatsby-source-shopify
Let's add the password we copied from Shopify and our storeUrl (which is your-store-name.myshopify.com ), in an environment file - so we don't commit them to Github, as it's a big security flaw. Create a .env file, and add your password and storeUrl in it.
GATSBY_SHOPIFY_PASSWORD=shppa_a59ejcnvk2l29jkdmcn35skw
GATSBY_SHOPIFY_STORE_URL=designcode-tutorial.myshopify.com
Remember to change the password and the storeUrl to the ones from your Shopify account. We'll need to configure the plugin to connect with our Shopify account in the gatsby-config.js file. In the plugins array, add the gatsby-source-shopify plugin and pass in your app password , along with your storeUrl , to the options object.
// gatsby-config.js
require("dotenv").config()
module.exports = {
plugins: [
{
resolve: "gatsby-source-shopify",
options: {
password: process.env.GATSBY_SHOPIFY_PASSWORD,
storeUrl: process.env.GATSBY_SHOPIFY_STORE_URL,
},
},
],
}
Before continuing, we need to make sure that the setup is correct, and the app compiles successfully. Run your development server to verify that. If the app built successfully, move on to the next step.
gatsby develop
If you run into an error saying that your password and storeUrl are required, and you added them both in the .env file, just add require("dotenv").config() at the top of your gatsby-config.js file.
Querying the products
Fetching the products from Shopify is quite easy, as it's simply a GraphQL query. With your development server running, head over to the Gatsby GraphiQL interface ( http://localhost:8000/___graphql ) and we'll query all of our products with the following query. To query all the Shopify products, we'll use the allShopifyProduct node.
query MyQuery {
allShopifyProduct {
nodes {
title
handle
variants {
shopifyId
}
priceRangeV2 {
maxVariantPrice {
amount
}
}
description
images {
src
}
}
}
}
Click on the Play button and once you're satisfied with the results you see on the right side panel, copy your entire GraphQL query.
We'll create a products page, listing all the products we queried with the GraphQL query above. In a new products.js file, under the src > pages folder, define your Products component.
// src/pages/products.js
const Products = () => {
return <div></div>
}
export default Products
Import React and graphql from gatsby at the top.
// src/pages/products.js
import React from "react"
import { graphql } from "gatsby"
Right below our export default , we'll add the GraphQL query we tested before.
// src/pages/products.js
export const query = graphql`
{
allShopifyProduct {
nodes {
title
handle
variants {
shopifyId
}
priceRangeV2 {
maxVariantPrice {
amount
}
}
description
images {
src
}
}
}
}
`
By adding this query in the Products.js file, we can access it with the data props we'll pass to our Products component.
// src/pages/products.js
const Products = ({ data }) => {
console.log(data)
return <div></div>
}
export default Products
We're console logging the data, and you should see the allShopifyProduct object printed on the console when navigating to the /products page. The products page should be a blank page now, but we'll fill it soon with all the products data.
Now, let's create a ProductCard component. Each product card will accept a product as a prop, and it'll display all the information of that product. Remember to npm install styled-components if you plan on using the ProductCard below.
// src/components/ProductCard.js
import React from 'react'
import styled from "styled-components"
const ProductCard = ({ product }) => {
return (
<Wrapper>
<AddButton onClick={() => alert("Added to cart!")}><p>+</p></AddButton>
<ContentWrapper>
<Image src={product.images[0]?.src} />
<TextWrapper>
<Title>{product.title}</Title>
<Price>{product.priceRangeV2.maxVariantPrice.amount}0$</Price>
</TextWrapper>
</ContentWrapper>
</Wrapper>
)
}
export default ProductCard
const Wrapper = styled.div`
display: grid;
justify-content: center;
align-items: center;
width: 200px;
border-radius: 20px;
gap: 10px;
cursor: pointer;
position: relative;
box-shadow: 0px 20px 40px rgba(52, 53, 99, 0.2),
0px 1px 3px rgba(0, 0, 0, 0.05);
`
const ContentWrapper = styled.div``
const Image = styled.img`
width: 200px;
height: 300px;
object-fit: cover;
border-radius: 20px;
margin: 0;
`
const TextWrapper = styled.div`
position: absolute;
bottom: 0px;
left: 0px;
border-radius: 0 0 20px 20px;
background: rgba(255, 255, 255, 0.2);
width: 200px;
padding: 10px 0;
backdrop-filter: blur(40px);
`
const Title = styled.p`
font-weight: 600;
text-align: center;
margin: 0;
color: #014c40;
`
const Price = styled.p`
font-weight: normal;
text-align: center;
margin: 0;
`
const AddButton = styled.div`
position: absolute;
top: 20px;
right: 20px;
background: #014c40;
padding: 10px;
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
:hover {
transform: scale(1.2);
transition: 0.2s;
}
p {
margin: 0;
color: white;
font-weight: bold;
}
`
Back in Products.js , we'll iterate over the products we got from the GraphQL query and, for each product, we'll display the ProductCard . Remember to import ProductCard in Product.js.
// src/pages/Products.js
import ProductCard from "../components/ProductCard"
const Products = ({ data }) => {
const { nodes } = data.allShopifyProduct
return (
<div>
{nodes?.map((product, index) => (<ProductCard key={index} product={product} />))}
</div>)
}
Create a product page
We'll need to create a template for each product we have in our store, since each one of them will have their own page. Let's create a templates folder under the src folder. In the templates folder, we'll add a new file called product.js . This is where we'll create our product page template. For now, let's just add the product title and its description on the page. This template will accept a pageContext prop, and we'll be able to get the product object from pageContext.
// src/templates/product.js
import React from "react"
const ProductTemplate = ({ pageContext }) => {
const { product } = pageContext
return (
<div>
<h1>{product.title}</h1>
<p>{product.description}</p>
</div>
)
}
export default ProductTemplate
Head over to the gatsby-node.js file. Copy and paste the following code. This code will query all Shopify products and, for each one, create a unique page with the handle field, using the product.js template we just created.
const path = require(`path`)
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
// Query for all products in Shopify
const result = await graphql(`
query {
allShopifyProduct {
edges {
node {
title
handle
variants {
shopifyId
}
priceRangeV2 {
maxVariantPrice {
amount
}
}
description
images {
src
}
}
}
}
}
`)
// Iterate over all products and create a new page using a template
// The product "handle" is generated automatically by Shopify
result.data.allShopifyProduct.edges.forEach(({ node }) => {
createPage({
path: `/products/${node.handle}`,
component: path.resolve(`./src/templates/product.js`),
context: {
product: node,
},
})
})
}
Now, since we changed our gatsby-node.js file, we need to restart the server. In the Terminal, stop the server with Control (^) + C , then restart the server.
gatsby develop
Link product card to product page
Head back to the ProductCard.js file. We'll add an onClick event on the card, so when the user clicks on the card, it'll lead them to the product page. Import navigate from gatsby-link , and add the onClick event on the ContentWrapper.
// src/components/ProductCard.js
import { navigate } from 'gatsby-link'
const ProductCard = ({ product }) => {
return (
<Wrapper>
{ /* Add button here... */ }
<ContentWrapper onClick={() => navigate(`${product.handle}`)}>
{ /* Card content... */ }
</ContentWrapper>
</Wrapper> )
}
Now let's test it out. Go to the products page, and click on any card. You should them land on a non-styled product page, and the URL should be /products/product-handle . We'll be styling this page right away!
Find below the product show page styled using styled-components. You can use this one, or code your own!
import { navigate } from "gatsby-link"
import React from "react"
import styled from "styled-components"
import Layout from "../components/layout"
import PrimaryButton from "../components/PrimaryButton"
const ProductTemplate = ({ pageContext }) => {
const { product } = pageContext
return (
<Layout>
<BackButton onClick={() => navigate(-1)}>{"< "} Back</BackButton>
<Wrapper>
<Image src={product.images[0]?.src} />
<InfoContainer>
<Title>{product.title}</Title>
<Subtitle>{product.priceRangeV2.maxVariantPrice.amount}0$</Subtitle>
<p>{product.description}</p>
<InputForm>
<Subtitle><label htmlFor="qty">Quantity:</label></Subtitle>
<Input placeholder="1" id="qty" type="number" defaultValue={1} />
</InputForm>
<PrimaryButton text="Add to cart" onClick={() => alert("Added to cart!")} />
</InfoContainer>
</Wrapper>
</Layout>
)
}
export default ProductTemplate
const BackButton = styled.p`
cursor: pointer;
color: #014c40;
margin-left: 40px;
font-size: 14px;
font-weight: 600;
`
const Wrapper = styled.div`
margin: 40px;
display: grid;
grid-template-columns: 400px auto;
gap: 40px;
`
const Image = styled.img`
width: 400px;
height: 500px;
border-radius: 30px;
object-fit: cover;
`
const InfoContainer = styled.div`
display: grid;
align-items: flex-start;
height: fit-content;
gap: 10px;
p {
margin: 0;
}
`
const Title = styled.h1`
margin: 0;
`
const Subtitle = styled.p`
font-weight: bold;
max-width: 500px;
`
const InputForm = styled.form`
display: grid;
grid-template-columns: repeat(2, auto);
width: fit-content;
gap: 20px;
align-items: center;
gap: 10px;
`
const Input = styled.input`
border-radius: 20px;
border: 2px solid rgba(0,0,0,0.3);
padding: 10px 20px;
max-width: 80px;
font-size: 12px;
:focus {
outline: none;
outline-color: #014c40;
}
`
Upcoming
Great, we now created a basic working e-commerce website: we have our products list and a unique page for each product. The only thing that's left is to implement the checkout process. In the (upcoming) last part of this tutorial, we'll be covering that. See you in the next section!
Learn with videos and source files. Available to Pro subscribers only.
Purchase includes access to 50+ courses, 320+ premium tutorials, 300+ hours of videos, source files and certificates.
Templates and source code
Download source files
Download the videos and assets to refer and learn offline without interuption.
Design template
Source code for all sections
Video files, ePub and subtitles
Browse all downloads
1
Intro to Firebase
Learn about Firebase and set it up in your React project
6:59
2
Firebase Auth
Set up authentication in your React application using Firebase Auth
11:59
3
Firestore
Enable Firestore as your database in your React application
10:51
4
Firebase Storage
Enable Firebase Storage in your application to store photos or videos from users
6:40
5
Serverless Email Sending
Use EmailJS to send an email without backend
10:02
6
Geocoding with Mapbox
Create an address autocomplete with Mapbox's Geocoding API
9:24
7
Contentful Part 1
Create a Contentful account, add a model and content
4:59
8
Contentful Part 2
How to use the Content Delivery API to fetch data from Contentful
8:52
9
Gatsby and Shopify Part 1
Create a Shopify store, generate a password and add products to the store
5:20
10
Gatsby and Shopify Part 2
Connect Shopify to Gatsby and display all products
13:21
11
Gatsby and Shopify Part 3
Create a seamless checkout experience with Shopify and Gatsby
14:32
12
Creating Stripe Account and Product
Start integrating with Stripe and set up an account, product and price
5:18
13
Adding Stripe.js to React
Loading Stripe.js library to your React client application
5:54
14
Stripe Checkout Client Only
Accept payment with Stripe Checkout without backend
18:18
15
PayPal Checkout
Integrate online payment with PayPal
31:21
Meet the instructor
We all try to be consistent with our way of teaching step-by-step, providing source files and prioritizing design in our courses.
Stephanie Diep
iOS and Web developer
Developing web and mobile applications while learning new techniques everyday
7 courses - 36 hours

Build Quick Apps with SwiftUI
Apply your Swift and SwiftUI knowledge by building real, quick and various applications from scratch
11 hrs

Advanced React Hooks Handbook
An extensive series of tutorials covering advanced topics related to React hooks, with a main focus on backend and logic to take your React skills to the next level
3 hrs

SwiftUI Concurrency
Concurrency, swipe actions, search feature, AttributedStrings and accessibility were concepts discussed at WWDC21. This course explores all these topics, in addition to data hosting in Contentful and data fetching using Apollo GraphQL
3 hrs

SwiftUI Combine and Data
Learn about Combine, the MVVM architecture, data, notifications and performance hands-on by creating a beautiful SwiftUI application
3 hrs

SwiftUI Advanced Handbook
An extensive series of tutorials covering advanced topics related to SwiftUI, with a main focus on backend and logic to take your SwiftUI skills to the next level
4 hrs

React Hooks Handbook
An exhaustive catalog of React tutorials covering hooks, styling and some more advanced topics
5 hrs

SwiftUI Handbook
A comprehensive series of tutorials covering Xcode, SwiftUI and all the layout and development techniques
7 hrs