Shopify app remix template billing example

I have implemented a solution for this issue. While I’m not entirely certain if it is the optimal approach, it is functioning as expected.

Within the shopify.server.js file, I included a function that retrieves the current active subscriptions using GraphQL, as follows:

/// .... more things on shopify.server.js
export const sessionStorage = shopify.sessionStorage;

const CACHED_SUBSCRIPTIONS: {
  [key: string]: {
    plan: string;
    timestamp: number;
  }
} = {};

export const getPlan = async (session: Session) => {
  // get cached charge if it exists and it is not expired
  if (
    CACHED_SUBSCRIPTIONS[session.shop] &&
    Date.now() - CACHED_SUBSCRIPTIONS[session.shop].timestamp < 1000 * 60 * 5) {
    return CACHED_SUBSCRIPTIONS[session.shop];
  }

  // get the active subscription from graphql
  const query = `#graphql
    {
      currentAppInstallation {
        activeSubscriptions {
          name
        }
      }
    }
  `;
  const {data} = await performQuery(session, query, {});

  // if there are no active subscriptions then return false
  if (data.currentAppInstallation.activeSubscriptions.length === 0) return false;

  // save current subscription in cache
  const subscription = {
    plan: data.currentAppInstallation.activeSubscriptions[0].name,
    timestamp: Date.now()
  }
  CACHED_SUBSCRIPTIONS[session.shop] = subscription;

  // return the current subscription
  return subscription;
}

Subsequently, in the app.jsx file, I perform a check to verify if there is an active subscription plan. If no active plan is found, the user is redirected to the managed charges page provided by Shopify:

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

  const currentPlan = await getPlan(session);

  if (!currentPlan)
    throw redirect(
      `https://admin.shopify.com/store/${session.shop.replace(".myshopify.com", "")}/charges/${process.env.APP_HANDLE}/pricing_plans`,
      { target: "_parent" }
    );

  return json({ apiKey: process.env.SHOPIFY_API_KEY || "" });
};

Please note that the redirect I am utilizing comes from authenticate.admin, rather than directly from Remix.

I hope this information is helpful.