skip to Main Content

The repo with this code can be found HERE

I’m working on sourcing and combining data from Shopify Storefront and GraphQL Admin APIs into Gatsby. For sourcing Storefront API I use gatsby-source-shopify, though I wasn’t able to find source plugin for Shopify Admin API and ended up using gatsby-source-graphql.

I have created a private Shopify app and granted all permissions and was able to fetch data using curl example from Shopify GraphQL Admin API documentation.

curl -X POST 
"https://shop-name.myshopify.com/admin/api/2019-04/graphql.json" 
-H "Content-Type: application/graphql" 
-H "X-Shopify-Access-Token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 
-d '
{
  shop {
    name
  }
}
'

Output:

{"data":{"shop":{"name":"Shop Name"}},"extensions":{"cost":{"requestedQueryCost":1,"actualQueryCost":1,"throttleStatus":{"maximumAvailable":1000.0,"currentlyAvailable":999,"restoreRate":50.0}}}}

Error message:

success open and validate gatsby-configs — 0.007 s
success load plugins — 0.345 s
success onPreInit — 0.005 s
success initialize cache — 0.015 s
success copy gatsby files — 0.068 s
success onPreBootstrap — 0.006 s
error Plugin gatsby-source-graphql returned an error


  Error: Parse error on "operationName" (STRING) at [1, 2]


gatsby-source-shopify/sandbox starting to fetch data from Shopify

gatsby-source-shopify/sandbox fetched and processed productTypes: 287.590ms

gatsby-source-shopify/sandbox fetched and processed policies: 297.440ms

gatsby-source-shopify/sandbox fetched and processed blogs: 302.418ms

gatsby-source-shopify/sandbox fetched and processed articles: 344.917ms

gatsby-source-shopify/sandbox fetched and processed collections: 8603.841ms


gatsby-source-shopify/sandbox fetched and processed products: 20362.561ms

gatsby-source-shopify/sandbox finished fetching data from Shopify: 20369.525ms
warning The gatsby-source-graphql plugin has generated no Gatsby nodes. Do you need it?
success source and transform nodes — 21.169 s
warning Multiple node fields resolve to the same GraphQL field `ShopifyArticle.blog` - [`blog`, `blog___NODE`]. Gatsby will use `blog___NODE`.
warning Multiple node fields resolve to the same GraphQL field `ShopifyCollection.products` - [`products`, `products___NODE`]. Gatsby will use `products___NODE`.
warning Multiple node fields resolve to the same GraphQL field `ShopifyProduct.options` - [`options`, `options___NODE`]. Gatsby will use `options___NODE`.
warning Multiple node fields resolve to the same GraphQL field `ShopifyProduct.variants` - [`variants`, `variants___NODE`]. Gatsby will use `variants___NODE`.
success building schema — 0.283 s
success createPages — 0.000 s
success createPagesStatefully — 0.042 s
success onPreExtractQueries — 0.005 s
success update schema — 0.019 s
success extract queries from components — 0.098 s
success run static queries — 0.021 s — 2/2 96.96 queries/second
success run page queries — 0.014 s — 4/4 301.32 queries/second
success write out page data — 0.012 s
success write out redirect data — 0.001 s
success Build manifest and related icons — 0.104 s
success onPostBootstrap — 0.106 s

info bootstrap finished - 23.946 s

 WARNING  Compiled with 1 warnings                                                         6:04:43 PM

Module Warning (from ./node_modules/eslint-loader/index.js):

/Users/skok/dev/gatsby-shopify-starter/src/components/collections.js
  2:10  warning  'useStaticQuery' is defined but never used  no-unused-vars
  2:26  warning  'graphql' is defined but never used         no-unused-vars

✖ 2 problems (0 errors, 2 warnings)


You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.

You can now view gatsby-shopify in the browser.

  http://localhost:8000/

View GraphiQL, an in-browser IDE, to explore your site's data and schema

  http://localhost:8000/___graphql

Note that the development build is not optimized.
To create a production build, use npm run build

warning ⚠ 「wdm」:
info ℹ 「wdm」: Compiled with warnings.
 WAIT  Compiling...                                                                        6:04:43 PM

info ℹ 「wdm」: Compiling...
 WARNING  Compiled with 1 warnings                                                         6:04:43 PM

Module Warning (from ./node_modules/eslint-loader/index.js):

/Users/skok/dev/gatsby-shopify-starter/src/components/collections.js
  2:10  warning  'useStaticQuery' is defined but never used  no-unused-vars
  2:26  warning  'graphql' is defined but never used         no-unused-vars

✖ 2 problems (0 errors, 2 warnings)


You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.
warning ⚠ 「wdm」:
info ℹ 「wdm」: Compiled with warnings.

gatsby-config.js:

require('dotenv').config({
  path: `.env.${process.env.NODE_ENV}`
});

