---
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)

***
## 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.
***