--- title: Admin UI extensions description: > Admin UI extensions make it possible to surface contextual app functionality within the Shopify Admin interface. api_version: 2024-01 api_name: admin-extensions source_url: html: 'https://shopify.dev/docs/api/admin-extensions/2024-01' md: 'https://shopify.dev/docs/api/admin-extensions/2024-01.md' --- # Admin UI extensions Admin UI extensions make it possible to surface contextual app functionality within the Shopify Admin interface. ## Getting started Use the Shopify CLI to [generate a new extension](https://shopify.dev/apps/tools/cli/commands#generate-extension) within your app. If you already have a Shopify app, you can skip right to the last command shown here. ![Admin extension example](https://shopify.dev/assets/assets/images/api/admin-extensions/2023-10/action-extension-example-D3UyRVWo.gif) ## Generate an extension ## CLI ```bash # scaffold an app if you don't already have one: npm init @shopify/app@latest --name my-app # navigate to your app's root directory: cd my-app # generate a new extension: npm run generate extension # follow the steps to create a new # extension in ./extensions. ``` *** ## App authentication Admin UI extensions can also make authenticated calls to your app's backend. When you use `fetch()` to make a request to your app's configured auth domain or any of its subdomains, an `Authorization` header is automatically added with a Shopify [OpenID Connect ID Token](https://shopify.dev/docs/api/app-bridge-library/reference/id-token). There's no need to manually manage session tokens. Relative URLs passed to `fetch()` are resolved against your app's `app_url`. This means if your app's backend is on the same domain as your `app_url`, you can make requests to it using `fetch('/path')`. ## Make requests to your app's backend ## Get Product Data ```tsx import {reactExtension, useApi, Text} from '@shopify/ui-extensions-react/admin'; import {useEffect, useState} from 'react'; // Get product info from app backend async function getProductInfo(id) { const res = await fetch(`/api/products/${id}`); return res.json(); } const TARGET = 'admin.product-details.block.render'; export default reactExtension(TARGET, () => ); function App() { // Contextual "input" data passed to this extension: const {data} = useApi(TARGET); const productId = data.selected?.[0]?.id; const [productInfo, setProductInfo] = useState(); useEffect(() => { getProductInfo(productId).then(setProductInfo); }, [productId]); return Info: {productInfo?.title}; } ``` *** ## Direct API access You can make Shopify Admin API requests directly from your extension using the [query API](https://shopify.dev/docs/api/admin-extensions/api/standard-api#standardapi-propertydetail-query) or the standard [web fetch API](https://developer.mozilla.org/en-US/docs/Web/API/fetch)! Any `fetch()` calls from your extension to Shopify's Admin GraphQL API are automatically authenticated by default. These calls are fast too, because Shopify handles requests directly. Direct API requests use [online access](https://shopify.dev/docs/apps/auth/oauth/access-modes#online-access) mode by default. If you want to use [offline access](https://shopify.dev/docs/apps/auth/oauth/access-modes#offline-access) mode, you can set the `direct_api_mode` property to `offline` in your [app TOML file](https://shopify.dev/docs/apps/tools/cli/configuration#admin). Note: Direct API can't be used to manage storefront access tokens. [Developer guide - Learn more about access scopes](https://shopify.dev/docs/api/usage/access-scopes) ## Query Shopify data ##### Fetch Product data ```tsx import {reactExtension, useApi, Text} from '@shopify/ui-extensions-react/admin'; import {useEffect, useState} from 'react'; async function getProduct(id) { const res = await fetch('shopify:admin/api/graphql.json', { method: 'POST', body: JSON.stringify({ query: ` query GetProduct($id: ID!) { product(id: $id) { title } } `, variables: {id}, }), }); return res.json(); } const TARGET = 'admin.product-details.block.render'; export default reactExtension(TARGET, () => ); function App() { // Contextual "input" data passed to this extension: const {data} = useApi(TARGET); const [product, setProduct] = useState(); useEffect(() => { const productId = data.selected?.[0]?.id; getProduct(productId).then(({data}) => setProduct(data.product)); }, [data]); return The selected product title is {product?.title}; } ``` ##### Query Product data ```tsx import {reactExtension, useApi, Text} from '@shopify/ui-extensions-react/admin'; import {useEffect, useState} from 'react'; const TARGET = 'admin.product-details.block.render'; export default reactExtension(TARGET, () => ); function App() { // Contextual "input" data passed to this extension: const {data, query} = useApi(TARGET); const [product, setProduct] = useState(); useEffect(() => { const productId = data.selected?.[0]?.id; query( `query GetProduct($id: ID!) { product(id: $id) { title } } `, {variables: {id: productId}}, ).then(({data}) => setProduct(data.product)); }, [data]); return The selected product title is {product?.title}; } ``` *** ## Custom protocols Custom protocols make it easier to navigate to common locations, and construct URLs. ##### Shopify Protocol Use the `shopify:admin` protocol when you want to construct a URL with a root of the Shopify Admin. ##### App Protocol Use the `app:` protocol to construct a URL for your app. Shopify will handle constructing the base URL for your app. This works for both embedded and non-embedded apps. ##### Extension Protocol Triggers an action extension from a block extension using the `extension:` protocol. The `extensionTarget` is the target of the action extension. The handle is the handle of the action extension that will be opened. ##### Relative Urls Relative urls are relative to your app and are useful when you want to link to a route within your app. This works for both embedded and non-embedded apps. ## shopify:admin ##### Link to Product Page ```tsx ; ``` ##### Fetch data ```ts fetch('shopify:admin/api/graphql.json', { method: 'POST', body: JSON.stringify(simpleProductQuery), }); ``` ## app: ## Link to Settings ```tsx ; ``` ## extension: ## Trigger Action Extension from a Block extension ```tsx ; ``` ## /relative/urls ## Link to route in your app ```tsx ; ``` *** ## Deploying Use the Shopify CLI to [deploy your app and its extensions](https://shopify.dev/docs/apps/deployment/extension). ## Deploy an extension ## CLI ```bash # navigate to your app's root directory: cd my-app # deploy your app and its extensions: npm run deploy # follow the steps to deploy ``` *** ## Security UI Extensions run on a different origin than the Shopify Admin. For network calls to succeed, your server must support [cross-origin resource sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for the origin `https://extensions.shopifycdn.com`. If you have a custom [`Access-Control-Allow-Origin` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) set, you must include `https://extensions.shopifycdn.com` in the list of allowed origins. If you are using the [Shopify App Remix Template](https://github.com/Shopify/shopify-app-template-remix), this is done automatically for you. *** ## Tutorials and resources Deepen your understanding of Admin UI extensions with these tutorials and resources. [Tutorial - Get started building your first admin extension](#getting-started) [Component APIs - See all available components](https://shopify.dev/docs/api/admin-extensions/components) [Reference - View a list of available extension targets](https://shopify.dev/docs/api/admin-extensions/api/extension-targets) [App authentication - Make authenticated requests to your app's backend](#app-authentication) [Direct API access - Access the Shopify GraphQL API directly](#direct-api-access) [Custom protocols - Easily construct URLs to navigate to common locations](#custom-protocols) [UI reference - Figma UI Kit](https://www.figma.com/community/file/1265417558571498993) ***