Build a Shopify App with Node.js and React

Embed your app in Shopify

To embed your app in Shopify, you need to expose it publicly and authenticate by using a Shopify API key.

Expose your dev environment

When authenticating merchants, Shopify redirects from the app authorization prompt back to your app. Your app needs an HTTPS address to be able to do this. Since your localhost:3000 isn’t a public address, you’ll use ngrok to create a secure tunnel from the public internet to your local machine.

  1. In a new terminal window, install ngrok:
    Terminal
    Copy
                npm install ngrok -g
    
  2. Set ngrok to use port 3000:
    Terminal
    Copy
                ngrok http 3000
    

When running, it should look like this:

terminal running ngrok

Get a Shopify API key and Shopify API secret key

The Shopify API key and Shopify API secret key are used to authenticate your app with Shopify. To get a Shopify API key and Shopify API secret key you’ll need to create an app in the Shopify Partners Dashboard. If you don’t have a Shopify Partners account, then you can sign up now.

  1. From your Shopify Partner Dashboard, click Apps.
  2. Click Create app.
    If this isn’t your first app, then the Create app button will be in the top-right corner of the Apps page.
    create app button in the Shopify Partner Dashboard
  3. Copy the HTTPS version of the forwarding URL from your ngrok terminal tab: terminal running ngrok
  4. Give your app a name. For example, Sample Embedded App.
  5. Paste the HTTPS version of your ngrok forwarding URL into the App URL field.
  6. Paste the same HTTPS forwarding URL into the Whitelisted redirection URL(s) field and add /auth/callback to the end of the path. create app modal in the Shopify Partner Dashboard
  7. Click Create app.

    You’ll be redirected to a welcome screen that displays your Shopify API key and Shopify API secret key.

Add the Shopify API key and Shopify API secret key

You’ll need a safe place to keep your Shopify API key and Shopify API secret key. A common best practice is to store API keys in an environment separate from your code. To do this, you’ll use a .env file and process.env to share them without exposing them publicly.

  1. Create a .env file in your root project folder.
  2. Add the keys and temporary placeholder to the .env file:
    The information you're storing in the .env file should never be shared on Github or any other version control service. Add it to your .gitignore file.
    SHOPIFY_API_KEY='YOUR API KEY FROM SHOPIFY PARTNERS DASHBOARD' SHOPIFY_API_SECRET_KEY='YOUR API SECRET KEY FROM SHOPIFY PARTNERS DASHBOARD'
  3. Copy your Shopify API key and Shopify API secret key from your app in the Shopify Partner Dashboard and paste them into your .env file. app api key and secret key in the Shopify Partners dashboard

Prepare for OAuth

Open Authorization (OAuth) is a token-based authentication and authorization system that Shopify uses to securely connect apps to Shopify and its merchants.

Install koa and other dependencies

koa-middleware will work with the koa-shopify-auth package to take care of most of the authentication process and create your custom server.

  1. Stop your server from the terminal window that’s running Next.js (ctrl + c).
    If you stop ngrok at any time, then you’ll need to restart the tunnel and update the URLs in your Shopify Partner Dashboard. It’s best to always keep it running in a separate terminal window.
  2. install koa, @shopify/koa-shopify-auth, dotenv, koa-session and isomorphic_fetch:
    Terminal
    Copy
                npm install --save koa @shopify/koa-shopify-auth dotenv koa-session isomorphic-fetch
    

Set up a Node.js server

You’ll need a server file that imports packages for koa, routing, Next.js, and a few functions from Shopify. The koa-shopify-auth package requires fetch, so you’ll also import isomorphic fetch.