module.exports = {
  siteMetadata: {
    title: `Gatsby Shopify`,
    description: `Gatsby Shopify Starter.`,
    author: `@iamskok`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: "gatsby-source-graphql",
      options: {
        // This type will contain remote schema Query type
        typeName: "ShopifyAdmin",
        // This is field under which it's accessible
        fieldName: "admin",
        // Url to query from
        url: `https://${process.env.SHOP_NAME}.myshopify.com/admin/api/2019-04/graphql.json`,
        headers: {
          // Learn about environment variables: https://gatsby.dev/env-vars
          'X-Shopify-Access-Token': `${process.env.ADMIN_PASSWORD}`,
          'Content-Type': 'application/graphql'
        },
        fetchOptions: {
          method: 'POST'
        },
        refetchInterval: 60
      },
    },
    {
      resolve: `gatsby-source-shopify`,
      options: {
        // The domain name of your Shopify shop. This is required.
        // Example: 'gatsby-source-shopify-test-shop' if your Shopify address is
        // 'gatsby-source-shopify-test-shop.myshopify.com'.
        shopName: process.env.SHOP_NAME,

        // An API access token to your Shopify shop. This is required.
        // You can generate an access token in the "Manage private apps" section
        // of your shop's Apps settings. In the Storefront API section, be sure
        // to select "Allow this app to access your storefront data using the
        // Storefront API".
        // See: https://help.shopify.com/api/custom-storefronts/storefront-api/getting-started#authentication
        accessToken: process.env.STOREFRONT_ACCESS_TOKEN,

        // Set verbose to true to display a verbose output on `npm run develop`
        // or `npm run build`. This prints which nodes are being fetched and how
        // much time was required to fetch and process the data.
        // Defaults to true.
        verbose: true,
      },
    },
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `gatsby-starter-default`,
        short_name: `starter`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
        icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
      },
    },
  ],
}

./src/collections.js:

import React from 'react'
import { useStaticQuery, graphql } from 'gatsby'

const Collections = () => {
  const storefrontData = useStaticQuery(
    graphql`
      query {
        allShopifyCollection {
          edges {
            node {
              id
              description
              descriptionHtml
              handle
              image {
                altText
                id
                src
                localFile {
                  childImageSharp {
                    fluid(maxWidth: 910) {
                      ...GatsbyImageSharpFluid_withWebp_tracedSVG
                    }
                  }
                }
              }
              products {
                id
                handle
                title
              }
              title
              updatedAt
            }
          }
        }
      }
    `
  )

  const adminData = useStaticQuery(
    graphql`
      query {
        admin {
          shop {
            name
          }
        }
      }
    `
  )

  console.log('storefront data:', JSON.stringify(storefrontData));
  console.log('admin data:', JSON.stringify(adminData));

  return (
    <div className="collections">
      <h2>Collections</h2>
    </div>
  )
}

export default Collections

index.js:

import React from 'react'
import Layout from '../components/layout'
import Collections from '../components/collections'

const IndexPage = () => (
  <Layout>
    <h1>Shopify</h1>
    <Collections />
  </Layout>
)

export default IndexPage

package.json:

{
  "name": "gatsby-shopify",
  "private": true,
  "description": "Gatsby Shopify Starter",
  "version": "0.1.0",
  "author": "Vladimir Skok <[email protected]>",
  "dependencies": {
    "gatsby": "^2.4.2",
    "gatsby-image": "^2.0.41",
    "gatsby-plugin-manifest": "^2.1.1",
    "gatsby-plugin-offline": "^2.1.0",
    "gatsby-plugin-react-helmet": "^3.0.12",
    "gatsby-plugin-sharp": "^2.0.36",
    "gatsby-source-filesystem": "^2.0.33",
    "gatsby-source-graphql": "^2.0.18",
    "gatsby-source-shopify": "^2.0.28",
    "gatsby-transformer-sharp": "^2.1.19",
    "prop-types": "^15.7.2",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-helmet": "^5.2.1"
  },
  "devDependencies": {
    "prettier": "^1.17.0"
  },
  "keywords": [
    "gatsby"
  ],
  "license": "MIT",
  "scripts": {
    "build": "gatsby build",
    "develop": "gatsby develop",
    "format": "prettier --write src/**/*.{js,jsx}",
    "start": "npm run develop",
    "serve": "gatsby serve",
    "test": "echo "Write tests! -> https://gatsby.dev/unit-testing""
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/iamskok/gatsby-shopify-starter"
  },
  "bugs": {
    "url": "https://github.com/iamskok/gatsby-shopify-starter/issues"
  }
}

The expected result is to make a successful GraphQL query to Shopify Admin API. The actual result is server error with 400 status code.

2

Answers


  1. You have a few issues here.

    First you need to pass X-Shopify-Storefront-Access-Token not X-Shopify-Access-Token. (
    if you are really using a private app )

    Then you need to request /api/2019-04/graphql not /admin/api/2019-04/graphql.json".

    Please refer to this doc: https://help.shopify.com/en/api/custom-storefronts/storefront-api/getting-started#accessing-the-storefront-api-graphql-endpoint

    Login or Signup to reply.
  2. Your gatsby-source-graphql setting is different than the curl command in the following seting:

    • the POST HTTP Method
    • Content-Type: application/graphql header

    In order to match the curl command, you could try the setting below:

        {
          resolve: "gatsby-source-graphql",
          options: {
            typeName: "ShopifyAdmin",
            fieldName: "admin",
            url: `https://${process.env.SHOP_NAME}.myshopify.com/admin/api/2019-04/orders.json`,
            headers: {
              'X-Shopify-Access-Token': `${process.env.ADMIN_PASSWORD}`,
       +      'Content-Type': 'application/graphql',
            },
       +    fetchOptions: {
       +      method: 'POST'
       +    }
            refetchInterval: 60
          },
        },
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search