--- title: Network Features description: > Admin UI extensions make it possible to surface contextual app functionality within the Shopify Admin interface. api_version: 2026-01 api_name: admin-extensions source_url: html: 'https://shopify.dev/docs/api/admin-extensions/latest/network-features' md: 'https://shopify.dev/docs/api/admin-extensions/latest/network-features.md' --- # Network Features Admin UI extensions make it possible to surface contextual app functionality within the Shopify Admin interface. *** ## Overview Extend the Shopify Admin with UI Extensions. [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) ![Overview](https://shopify.dev/assets/assets/images/api/admin-extensions/2023-10/action-extension-example-D3UyRVWo.gif) *** ## 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-home/apis/id-token). There's no need to manually manage ID 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')`. If you need to make requests to a different domain, you can use the [`auth.idToken()` method](https://shopify.dev/docs/api/admin-extensions/api/standard-api#standardapi-propertydetail-auth) to retrieve the ID token and manually add it to your request headers. ## Make requests to your app's backend ##### Get Product Data ```tsx import {render} from 'preact'; import {useEffect, useState} from 'preact/hooks'; export default async () => { render(, document.body); } // Get product info from app backend async function getProductInfo(id) { const res = await fetch(`/api/products/${id}`); return res.json(); } function Extension() { // Contextual "input" data passed to this extension: const {data} = shopify; const productId = data.selected?.[0]?.id; const [productInfo, setProductInfo] = useState(); useEffect(() => { getProductInfo(productId).then(setProductInfo); }, [productId]); return ( Info: {productInfo?.title} ); } ``` ##### Get Data from a different domain ```tsx import {render} from 'preact'; import {useEffect, useState} from 'preact/hooks'; export default async () => { render(, document.body); } // Get product info from a different app backend async function getProductInfo(id, auth) { const token = await auth.idToken(); const res = await fetch(`https://app.example.com/api/products/${id}`, { headers: { Authorization: `Bearer ${token}`, }, }); return res.json(); } function Extension() { // Contextual "input" data passed to this extension: const {data, auth} = shopify; const productId = data.selected?.[0]?.id; const [productInfo, setProductInfo] = useState(); useEffect(() => { getProductInfo(productId, auth).then(setProductInfo); }, [productId, auth]); 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/build/authentication-authorization/access-token-types/online-access-tokens) mode by default. If you want to use [offline access](https://shopify.dev/docs/apps/build/authentication-authorization/access-token-types/offline-access-tokens) 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. [Note - Direct API can't be used to manage storefront access tokens.](https://shopify.dev/docs/api/admin-extensions#direct-api-access) [Developer guide - Learn more about access scopes](https://shopify.dev/docs/api/usage/access-scopes) ## Query Shopify data ##### Fetch Product data ```tsx import {render} from 'preact'; export default async () => { const productId = shopify.data.selected?.[0]?.id; const product = await getProduct(productId); render(, document.body); }; 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}, }), }); const {data} = await res.json(); return data.product; } function Extension({product}) { return ( The selected product title is {product.title} ); } ``` ##### Query Product data ```tsx import {render} from 'preact'; export default async () => { const productId = shopify.data.selected?.[0]?.id; const { data: {product}, } = await shopify.query( ` query GetProduct($id: ID!) { product(id: $id) { title } } `, {variables: {id: productId}}, ); render(, document.body); }; function Extension({product}) { 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 Link to Product Page; ``` ##### 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 ; ``` *** ## 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. ***