In this case, the app refers to the next.js app, and the server middleware refer to the koa server itself.

  1. Create a server.js file in the root of your project folder.
  2. Add your imports and set up the variables from your dotenv file:

    /server.js

    code contained in /server.js
    require('isomorphic-fetch'); const dotenv = require('dotenv'); const Koa = require('koa'); const next = require('next'); const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth'); const { verifyRequest } = require('@shopify/koa-shopify-auth'); const session = require('koa-session'); dotenv.config(); const port = parseInt(process.env.PORT, 10) || 3000; const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env;
  3. Add the app to your server file:

    /server.js

    code contained in /server.js
    require('isomorphic-fetch'); const dotenv = require('dotenv'); const Koa = require('koa'); const next = require('next'); const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth'); const { verifyRequest } = require('@shopify/koa-shopify-auth'); const session = require('koa-session'); dotenv.config(); const port = parseInt(process.env.PORT, 10) || 3000; const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env; Add:app.prepare().then(() => {});
  4. Add your routing middleware and koa server:

    /server.js

    code contained in /server.js
    require('isomorphic-fetch'); const dotenv = require('dotenv'); const Koa = require('koa'); const next = require('next'); const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth'); const { verifyRequest } = require('@shopify/koa-shopify-auth'); const session = require('koa-session'); dotenv.config(); const port = parseInt(process.env.PORT, 10) || 3000; const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env; app.prepare().then(() => { Add: const server = new Koa(); Add: server.use(session(server)); Add: server.keys = [SHOPIFY_API_SECRET_KEY]; Add: server.use(async (ctx) => { Add: await handle(ctx.req, ctx.res); Add: ctx.respond = false; Add: ctx.res.statusCode = 200; Add: return Add: }); });
  5. Add the createShopifyAuth and verifyRequest middleware:
    The createShopifyAuth functions take the Shopify API key and the Shopify API secret key from your .env file, and trigger the authentication screen. The function provides you the afterAuth, where you can use your own logic or redirect. The verifyRequest redirects users to the OAuth route if they haven’t been authenticated.

    /server.js

    code contained in /server.js
    require('isomorphic-fetch'); const dotenv = require('dotenv'); const Koa = require('koa'); const next = require('next'); const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth'); const { verifyRequest } = require('@shopify/koa-shopify-auth'); const session = require('koa-session'); dotenv.config(); const port = parseInt(process.env.PORT, 10) || 3000; const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env; app.prepare().then(() => { const server = new Koa(); server.use(session(server)); server.keys = [SHOPIFY_API_SECRET_KEY]; Add: server.use( Add: createShopifyAuth({ Add: apiKey: SHOPIFY_API_KEY, Add: secret: SHOPIFY_API_SECRET_KEY, Add: scopes: ['read_products'], Add: afterAuth(ctx) { Add: const { shop, accessToken } = ctx.session; Add: ctx.redirect('/'); Add: }, Add: }), Add: ); Add: server.use(verifyRequest()); Add: server.use(async (ctx) => { Add: await handle(ctx.req, ctx.res); Add: ctx.respond = false; Add: ctx.res.statusCode = 200; Add: return Add: }); });
  6. Set your app to run on port 3000:

    /server.js

    code contained in /server.js
    require('isomorphic-fetch'); const dotenv = require('dotenv'); const Koa = require('koa'); const next = require('next'); const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth'); const { verifyRequest } = require('@shopify/koa-shopify-auth'); const session = require('koa-session'); dotenv.config(); const port = parseInt(process.env.PORT, 10) || 3000; const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env; app.prepare().then(() => { const server = new Koa(); server.use(session(server)); server.keys = [SHOPIFY_API_SECRET_KEY]; server.use( createShopifyAuth({ apiKey: SHOPIFY_API_KEY, secret: SHOPIFY_API_SECRET_KEY, scopes: ['read_products'], afterAuth(ctx) { const { shop, accessToken } = ctx.session; ctx.redirect('/'); }, }), ); server.use(verifyRequest()); server.use(async (ctx) => { await handle(ctx.req, ctx.res); ctx.respond = false; ctx.res.statusCode = 200; return }); Add: server.listen(port, () => { Add: console.log(`> Ready on http://localhost:${port}`); Add: }); });
  7. Update your package.json file to use the new Node.js server:

    /package.json

    code contained in /package.json
    "scripts": { "test": "echo \"Error: no test specified\" && exit 1", Remove: "dev": "next", Add: "dev": "node server.js", "build": "next build", Remove: "start": "next start" Add: "start": "NODE_ENV=production node server.js" },
  8. In your original terminal window, start your server:
    Terminal
    Copy
                npm run dev
    

Authenticate and test your app

You’ll need a Shopify development store to authenticate your app. If you don’t have one, then create it from the Development stores page in the Shopify Partner Dashboard. Learn more about development stores.

Your developer store’s myshopify URL is also called your shop origin.
  1. Add the HTTPS version of your ngrok forwarding URL and your store’s URL to the following placeholder and load it in a browser:

    https://YOUR_NGROK_ADDRESS.io/auth?shop=YOUR_SHOPIFY_STORE.myshopify.com
    install returning 'the page you’re looking for couldn’t be found'
    If you get an error that says "The page you’re looking for couldn’t be found", then paste the install link back into your browser and load the page again.
  2. Click the Install unlisted app button. install page When the redirect is successful, you’ll be sent back to your ngrok URL. install redirecting back to ngrok
  3. Log in to your development store and visit the Apps page. apps section of your development store
  4. Click on your app.

    You should see your app printing out Sample app using React and Next.js, embedded inside Shopify.

    your app embedded in Shopify
Continue to Build your user interface with Polaris