Docs Guides Create a Shopify app with Mantle

Integrate your Shopify remix app with Mantle

The code for this sample app can be found at https://github.com/Hey-Mantle/mantle-shop-example.

1. Create your Shopify app

Follow the guide at https://shopify.dev/docs/apps/getting-started/create to create the default Shopify remix app.

Create an empty .env file in your project if it doesn’t already exist.

2. Add the app to Mantle

In your Mantle dashboard, under Apps hit the Add app button to add this new app. Once added, go to Settings for the app and create a new API key.

Add the app ID and API key to MANTLE_APP_ID and MANTLE_API_KEY variables in .env, respectively.

3. Add Mantle helper library

npm install @heymantle/polaris

This includes @heymantle/react and @heymantle/client as dependencies.

4. Add mantleApiToken to Session model

You’ll need to store the Mantle customer API token for each shop, the database table used in the default Shopify sample app is Session, so let’s open prisma/schema.prisma and add the mantleApiToken field to to the end of the Session model so it looks like:

model Session {
  id          String    @id
  shop        String
  state       String
  isOnline    Boolean   @default(false)
  scope       String?
  expires     DateTime?
  accessToken String
  userId      BigInt?
  mantleApiToken String?
}

and then run npm run prisma migrate dev -- --name add-mantle-api-token-to-session to create and run the migration.

5. Identify shops to Mantle when they install the app

In app/shopify.server.js we’ll import the mantle API client at the top

import { MantleClient } from "@heymantle/client"

Then, at the end of the shopify.hooks.afterAuth function we’ll add the identify request, so the function now looks like:

afterAuth: async ({ session, admin }) => {
  shopify.registerWebhooks({ session });

  // fetch current shop and identify to Mantle
  const response = await admin.graphql(
    `#graphql
      query getShop {
        shop {
          id
        }
      }`,
  );
  const responseJson = await response.json();
  const shop = responseJson.data?.shop;
  const mantleClient = new MantleClient({
    appId: process.env.MANTLE_APP_ID,
    apiKey: process.env.MANTLE_APP_API_KEY,
  });
  const identifyResponse = await mantleClient.identify({
    platform: "shopify",
    platformId: shop.id,
    myshopifyDomain: session.shop,
    accessToken: session.accessToken,
  });
  const mantleApiToken = identifyResponse?.apiToken;
  await prisma.session.update({
    where: { id: session.id },
    data: { mantleApiToken },
  });
}

Now the shop is identified to Mantle and you have the Mantle customer API token that you can use in frontend requests.

6. Add MantleProvider context to your frontend

Next, we’ll need to add the MantleProvider context to your react frontend to be able to access mantle customer information and performance actions such as subscribe. In app/routes/app.jsx you’ll need to load the new session object in the loader function and include the Mantle customer API key stored there in the data available in the component below it. With this you’ll add MantleProvider just after AppProvider with the appropriate props:

// other imports... 
import { MantleProvider } from "@heymantle/react";

export const loader = async ({ request }) => {
  const { session: _session } = await authenticate.admin(request);

  const { mantleApiToken } = await prisma.session.findUnique({
    where: { id: _session.id },
  });

  return json({
    apiKey: process.env.SHOPIFY_API_KEY || "",
    mantleAppId: process.env.MANTLE_APP_ID || "",
    mantleApiToken,
  });
};

export default function App() {
  const { apiKey, mantleAppId, mantleApiToken } = useLoaderData();

  return (
    <AppProvider isEmbeddedApp apiKey={apiKey}>
      <MantleProvider
        appId={mantleAppId}
        customerApiToken={mantleApiToken}
      >
        <NavMenu>
          <Link to="/app" rel="home">
            Home
          </Link>
          <Link to="/app/additional">Additional page</Link>
          <Link to="/app/plans">Plans</Link>
        </NavMenu>
        <Outlet />
      </MantleProvider>
    </AppProvider>
  );
}

You may noticed we also added a new route for /app/plans, we’ll add this page in the next step.

7. Add plans page

First you’ll want to add a couple plans so there’s something to show on this page, hop on back to your Mantle dashboard, select your test app, under Plans hit the Add plan button and add a couple test plans.

In order to use the Shopify Billing API, apps must also have the public distribution setting. Go to your Shopify partner dashboard, into your app, hit the Choose Distribution button and select Public distribution.

Now, to show these plans to your customers in your app, add a new file app/routes/app.plans.jsx

import { Layout, Page } from "@shopify/polaris";
import { TitleBar } from "@shopify/app-bridge-react";
import { PlanCardStack, PlanCardType } from "@heymantle/polaris";
import { useMantle } from "@heymantle/react";

export default function PlansPage() {
  const { customer, plans, mantleClient } = useMantle();

  const handleSelectPlan = async ({ plan, discount }) => {
    const subscription = await mantleClient.subscribe({
      planId: plan.id,
      discountId: discount?.id,
      returnUrl: "/app/plans",
    });
    const url = subscription.confirmationUrl;
    open(url, "_top");
  };

  return (
    <Page>
      <TitleBar title="Select a plan" />
      <Layout>
        <Layout.Section>
          <PlanCardStack
            cardType={PlanCardType.Highlighted}
            customer={customer}
            plans={plans}
            onSelectPlan={handleSelectPlan}
          />
        </Layout.Section>
      </Layout>
    </Page>
  );
}

Wrapping it up

That’s it! You now have a Shopify app with Mantle integrated and a plans page. As always, reach out to us if you have any questions!