All Tutorials

Build a Shopify app with Rails, React, and App Bridge

All Tutorials

Build a Shopify app with Rails, React, and App Bridge

Build a Shopify app with Rails, React, and App Bridge

This tutorial shows you how to build an embedded Shopify app with Rails 6 using the Shopify App gem, React, and App Bridge authentication.

The app uses session tokens to authenticate requests from the app frontend to the app backend. When you've completed this tutorial, any requests made to the protected /graphql endpoint of the app will be authenticated with an Authorization: Bearer <session-token> header.

Requirements

Your app must meet the following requirements to complete this tutorial:

You can view the code for the sample app on GitHub.

Generate credentials from your Partner Dashboard

If you haven't done so already, then note the app's Shopify API key and secret found on your Shopify Partner Dashboard. These credentials are used to implement OAuth so that the app can access Shopify APIs.

Create a backend using Rails

  1. Run the following console command in your working directory:

    $ rails new <your-app-name> --webpack=react
  2. In your newly-created app, create a .env file in the root directory of <your-app-name>:

    SHOPIFY_API_KEY=<The API key app credential specified in the Shopify Partners dashboard>
    SHOPIFY_API_SECRET=<The API secret key app credential specified in the Shopify Partners dashboard>
  3. Open the app's Gemfile and add the following dependencies:

    gem 'dotenv-rails'
    gem 'graphql'
    gem 'react-rails'
    gem 'shopify_app', '~> 17.1.0' # v17.1.0 is used in this guide
  4. Run the following command to install the gems:

    $ bundle install
  5. Run the following command to generate an embedded app using the Shopify App gem:

    $ rails generate shopify_app
  6. Run the following installer to create a GraphQL backend:

    $ rails generate graphql:install
  7. Run any outstanding database migrations:

    $ rails db:migrate

Create a frontend using React

  1. In the root folder of the app, run the following commands to install React using webpacker:

    $ rails webpacker:install
    $ rails webpacker:install:react
    $ rails generate react:install
  2. Add the following dependencies to your package.json file:

    $ yarn add @shopify/app-bridge-utils@1.26.0 @apollo/client graphql @shopify/polaris
  3. Generate a default App.js component:

    $ rails generate react:component App
  4. Overwrite app/views/home/index.html.erb to match the following code:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <link rel="stylesheet" href="https://unpkg.com/@shopify/polaris@4.22.0/styles.min.css"/>
      </head>
      <body>
        <%= react_component("App") %>
      </body>
    </html>

Make authenticated requests using App Bridge

Configure the backend

  1. Update GraphqlController in /app/controllers/graphql_controller.rb to inherit AuthenticatedController:

    class GraphqlController < AuthenticatedController
  2. Add an expected message to the test_field method of app/grapqhl/types/query_type.rb:

    def test_field
      "Congratulations! Your requests are now authenticated using App Bridge Authentication."
    end
  3. To handle changes in access scopes requested by your app, add the following configuration to /app/config/initializers/shopify_app.rb. For more information on handling changes in access scopes, refer to the Shopify App gem.

    ShopifyApp.configuration.reauth_on_access_scope_changes = true

Configure the frontend

Your app's frontend uses authenticatedFetch to attach a session token as an authorization header when making requests to your app's backend. This header authenticates that the request was made by your app embedded in a shop.

  1. In app/javascript/components/App.js, import authenticatedFetch from @shopify/app-bridge-utils:

    import { authenticatedFetch } from '@shopify/app-bridge-utils';
  2. In app/javascript/components/App.js, create an Apollo Client and provide authenticatedFetch as the fetch method:

    import {
      ApolloClient,
      ApolloProvider,
      HttpLink,
      InMemoryCache,
    } from '@apollo/client';
    import { AppProvider, EmptyState, Page } from '@shopify/polaris';
    import { authenticatedFetch } from '@shopify/app-bridge-utils';
    
    import enTranslations from '@shopify/polaris/locales/en.json';
    import React from 'react';
    
    export default function App() {
      const client = new ApolloClient({
        link: new HttpLink({
          credentials: 'same-origin',
          fetch: authenticatedFetch(window.app), // created in shopify_app.js
          uri: '/graphql'
        }),
        cache: new InMemoryCache()
      });
    
      return (
        <AppProvider i18n={enTranslations}>
          <ApolloProvider client={client}>
            <Page>
              <EmptyState>
                ...
              </EmptyState>
            </Page>
          </ApolloProvider>
        </AppProvider>
      );
    }
  3. Create a TestData component to query the /graphql endpoint of the app:

    import { gql, useQuery } from '@apollo/client';
    
    import React from 'react';
    
    const TEST_QUERY = gql`query { testField }`;
    
    export default function TestData() {
      const {loading, error, data} = useQuery(TEST_QUERY);
    
      if (loading) {
        return (
          <div>Loading</div>
        );
      } else if (error) {
        return (
          <div>Something went wrong!</div>
        );
      } else {
        return (
          <p>{data.testField}</p>
        );
      }
    }
  4. Import the TestData in the App component:

    import TestData from './TestData'
    
    export default function App() {
    
     return (
        <AppProvider i18n={enTranslations}>
          <ApolloProvider client={client}>
            <Page>
              <EmptyState>
                <TestData/>    # Add the TestData component here
              </EmptyState>
            </Page>
          </ApolloProvider>
        </AppProvider>
      );
    }

Embed the app in Shopify

During OAuth, Shopify redirects from the app authorization prompt back to the allow-listed redirect URL specified in your Shopify Partner Dashboard. The app needs an HTTPS address to be able to do this. Since your localhost:3000 is not public, you need to use a tool like ngrok to create a secure tunnel from the public internet to your local machine.

  1. Download and install ngrok.

  2. Initialize ngrok to use port 3000 using the following console command:

    $ ngrok http 3000
  3. Start the app using the following console command:

    $ rails s
  4. Visit https://<ngrok-id>.ngrok.io and specify the shop you want to install your app on.

  5. After the app is installed, you're redirected to the embedded app. The app displays the following message:

    "Congratulations! Your requests are now authorized using App Bridge Authentication."

Resources

Sample app using Rails and React

Next steps