Skip to main content

Extension Points

A checkout UI extension will register for one or more extension points using shopify.extend(). An extension point in a UI extension is a plain JavaScript function. This function receives an API object for interacting with the application, and is expected to return a value in a specific shape. The input arguments and the output type are different for each extension point.


Anchor to static-extension-pointsStatic extension points

Static extension points render immediately before or after most core checkout features such as contact information, shipping methods, and order summary line items. Merchants use the checkout editor to activate and place the extension in the checkout experience.

When a core checkout feature isn't rendered, neither are the static extension points tied to it. For example, shipping methods aren't shown when customers select the option for store pickup and the UI extensions that load before or after the shipping method aren't rendered.

Choose static extension points when your content and functionality is closely related to a core checkout feature. An example is a shipping delay notice.

Anchor to dynamic-extension-pointsDynamic extension points

Dynamic extension points render between core checkout features. Merchants can use the checkout editor to place the extension in any one of the supported locations for the dynamic extension point.

When a checkout feature for that location is hidden, dynamic extensions are still rendered. For example, an extension placed above the shipping address will still render even for digital products which do not require a shipping address.

Choose dynamic extension points when your content and functionality works independently of a core checkout feature. An example is a field to capture order notes from the customer.

Checkout is where buyers go to purchase goods. Checkout consists of the information, shipping, and payment steps in addition to the order summary and Shop Pay. Learn more about building custom functionality for checkout.

This is the first step in the checkout process where the buyer enters contact information and a delivery address.

See all extensions points.

Point in checkout where the buyer selects a shipping method.

See all extensions points.

Point in checkout where the buyer enters their payment information.

See all extensions points.

Summary of the cart contents, discounts, and order totals.

See all extensions points.

Accelerated checkout where Shopify pre-fills buyer information using their Shop Pay account.

See all extensions points.

Point in checkout where the buyer can select a store location to pick up their purchase.

See all extensions points.

Point in checkout where the buyer can select a pickup point to have their purchase delivered to.

See all extensions points.

DEV PREVIEW

All checkout pages (information, shipping, and payment) are combined into a single page with the order summary.

Get started testing extensions on one-page checkout.

The thank you page is shown to buyers immediately after a checkout is successfully submitted. Learn more about building for the thank you page.

Displays all order information to buyers.

See all thank you page extension points.

Summary of the cart contents, discounts, and order totals.

See all thank you page extensions points.

Anchor to supported-osp-locationsOrder status locations

The order status page is shown to buyers when they return to a completed checkout for order updates. Learn more about building for the order status page.

Displays all order information to buyers.

See all order status page extension points.

Summary of the cart contents, discounts, and order totals.

See all order status page extensions points.

The checkout-ui-extensions library provides an alias for shopify.extend in the form of the extend() export. This function is also strongly-typed. If you’re working in an editor that supports TypeScript’s language server (we recommend VSCode), then you get feedback about the input arguments to that extension point.

For extensions that render UI, such as Checkout::Dynamic::Render, the first argument is always a @remote-ui RemoteRoot object that enables you to render UI components into your extension point in checkout. You don't need to explicitly call mount() on this object. After the callback that you registered for the extension point ends, or if it returns a Promise that resolves, your initial UI is rendered.

Anchor to Web platform globalsWeb platform globals

Checkout UI extensions always run in a web worker. This environment has access to many of the same globals as you’d get with JavaScript running in a browser. However, we only guarantee the presence of the following globals:

  • self, a reference back to the global object.
  • console, which is the same console available in the browser and can be used for printing to the browser’s console. Your app shouldn’t log any content when running in production.
  • setTimeout, clearTimeout, setInterval, and clearInterval, which behave the same as they do outside a web worker
  • fetch and related globals (Headers, Request, and Response), which can be used to make HTTPS requests to arbitrary endpoints. Any requests you make must explicitly support cross-origin resource sharing (CORS), just as they would if the request were coming from fetch() outside of a web worker.
Caution

You must not rely on any other globals being available. Many will be explicitly overwritten to be undefined in the sandbox, and non-language globals that aren’t hidden and aren’t in the list above may also be overwritten at any time.

Anchor to JavaScript environmentJavaScript environment

The sandbox that loads your extension guarantees all of the globals available in ECMAScript 2015 (ES2015). This includes Set, Map, Promise, Symbol, and more. You should rely on these globals directly when you need them, and you shouldn't use your own polyfill for any of these features. If you use globals added after ES2015, or new static methods on globals added after ES2015 (like Object.entries), then you must polyfill your usage of these features.

Your UI extension shouldn't ship any ES2015 (or newer) syntax, like class, const/let, or for..of loops. This syntax isn't understood by some of the browsers that checkout supports. If you use these features in your source code, then make sure that they're compiled to ES5 syntax in your final JavaScript file.

The UI extension sandbox makes a regeneratorRuntime instance available globally. This object is provided by regenerator-runtime, and is used by many compilers to provide an ES5-compatible compilation target for generator functions and async/ await. If you use generators or async/ await, then make sure you compile it down to code that uses regenerator-runtime, and make sure you don't import your own version of that polyfill.

Extend()

import {
extend,
Banner,
} from '@shopify/checkout-ui-extensions';

extend(
'Checkout::Dynamic::Render',
(root, api) => {
root.appendChild(
root.createComponent(
Banner,
{},
`Extension version: ${api.extension.version}`,
),
);
},
);