Close

Sign up to Gadget

Introducing support for customer account UI extensions in Gadget

-

About

Build extensions for customer accounts easily with the ability to process and aggregate data without the hassle of setting up your infrastructure

Problem

Solution

Result

Introducing support for customer account UI extensions in Gadget

Emma Hyde
May 27, 2024

TL;DR: Build extensible customer accounts with new built-in authentication roles in Gadget.

Customer account UI extensions are one of the new ways for Shopify merchants to customize the post-checkout experience in their store. This new variety of extensions offers a chance for developers to support merchants by building opportunities for engagement, communication, and overall smoother customer experiences.

Shopify first introduced new customer accounts back in early 2023 to make it easier for customers to manage order tracking, returns, subscriptions, loyalty programs, reviews, and any other personalizations merchants choose to introduce. Extensibility however, was only recently introduced.

Although Shopify allows you to build extension-only apps that do not require any database, servers or hosting, there are a few things you cannot do natively. If you’re hoping to do any kind of custom processing or aggregations on store data, you’ll need to have the infrastructure to host it. And with customer account UI extensions, if you're building things like custom loyalty programs, there’s a good chance that data aggregation is exactly what you’re looking to do. 

Thankfully, Gadget gives you full-stack infrastructure out of the box, so you can easily process and aggregate data as you need, without dealing with the headache of setting up an app from scratch.

Working with customer account UI extensions in Gadget

The primary difference to keep in mind when building for customer accounts is the changes to authentication. Normally, most Shopify apps have two roles. You either have merchants, with their own set of permissions, and unauthenticated users such as storefront shoppers, who have not signed in to a store and typically have much more limited capabilities. But by giving customers the option to make changes to their accounts and all the orders associated with them, developers building with customer account UI extensions need to create a third role: <inline-code>shopify-storefront-customers<inline-code>.

In Gadget, you can enable customer account authentication when setting up a Shopify connection. This will automatically create the <inline-code>shopify-storefront-customers<inline-code> access role for your app, and grants that role read access to any Shopify customer data. (See our docs for the complete list of customer models!).

Multitenancy is also handled automatically for these customer models. Tenancy filters, written in Gelly, Gadget’s data access language, are added automatically in <inline-code>access-control/permissions<inline-code> and the <inline-code>preventCrossShopDataAccess<inline-code> function found in Shopify model actions will handle both customer and shop tenancy.

With the new access role set up and multitenancy handled out of the box, the final step is to actually make API calls from within the customer account UI extension. You can install your Gadget app’s API client in the extension and then use it to send requests to your backend. Any requests sent with an <inline-code>Authorization: ShopifySessionToken <token><inline-code> header from within a customer account UI extension will now be assigned the <inline-code>shopify-storefront-customers<inline-code> role. 

A new way to manage session tokens in extensions

To make it easier to register a session token with a Gadget API client in Shopify extensions, we have also built a <inline-code>@gadgetinc/shopify-extensions<inline-code> package. After installing this package in your extension, you can make use of the <inline-code>Provider<inline-code> to register the session token on your app’s API client. A <inline-code>useGadget<inline-code> React hook is also available and gives you the updated API client, and a <inline-code>ready<inline-code> boolean you can use to check the status of the client.

For example, when building a customer account UI menu action extension:

import { useEffect } from "react";
import {
  Button,
  reactExtension,
  useApi,
} from "@shopify/ui-extensions-react/customer-account";
import { Provider } from "@gadgetinc/shopify-extensions";
import { useFindOne } from "@gadgetinc/react";
import { Client } from "@gadget-client/example-app";

// initialize a new Client for your Gadget API
const api = new Client();

// the Provider is set up in the reactExtension() initialization function
export default reactExtension(
  "customer-account.order.action.menu-item.render",
  () => <GadgetUIExtension />
);

// component to set up the Provider with the sessionToken from Shopify
function GadgetUIExtension() {
  const { sessionToken } = useApi();

  return (
    <Provider api={api} sessionToken={sessionToken}>
      <MenuActionExtension />
    </Provider>
  );
}

function MenuActionExtension() {
  // get the 'api' client and a 'ready' boolean from the useGadget hook
  const { api, ready } = useGadget();
  const { orderId } = useApi();

  // the useFindOne hook gets the issueId (a custom field on order)
  // of the current order from the Gadget API
  const [{ data: orderIssue, fetching, error }] = useFindOne(
    api.shopifyOrder,
    orderId.split("/").pop(),
    {
      select: {
        issueId: true,
      },
      // use ready to pause hooks until the API client is ready to make authenticated requests
      pause: !ready,
    }
  );

  // do not display anything if the data is still being fetched or there is an error
  if (fetching) return null;
  if (error) {
    console.error(error);
    return null;
  }

  // disable the button if an issue has already been reported
  return (
    <Button disabled={!!orderIssue.issueId}>
      {orderIssue.issueId ? "Report submitted" : "Report a problem"}
    </Button>
  );
}

If you aren’t using React to build extensions, there is also a <inline-code>registerShopifySessionTokenAuthentication<inline-code> function that will register the token on an API client.

And <inline-code>@gadgetinc/shopify-extensions<inline-code> isn’t limited to customer account UI extensions. It can also be used with other extension types, including checkout UI extensions.

Check out our documentation for more information on working with customer account UI extensions and the <inline-code>@gadgetinc/shopify-extensions<inline-code> package.

Although they’re still in developer preview, customer account UI extensions have introduced a new suite of opportunities, including the ability to build for B2B merchants. So if you haven’t already started building with them, now is the time.

If you have any questions on getting started with customer account UI extensions, you can always connect with other Shopify developers over on our community Discord.

Watch a tutorial on working with customer account UI extensions in Gadget:

Interested in learning more about Gadget?

Join leading agencies making the switch to Gadget and experience the difference a full-stack platform can make.
Keep reading to learn about how it's built

Under the hood

We're on Discord, drop in and say hi!
Join Discord
Bouncing Arrow