Blog · · 9 min

Replace Shopify apps with code you own

The case for replacing an app with a component is not the monthly fee. It is that an app is a tenant: it renders inside your page, it can price per order rather than per month, and uninstalling it can take page content with it. The case against is honest too — some apps reach surfaces your code cannot.

By

Three properties separate an app from a component, and only one of them is the price.

  1. A component leaves nothing behind. You delete a file. An app is installed into your theme, and several of the loudest complaints in public app reviews are about uninstalling taking page content with it — pages that had been rebuilt natively, gone.
  2. A component is charged once. Several upsell apps charge per order, which means you pay on orders the widget did not influence. That is a different economics from a monthly fee, and it scales against you exactly when the store starts working.
  3. A component does not have a second customer. An app's business is not only you. The extreme end of that is an app monetising your checkout page with someone else's offer, and there are apps that state the per-order revenue share openly as a feature.

None of that means "never install an app". It means the decision has three axes and most people only look at the first.

When is the app still the right answer?

Say this plainly, because the opposite argument is usually made by someone selling components.

When the app reaches a surface your code cannot. On a hosted checkout you do not control the post-purchase page, the checkout extension points or the payment step. If the mechanic lives there, an app is not a preference, it is the only implementation.

When the app carries compliance you would otherwise own. Tax calculation, age verification in a regulated category, accessibility statements tied to a jurisdiction. Owning the code means owning the obligation to keep it correct.

When it exists this afternoon and your component does not. A store with no upsell mechanic at all learns more from a rented widget running for three weeks than from a perfect component that is still being written. Build the owned version once you know the mechanic matters for your catalogue.

When it is genuinely one of a kind. A review platform with a verified-buyer network, a shipping rate engine with live carrier contracts. Those are not components, they are services.

What are you actually replacing?

Most stores have between four and eight apps, and the list is remarkably consistent. Split it into three columns before touching anything.

App categoryVerdictWhy
Quantity breaks / volume discountreplacepure front-end mechanic, it is a radio group
Free shipping progress barreplaceone sentence and an arithmetic threshold
Cart upsell / order bumpreplacea checkbox above the totals, with legal constraints you own anyway
Sticky add to cartreplaceone observer, no dependency
Countdown / urgencyreplace or deleteif it is honest it needs a server date; if it is not, delete it
Trust badge / icon packsdeletean unverifiable badge is not a feature
Post-purchase upsell on hosted checkoutkeepyou cannot reach that surface
Tax, duties, carrier rateskeepa service, not a component
Reviews with verified-buyer networkkeepthe network is the product
Page builderdecidesee below, this is the load-bearing one

The four "replace" rows at the top are the common case and they are all the same shape: a piece of interface, a small amount of state, no external data. They are components that were sold as software because there was no other way to deliver them to a hosted store.

![A brass key and a rent receipt on dark slate, the receipt stamped MONTHLY, beside a second key cut from steel with a small paper tag reading OWNED.](/blog/deux-cles.webp "The fee is the visible cost. The invisible one is that a tenant renders inside your page, and can leave it damaged when it goes.")

The page builder is the decision that matters

It is the app that is hardest to leave, because it does not add a widget — it owns your pages. Pages built in it are stored in its own format, rendered by its own runtime, and the exit path is rebuilding them.

That is the property to weigh before installing one, not after. The question is not what it costs per month; it is what a page looks like the day the subscription stops. If the answer is "an empty page", the monthly fee is not the price. It is the deposit.

A component approach answers that differently: the output is HTML in your theme or your repository. It renders with no runtime of its own, and it is still there if you stop paying whoever generated it. That is the argument, and it is the same argument whether the generator is a marketplace, an agency or an MCP server — including ours.

How do you replace one, concretely?

Take the free-shipping bar, which is the smallest. The app version is a script tag, a settings panel and a monthly line on your invoice. The owned version is a component, a threshold you computed from your own margin, and nothing else.

// The whole contract. No settings panel, no script tag, no account.
type Props = {
  subtotalCents: number;
  thresholdCents: number;
  currency: string;
  /** below this share of the goal, render nothing at all */
  showFrom?: number;
};

