# Shopify Developer Platform The Shopify developer platform enables developers to create and customize applications, themes, and integrations for Shopify's e-commerce ecosystem. It provides robust APIs, development tools, and extensive documentation to facilitate the building of tailored solutions for merchants. Here are some examples of what developers can build with Shopify: * Build apps that extend the functionality of Shopify stores. For example, apps for inventory management, analytics and reporting, or customer loyalty programs. * Extend Shopify’s checkout with extensions that change its UI or business logic. * Customize a store’s theme to match the merchant’s brand or change the layout. * Build online storefronts that allow buyers to shop in a merchant’s store. * Provide custom admin workflows for merchants that are not included in the Shopify core product. For example, subscription management, email marketing, and live customer support. * Integrate external systems like ERPs, CRMs, accounting systems into Shopify to import/export data. ## Apps Shopify Apps are third-party applications that can be integrated into Shopify stores to enhance functionality and improve the e-commerce experience. These apps cover a wide range of features, including inventory management, marketing tools, customer support, shipping solutions, and analytics, allowing merchants to customize their stores according to their specific needs. Developers can create their own apps using Shopify's APIs and resources, and they can publish them on the Shopify App Store for merchants to discover and install. This ecosystem supports a vibrant community of developers and provides merchants with numerous options to optimize their online businesses. Shopify apps can appear in and add functionality to nearly every area of the Shopify platform. A single app can add functionality to multiple areas of the platform. ### Configuration and shopify.app.toml When you initialize an app using the CLI (shopify app init CLI command) you will receive a folder structure that contains a `shopify.app.toml` file at the root. This file helps you describe what capabilities you want your app to have and Shopify ensures that this app configuration is then instantiated on every shop where the app is installed. You can use scopes to configure the scopes that your app requires, and webhook subscriptions to detail out what events your app should receive. ``` name = "Example App" client_id = "a61950a2cbd5f32876b0b55587ec7a27" application_url = "https://www.app.example.com/" embedded = true handle = "example-app" [access_scopes] scopes = "read_products, write_products" [access.admin] direct_api_mode = "online" [auth] redirect_urls = [ "https://app.example.com/api/auth/callback", "https://app.example.com/api/auth/oauth/callback", ] [webhooks] api_version = "2024-01" [[webhooks.subscriptions]] topics = [ "app/uninstalled" ] compliance_topics = [ "customers/redact", "customers/data_request", "shop/redact" ] uri = "/webhooks" [app_proxy] url = "https://app.example.com/api/proxy" subpath = "store-pickup" prefix = "apps" [pos] embedded = false [app_preferences] url = "https://www.app.example.com/preferences" [build] automatically_update_urls_on_dev = false ``` If you are working with multiple environments (dev, staging, production) it is recommended that you have a different `shopify.app.toml` file for each environment. The Shopify CLI makes this easy by allowing you to link multiple Shopify apps to your codebase, so that you can dedicate specific apps and their configuration for various development, staging, and production workflows. You would create a new configuration using the command `shopify app config link` and then you can tell the CLI to use a specific configuration with the use command and so if you had a TOML configuration called `development` you would say `shopify app config use development` in the CLI. For more, see [App configuration](https://shopify.dev/docs/apps/build/cli-for-apps/app-configuration) and [Manage app config files](https://shopify.dev/docs/apps/build/cli-for-apps/manage-app-config-files). ### Admin API The [GraphQL Admin API](https://shopify.dev/docs/api/admin-graphql) lets you build apps and integrations that extend and enhance the Shopify admin. You can query and manage resources like products, customers, orders, inventory, fulfillment, and more. Because it’s GraphQL, it provides a more flexible, efficient, and controlled way to query and manipulate data than traditional REST APIs. For more on how to work with GraphQL, see [About GraphQL](https://shopify.dev/docs/apps/build/graphql). The Admin GraphQL endpoint URL depends on your shop name and the API version: ``` https://{shop-name}.myshopify.com/admin/api/2025-01/graphql.json ``` #### Authentication Authentication requires both access tokens and specific access scopes depending what resource you need to access. - All GraphQL Admin API queries require a valid Shopify access token. - Public and custom apps created in the Partner Dashboard generate tokens using OAuth, and custom apps made in the Shopify admin are authenticated in the Shopify admin. - Include your token as a `X-Shopify-Access-Token` header on all API queries. - Your app will need the correct [access scopes](https://shopify.dev/api/usage/access-scopes). #### Example queries Get shop information: ``` query { shop { id name email domain createdAt updatedAt } } ``` Get products: ``` query { products(first: 10) { edges { node { id title description variants(first: 5) { edges { node { id price sku } } } } } } } ``` Get orders: ``` query { orders(first: 10) { edges { node { id name totalPrice createdAt lineItems(first: 5) { edges { node { title quantity } } } } } } } ``` Get customers: ``` query { customers(first: 10) { edges { node { id firstName lastName email ordersCount } } } } ``` #### Example mutations Create a product: ``` mutation { productCreate(input: { title: "New Product" bodyHtml: "Good Product" vendor: "Vendor Name" productType: "Type" tags: "tag1, tag2" variants: [{ price: "19.99" sku: "SKU123" }] }) { product { id title } userErrors { field message } } } ``` Update a product: ``` mutation { productUpdate(input: { id: "gid://shopify/Product/1234567890" title: "Updated Product Title" }) { product { id title } userErrors { field message } } } ``` Delete a product: ``` mutation { productDelete(id: "gid://shopify/Product/1234567890") { deletedProductId userErrors { field message } } } ``` #### Best practices * **Paginate results**: Use first, last, after, and before for pagination in queries. * **Error handling**: Always check for userErrors in mutations to handle any issues that may arise. * **Rate limiting**: Be aware of rate limits (typically 2 requests per second) and implement retries or exponential backoff if necessary. * **Use fragments**: For commonly used fields across multiple queries, consider defining fragments to keep your queries DRY. ### Shopify CLI The [Shopify CLI](https://shopify.dev/docs/api/shopify-cli) is a command-line interface tool that helps you generate and work with Shopify apps, themes and custom storefronts. You can also use it to automate many common development tasks. Using the CLI makes it faster and easier to build on Shopify. The general syntax for CLI commands is: ``` shopify [topic] [command] ``` Here are some examples of common commands: * Install the Shopify CLI: `npm install -g @shopify/cli@latest` * Create a new app: `shopify app init` * Serve your app locally: `shopify app dev` * Deploy your app: `shopify app deploy` * Retrieve your theme files from Shopify: `shopify theme pull` * Upload your theme to preview it: `shopify theme dev` * Generate an extension: `shopify app generate extension` You can find all the commands in the Shopify dev docs: * [App commands](https://shopify.dev/docs/api/shopify-cli/app) * [Theme commands](https://shopify.dev/docs/api/shopify-cli/theme) * [Hydrogen commands](https://shopify.dev/docs/api/shopify-cli/hydrogen) * [General commands](https://shopify.dev/docs/api/shopify-cli/general-commands) You can also use `shopify help` to get help within the CLI. ### Polaris Web Components Polaris Web Components are Shopify's unified UI toolkit built on web platform standards. They provide consistent design and functionality across all Shopify surfaces including Admin, Checkout, Customer accounts, and POS. Built with actual web components technology, they're framework-agnostic and work with any JavaScript library or framework. #### Why use Polaris Web Components? We base our design guidelines on some basic principles, so you can build apps that are predictable and easy to use. Here are four key reasons to use Polaris Web Components: * **Built for Shopify**: Apps must meet all directives to qualify for the [Built for Shopify](https://shopify.dev/docs/apps/launch/built-for-shopify) program. * **A better merchant experience**: Merchants expect a predictable user experience that works like the rest of the Shopify admin. * **Framework agnostic**: Works with React, Vue, vanilla JS, or any framework using standard HTML. * **Accessible**: Built-in accessibility features ensure great experiences for all users. * **Consistent**: Use the same components across all Shopify surfaces. #### Setup Polaris Web Components **Required script tag:** ```html ``` **For TypeScript projects:** ```bash npm install -D @shopify/polaris-types@latest ``` **Configure TypeScript:** ```json { "compilerOptions": { "types": ["@shopify/polaris-types"] } } ``` **For React projects:** See our [App template](https://github.com/Shopify/shopify-app-template-react-router). Getting set up with [React router](https://github.com/Shopify/shopify-app-js/blob/main/packages/apps/shopify-app-react-router/src/react/components/AppProvider/AppProvider.tsx#L111-L126) #### Best practices * **Follow accessibility guidelines**: [Ensure your app is accessible](https://shopify.dev/docs/apps/build/accessibility); Polaris components are designed with accessibility in mind. * **Keep design consistent**: Stick to the guidelines provided in the Polaris documentation to maintain a cohesive user experience. * **Use the latest version**: The CDN script automatically provides the latest version of components. #### Common Polaris Web Components You can find all the Polaris web components in the [Polaris documentation](/docs/api/app-home/polaris-web-components). Here are a few of the most common components along with their syntax. ##### Box Box components provide layout and spacing control for content grouping. They're used similarly to cards for organizing content. ```html Content inside a box Additional text content goes here ``` ##### Page Layout Pages are structured using s-page as the main container with sections for content organization. ```html Back Duplicate View Save Credit card information ``` ##### Grid Layout Grid components are used for creating responsive layouts with consistent spacing and alignment. ```html Online store dashboard View a summary of your online store's performance. Analytics Track your store performance. ``` ##### Button Buttons are used in Polaris primarily for actions, such as "Add", "Close", "Cancel", or "Save". ```html Add product Cancel Delete Add product Processing... View products ``` ##### Text Field Text fields are used as input fields that merchants can type into. They support various formats including text, email, and numbers. ```html ``` ##### Checkbox Checkboxes are most commonly used in Polaris to give merchants a way to make a range of selections (zero, one, or multiple). ```html ``` ##### Choice List Choice lists are used to present options where merchants must make a single selection. The choice list automatically handles radio button behavior when multiple=false and checkbox behavior when multiple=true. ```html Hidden Optional Required ``` ##### Additional Common Components **Badge**: Used to highlight status or provide quick visual context. ```html Active Pending Error Featured ``` **Banner**: Used for important messaging that affects the entire page or section. ```html This order was archived on March 7, 2017 at 3:12pm EDT. ``` **Modal**: Used for focused tasks that require user attention. ```html Are you sure you want to delete this product? This action cannot be undone. Delete Cancel ``` **Stack**: Used for flexible layout with consistent spacing. ```html Customer information Email: customer@example.com Phone: +1 (555) 123-4567 Save Cancel ``` ### Polaris Shopify Polaris is the design system used by Shopify to create a consistent user interface across applications. We believe that the best apps provide merchants with a user experience that matches the appearance and behaviors of the Shopify admin UI. Using Polaris lets you achieve that consistency. #### Why follow Polaris? We base our design guidelines on some basic principles, so you can build apps that are predictable and easy to use. Here are four key reasons to follow the guidelines: * **Built for Shopify**: Apps must meet all directives to qualify for the [Built for Shopify](https://shopify.dev/docs/apps/launch/built-for-shopify) program. * **A better merchant experience**: Merchants expect a predictable user experience that works like the rest of the Shopify admin. * **Adaptive:** Designing for mobile devices must be at the forefront of the app building process. * **Accessible**: To provide a great experience for all Shopify merchants and their customers, apps must be built using accessibility best practices. #### Install Polaris ``` npm install @shopify/polaris ``` #### Best practices * **Use components**: Always use Polaris components for consistency and accessibility. * **Follow accessibility guidelines**: [Ensure your app is accessible](https://shopify.dev/docs/apps/build/accessibility); Polaris components are designed with accessibility in mind. * **Keep design consistent**: Stick to the guidelines provided in the Polaris documentation to maintain a cohesive user experience. * **Use the latest version**: Regularly check for updates to Polaris to take advantage of new components and features. #### Common Polaris Components You can find all the Polaris components on [polaris.shopify.com](https://polaris.shopify.com/). Here are a few of the most common components along with their syntax. ##### Card Cards are used in Polaris to group similar concepts and tasks together for merchants to scan, read, and get things done. It displays content in a familiar and recognizable style. ``` import {Card, Text} from '@shopify/polaris'; import React from 'react'; function CardDefault() { return ( Content inside a card ); } ``` ##### Page Pages are used in Polaris to build the outer wrapper of a page, including the page title and associated actions. ``` import {Page, Badge, LegacyCard} from '@shopify/polaris'; import React from 'react'; function PageExample() { return ( Paid} subtitle="Perfect for any pet" compactTitle primaryAction={{content: 'Save', disabled: true}} secondaryActions={[ { content: 'Duplicate', accessibilityLabel: 'Secondary action label', onAction: () => alert('Duplicate action'), }, { content: 'View on your store', onAction: () => alert('View on your store action'), }, ]} actionGroups={[ { title: 'Promote', actions: [ { content: 'Share on Facebook', accessibilityLabel: 'Individual action label', onAction: () => alert('Share on Facebook action'), }, ], }, ]} pagination={{ hasPrevious: true, hasNext: true, }} >

