The Custom App Advantage

Shopify's app ecosystem has over 8,000 apps in the marketplace, yet many growing merchants find themselves stitching together three or four apps to achieve a single workflow โ€” paying recurring fees for each, dealing with conflicts, and accepting data models that don't fit their business. A custom Shopify app eliminates all of that.

Whether you need tight ERP integration, a workflow automation spanning multiple Admin objects, or a buyer-facing experience the Liquid theme system can't deliver, a purpose-built app is the right call.

Choosing Your App Type

Shopify supports two primary app models, and picking the wrong one early is expensive to undo:

Custom Apps (Single-store, no distribution)

If the app is for a single store and will never be listed in the App Store, use a Custom App installed directly from the Shopify Admin. No OAuth dance, no app listing, no review process. API credentials are generated per-store and rotated on demand. This is the fastest path for merchant-specific automation.

Public Apps (OAuth, distributable)

Public apps authenticate via OAuth 2.0, can be installed on any store, and appear in the Shopify App Store. They require a hosted backend that handles the OAuth callback, stores access tokens securely, and processes Shopify webhooks reliably.

Our RecommendationStart with a Custom App. If distribution becomes a requirement later, migrating to a Public App is straightforward โ€” you're adding OAuth on top of an already-working integration.

REST API vs GraphQL Admin API

Shopify offers both a REST Admin API and a GraphQL Admin API. Shopify has been deprecating REST endpoints in favour of GraphQL since 2024, and new surface areas (Metaobjects, Markets, B2B) are GraphQL-only from day one.

GraphQL in Practice

const GET_PRODUCTS = `
  query GetProducts($first: Int!) {
    products(first: $first) {
      edges {
        node {
          id
          title
          variants(first: 5) {
            edges {
              node {
                id
                price
                inventoryQuantity
              }
            }
          }
        }
      }
    }
  }
`;

const response = await fetch(
  `https://${shop}/admin/api/2024-04/graphql.json`,
  {
    method: 'POST',
    headers: {
      'X-Shopify-Access-Token': accessToken,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ query: GET_PRODUCTS, variables: { first: 10 } }),
  }
);
Rate LimitsGraphQL uses a cost-based throttle โ€” calculated query points per second. Avoid requesting deeply nested associations you don't need. Every nested edge multiplies cost.

Theme App Extensions

If your app needs to render UI on the storefront (product pages, cart, checkout), Theme App Extensions are the correct approach. They inject app blocks into Online Store 2.0 themes without touching theme code โ€” meaning merchants can update their theme without breaking your app.

  • Create an extensions/ directory in your app with a .liquid block file
  • Merchants add your block via the Theme Editor drag-and-drop interface
  • App proxy endpoints serve dynamic data back to the block via JavaScript fetch calls

Checkout Extensions (Checkout Extensibility)

Post-purchase upsells, custom delivery instructions, loyalty points at checkout โ€” these are now built with Checkout Extensions using Shopify's UI Extensions framework. React-based components render natively inside Shopify's checkout with access to the Checkout Branding API for styling.

import { useSettings, Banner } from "@shopify/ui-extensions-react/checkout";

export function DeliveryNote() {
  const { noteLabel } = useSettings();
  return (
    <Banner title={noteLabel || "Delivery Instructions"}>
      <TextField label="Note for delivery driver" />
    </Banner>
  );
}

Webhooks and Event-Driven Architecture

Design your Shopify app around webhooks rather than polling. Subscribe to the events you care about โ€” orders/create, products/update, customers/create โ€” and process them asynchronously with a queue to handle spikes during flash sales without timeouts.

Always verify the HMAC signature on every incoming webhook before processing:

import crypto from 'crypto';

function verifyWebhook(rawBody, hmacHeader, secret) {
  const digest = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('base64');
  return crypto.timingSafeEqual(
    Buffer.from(digest),
    Buffer.from(hmacHeader)
  );
}

Embedded App Architecture

Most Shopify apps render inside the Admin via an iframe using App Bridge. App Bridge handles session tokens, navigation, modals, and toasts โ€” it's the communication layer between your app's iframe and the Shopify Admin shell. Always use App Bridge's authenticatedFetch for API calls from the frontend to avoid CORS and session issues.


A well-built Shopify app feels invisible to the merchant โ€” it just works, handles edge cases gracefully, and stays out of the way of Shopify's own upgrade cycle. Getting the app type, API strategy, and webhook architecture right from the start is how you achieve that reliability.

Ready to Build Your Shopify App?

From private automation tools to distributable App Store products, we architect and build Shopify apps that scale with your business.

See Shopify Services