export function ShippingThreshold({
  subtotalCents, thresholdCents, currency, showFrom = 0.4,
}: Props) {
  const ratio = subtotalCents / thresholdCents;
  if (subtotalCents === 0 || ratio < showFrom) return null;

  const fmt = new Intl.NumberFormat(undefined, { style: "currency", currency });
  if (ratio >= 1) return <p role="status">Free shipping unlocked.</p>;

  const missing = fmt.format((thresholdCents - subtotalCents) / 100);
  return (
    <p role="status" aria-live="polite" className="threshold">
      <strong>{missing}</strong> to unlock free shipping
    </p>
  );
}

The threshold itself is the part the app could never get right, because it depends on your margin rather than on a round number:

// Not a number you liked. A number your margin can pay for.
export function threshold(medianOrderCents: number, shipCents: number, marginRate: number) {
  const extraSpend = shipCents / marginRate;
  return Math.ceil((medianOrderCents + extraSpend) / 500) * 500;
}
// threshold(3800, 600, 0.55) → 5000  (€50.00)
// threshold(3800, 600, 0.30) → 6000  (€60.00)

Same store size, same shipping cost, ten euros of difference purely from margin. A threshold copied from a competitor is a threshold copied from someone else's margin. The rest of the reasoning, including when the bar should not render at all, is in the free shipping threshold bar.

What does removal actually cost?

Budget for the three things that are not the code.

  • The settings you never wrote down. Thresholds, tier percentages, copy, exclusion rules — all of it lives in someone's admin panel. Export or screenshot before you cancel, not after.
  • The theme residue. App blocks and script tags can remain in your theme after removal. Search the theme for the app's handle and remove it by hand, then check a cached page rather than a fresh one.
  • A period where both run. Two free-shipping bars on the same cart is worse than either. Ship the component, verify it on the live cart, then uninstall — with the settings already saved somewhere you can read them.

The order to do it in

  1. Delete first. Anything unverifiable — badge packs, fake urgency, visitor counters. Deleting costs nothing and removes the weakest elements on the page.
  2. Replace the pure front-end mechanics, cheapest first: sticky add-to-cart, then the shipping bar, then the tier selector, then the cart bump.
  3. Keep the services. Tax, rates, verified reviews, anything reaching a surface you do not control.
  4. Decide on the page builder deliberately, and decide it against the question of what the pages look like when you stop paying.

Most stores finish that list with two or three apps instead of seven, and the ones that remain are the ones actually doing something a component cannot.

If you want the replacements produced by your coding agent rather than written by hand, that is what uxgen is for: an MCP server that hands Claude the commerce components and returns HTML you own, with no per-order fee and nothing to uninstall. Several of them are open, MIT, in the commerce kit.

FAQ

Is it worth replacing Shopify apps with custom code?

For pure front-end mechanics — volume discounts, shipping progress bars, sticky add-to-cart, cart bumps — usually yes, because they are small components with no external data and the recurring cost buys you nothing after the first month. For services with a network or a live data feed behind them, such as carrier rates, tax calculation or verified-buyer reviews, the app is doing something your code cannot.

What is the risk of uninstalling a page builder app?

Pages built inside it are stored in its format and rendered by its runtime, so removing the app can leave those pages empty or broken, including pages that were later rebuilt natively. That risk should be weighed before installing rather than after, by asking what a page looks like the day the subscription stops.

Why do some upsell apps charge per order?

Because their pricing is indexed to your revenue rather than to their cost. The practical consequence is that you pay on orders the widget had no part in, and the bill grows fastest exactly when the store starts working. A component you own carries the opposite shape: one build, no variable cost.

In what order should I remove apps from my store?

Delete the unverifiable ones first, since that costs nothing and improves the page immediately. Then replace the front-end mechanics from cheapest to most complex, running the component alongside the app for long enough to verify it on a live cart. Keep anything that reaches a checkout surface you do not control, and treat the page builder as a separate, deliberate decision.

uxgen is a service of UXGen AI, LLC — 131 Continental Dr, Suite 305, Newark, DE 19713, United States.

© 2026 UXGen AI, LLC. All rights reserved.