Credit card information

); } ``` ##### Layout The layout component is used in Polaris to create the main layout on a page. Layouts sections come in three main configurations. one-column, two-column, and annotated. ``` import {Page, Layout, LegacyCard} from '@shopify/polaris'; import React from 'react'; function LayoutExample() { return (

View a summary of your online store’s performance.

); } ``` ##### Tabs Tabs are used in Polaris to alternate among related views within the same context. ``` import {LegacyCard, Tabs} from '@shopify/polaris'; import {useState, useCallback} from 'react'; function TabsDefaultExample() { const [selected, setSelected] = useState(0); const handleTabChange = useCallback( (selectedTabIndex: number) => setSelected(selectedTabIndex), [], ); const tabs = [ { id: 'all-customers-1', content: 'All', accessibilityLabel: 'All customers', panelID: 'all-customers-content-1', }, { id: 'accepts-marketing-1', content: 'Accepts marketing', panelID: 'accepts-marketing-content-1', }, { id: 'repeat-customers-1', content: 'Repeat customers', panelID: 'repeat-customers-content-1', }, { id: 'prospects-1', content: 'Prospects', panelID: 'prospects-content-1', }, ]; return (

Tab {selected} selected

); } ``` ##### Button Buttons are used in Polaris primarily for actions, such as “Add”, “Close”, “Cancel”, or “Save”. ``` import {Button} from '@shopify/polaris'; import React from 'react'; function ButtonExample() { return ; } ``` ##### TextField A text field are used in Polaris as input fields that merchants can type into. It has a range of options and supports several text formats including numbers. ``` import {TextField} from '@shopify/polaris'; import {useState, useCallback} from 'react'; function TextFieldExample() { const [value, setValue] = useState('Jaded Pixel'); const handleChange = useCallback( (newValue: string) => setValue(newValue), [], ); return ( ); } ``` ##### Checkbox Checkboxes are most commonly used in Polaris to give merchants a way to make a range of selections (zero, one, or multiple). ``` import {Checkbox} from '@shopify/polaris'; import {useState, useCallback} from 'react'; function CheckboxExample() { const [checked, setChecked] = useState(false); const handleChange = useCallback( (newChecked: boolean) => setChecked(newChecked), [], ); return ( ); } ``` ##### Radio button Radio buttons are used in Polaris to present each item in a list of options where merchants must make a single selection. ``` import {LegacyStack, RadioButton} from '@shopify/polaris'; import {useState, useCallback} from 'react'; function RadioButtonExample() { const [value, setValue] = useState('disabled'); const handleChange = useCallback( (_: boolean, newValue: string) => setValue(newValue), [], ); return ( ); } ``` ### Embedded apps and App bridge The primary place where users engage with your app is its app home. This is the location where merchants are directed when they navigate to your app in Shopify. The Shopify admin provides a surface for apps to render the UX for their app home. On the web, the surface is an iframe and in the Shopify mobile app, the surface is a WebView. By combining Shopify App Bridge and Polaris, you can make your app display seamlessly in the Shopify admin. Polaris enables apps to match the visual appearance of the admin by using the same design components. App Bridge enables apps to communicate with the Shopify admin and create UI elements outside of the app's surface. Such elements include navigation menus, modals that cover the entire screen, and contextual save bars that prevent users from navigating away from the page when they have unsaved changes. #### App Bridge The App Bridge library provides APIs that enable Shopify apps to render UI in the Shopify app home surface. Apps built with Shopify App Bridge are more performant, flexible, and seamlessly integrate with the Shopify admin. You can use Shopify App Bridge with Polaris to provide a consistent and intuitive user experience that matches the rest of the Shopify admin. On the web, your app renders in an iframe and in the Shopify mobile app it renders in a WebView. The latest version of App Bridge is built on top of web components and APIs to provide a flexible and familiar development environment. Your app can invoke these APIs using vanilla JavaScript functions. App Bridge enables you to do the following from your app home: * Render a navigation menu on the left of the Shopify admin ``` Home Templates Settings ``` * Render a contextual save bar above the top bar of the Shopify admin ``` ``` * Render a title bar with primary and secondary actions ``` ``` ### Checkout UI extensions [Checkout UI Extensions](https://shopify.dev/docs/api/checkout-ui-extensions) allow developers to customize the checkout experience for Shopify stores. They allow merchants to add custom fields, promotional messages, and more. #### Key concepts * [**Extension targets**](https://shopify.dev/docs/api/checkout-ui-extensions/2025-01/extension-targets-overview): Extension targets provide locations where merchants can insert custom content. * **Static extension targets** are tied to core checkout features like contact information, shipping methods, and order summary line items. * **Block extension targets** can be displayed at any point in the checkout process and will always render regardless of which checkout features are available. * **Configuration file**: The `shopify.extension.toml` contains the extension's configuration, which includes the extension name, extension targets, metafields, capabilities, and settings definition. * [**Extension APIs**](https://shopify.dev/docs/api/checkout-ui-extensions/2025-01/apis): APIs enable checkout UI extensions to get information about the checkout or related objects and to perform actions * [**UI components**](https://shopify.dev/docs/api/checkout-ui-extensions/2025-01/components): Checkout UI extensions declare their interface using supported UI components. Shopify renders the UI natively, so it's performant, accessible, and works in all of checkout's supported browsers. * **Security**: Checkout UI extensions are a safe and secure way to customize the appearance and functionality of the checkout page without compromising the security of checkout or customer data. #### Create a new extension To create a new extension, use the Shopify CLI: ``` shopify app generate extension ``` #### Common components ##### View View in checkout UI extensions is a generic container component. Its contents will always be their “natural” size, so this component can be useful in layout components. ``` import { reactExtension, View, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { return ( View ); } ``` ##### InlineLayout InlineLayout in checkout UI extensions is used to lay out content over multiple columns. ``` import { reactExtension, InlineLayout, View, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { return ( 20% fill ); } ``` ##### Button Buttons in checkout UI extensions are used for actions, such as “Add”, “Continue”, “Pay now”, or “Save”. ``` import { reactExtension, Button, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { return ( ); } ``` ##### Link Links in checkout UI extensions make text interactive so customers can perform an action, such as navigating to another location. ``` import { reactExtension, Link, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { return ( Sustainability fund ); } ``` ##### Modal Modals in checkout UI extensions are a special type of overlay that shift focus towards a specific action/set of information before the main flow can proceed. ``` import { reactExtension, useApi, Button, Link, Modal, TextBlock, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { const {ui} = useApi(); return ( We have a 30-day return policy, which means you have 30 days after receiving your item to request a return. } > Return policy ); } ``` ##### Banner Banners in checkout UI extensions are used to communicate important messages to customers in a prominent way. ``` import { reactExtension, Banner, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { return ( ); } ``` ### Admin UI extensions An [admin UI extension](https://shopify.dev/docs/api/admin-extensions) is a JavaScript-based module that can hook in to client-side behaviors on any of Shopify’s first-party UI surface areas. These extensions enable your app to embed workflows and UX on core admin pages while automatically matching the Shopify admin's look and feel. Shopify provides different “variants” of UI extension APIs that are suitable for different developers: * [@shopify/ui-extensions](https://github.com/Shopify/ui-extensions/blob/unstable/packages/ui-extensions) lets developers use a small, strongly-typed JavaScript API for creating UI extensions. * [@shopify/ui-extensions-react](https://github.com/Shopify/ui-extensions/blob/unstable/packages/ui-extensions-react) lets developers create UI extensions using [React](https://reactjs.org/). #### Types of admin extensions * **Admin actions**: Admin action extensions enable you to create transactional workflows within existing pages of the Shopify admin. Merchants can launch these extensions from the More actions menus on resource pages or from an index table's bulk action menu when one or more resources are selected. * **Admin blocks**: Admin block extensions enable your app to embed contextual information and inputs directly on resource pages in the Shopify admin. When a merchant has added them to their pages, these extensions display as cards inline with the other resource information. With admin block extensions, merchants can view and modify information from your app and other data on the page simultaneously. To facilitate complex interactions and transactional changes, you can launch admin actions directly from an admin block. * **Admin print actions**: Admin print actions extensions are a special form of action extension designed to let your app print documents from key pages in the Shopify admin. Unlike a typical admin action extension, these extensions are found under the Print menu on orders and product pages. #### Create a new admin extension To create a new extension, use Shopify CLI: ``` shopify app generate extension ``` ##### Deploy an admin extension To deploy an admin extension, run this within your app's directory: ``` npm run deploy ``` #### Example: Build an admin action In this example, we create an extension’s UI and render it. First, we’ll create a `shopify.extension.toml` file that targets `admin.product-details.action.render`: ``` api_version = "2025-01" [[extensions]] # Change the merchant-facing name of the extension in locales/en.default.json name = "t:name" handle = "issue-tracker-action" type = "ui_extension" [[extensions.targeting]] module = "./src/ActionExtension.jsx" # The target used here must match the target used in the module file (./src/ActionExtension.jsx) target = "admin.product-details.action.render" ``` Next, we set the title of the page in `/locales/en.default.json`: ``` { "name": "Create an issue" } ``` Then, in `/src/ActionExtension.jsx` we’ll import the necessary components from Remote UI: ``` import { reactExtension, useApi, TextField, AdminAction, Button, TextArea, Box, } from "@shopify/ui-extensions-react/admin"; ``` Then we’ll build out the file with the target, logic, and UI rendering: ``` import { useCallback, useEffect, useState } from "react"; import { reactExtension, useApi, TextField, AdminAction, Button, TextArea, Box, } from "@shopify/ui-extensions-react/admin"; import { getIssues, updateIssues } from "./utils"; function generateId (allIssues) { return !allIssues?.length ? 0 : allIssues[allIssues.length - 1].id + 1; }; function validateForm ({title, description}) { return { isValid: Boolean(title) && Boolean(description), errors: { title: !title, description: !description, }, }; }; // The target used here must match the target used in the extension's .toml file at ./shopify.extension.toml const TARGET = "admin.product-details.action.render"; export default reactExtension(TARGET, () => ); function App() { //connect with the extension's APIs const { close, data } = useApi(TARGET); const [issue, setIssue] = useState({ title: "", description: "" }); const [allIssues, setAllIssues] = useState([]); const [formErrors, setFormErrors] = useState(null); const { title, description } = issue; useEffect(() => { getIssues(data.selected[0].id).then(issues => setAllIssues(issues || [])); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const onSubmit = useCallback(async () => { const {isValid, errors} = validateForm(issue); setFormErrors(errors); if (isValid) { // Commit changes to the database await updateIssues(data.selected[0].id, [ ...allIssues, { id: generateId(allIssues), completed: false, ...issue, } ]); // Close the modal using the 'close' API close(); } }, [issue, data.selected, allIssues, close]); return ( Create } secondaryAction={} > setIssue((prev) => ({ ...prev, title: val }))} label="Title" maxLength={50} />