--- title: Customers description: >- Customer pages display information about individual customers, customer lists, and customer segments. Extensions on these pages help merchants enhance customer relationships, manage customer data, and build targeted marketing campaigns. api_version: 2025-07 api_name: admin-extensions source_url: html: 'https://shopify.dev/docs/api/admin-extensions/2025-07/targets/customers' md: 'https://shopify.dev/docs/api/admin-extensions/2025-07/targets/customers.md' --- Migrate to Polaris Version 2025-07 is the last API version to support React-based UI components. Later versions use [web components](https://shopify.dev/docs/api/admin-extensions/latest/web-components), native UI elements with built-in accessibility, better performance, and consistent styling with [Shopify's design system](https://shopify.dev/docs/apps/design). Check out the [migration guide](https://shopify.dev/docs/apps/build/admin/upgrading-to-2025-10) to upgrade your extension. # Customers Customer pages display information about individual customers, customer lists, and [customer segments](https://help.shopify.com/manual/customers/customer-segmentation). Extensions on these pages help merchants enhance customer relationships, manage customer data, and build targeted marketing campaigns. ### Use cases * **Enhanced customer insights:** Display customer insights from external CRM systems, loyalty platforms, or analytics tools to provide merchants with a complete view of customer behavior and preferences. * **Marketing workflows:** Enable merchants to export customer segments to email marketing platforms, create targeted campaigns, or sync customer data with advertising networks for personalized outreach. * **Loyalty and rewards:** Show customer loyalty status, points balances, tier information, or special perks directly within the customer profile to help merchants provide better service. * **Data quality and verification:** Verify customer information, flag duplicate records, enhance customer profiles with additional data from third-party sources, or validate addresses and contact details. * **Bulk customer operations:** Process multiple customers at once for operations like tagging, exporting, updating custom fields, or triggering workflows in external systems. ![Customers targets overview](https://shopify.dev/assets/assets/images/templated-apis-screenshots/admin-extensions/targets-overview-images/admin.customer.overview-DOtAHAb9.png) *** ## Customer details targets Use [action and block targets](https://shopify.dev/docs/api/admin-extensions/2025-07#building-your-extension) to extend the customer details page. Add workflows and contextual information that help merchants manage customer relationships and access integrated customer data. Action targets open as modal overlays from the **More actions** menu, while block targets display as inline cards. The examples demonstrate fetching data from Shopify's [direct API](https://shopify.dev/docs/api/admin-extensions/2025-07#direct-api-access) or your [app's backend](https://shopify.dev/docs/api/admin-extensions/2025-07#app-authentication). ### Customer details action target `admin.customer-details.action.render` Renders an admin action extension on the customer details page. Merchants can access this extension from the **More actions** menu. Use this target to provide workflows that operate on individual customer data, such as exporting customer information, syncing with CRM systems, or managing loyalty programs. Extensions at this target can access information about the customer through the `data` property in the [Action Extension API](https://shopify.dev/docs/api/admin-extensions/2025-07/target-apis/core-apis/action-extension-api). The action renders in a modal overlay, providing space for multi-step workflows, forms, and confirmations. ### Support Components (35) APIs (1) ### Supported components * [Admin​Action](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/settings-and-templates/adminaction) * [Admin​Block](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/settings-and-templates/adminblock) * [Admin​Print​Action](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/settings-and-templates/adminprintaction) * [Badge](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/feedback-and-status-indicators/badge) * [Banner](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/feedback-and-status-indicators/banner) * [Block​Stack](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/layout-and-structure/blockstack) * [Box](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/layout-and-structure/box) * [Button](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/actions/button) * [Checkbox](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/checkbox) * [Choice​List](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/choicelist) * [Color​Picker](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/colorpicker) * [Date​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/datefield) * [Date​Picker](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/datepicker) * [Divider](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/layout-and-structure/divider) * [Email​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/emailfield) * [Form](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/form) * [Function​Settings](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/functionsettings) * [Heading](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/typography-and-content/heading) * [Heading​Group](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/typography-and-content/headinggroup) * [Icon](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/media-and-visuals/icon) * [Image](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/media-and-visuals/image) * [Inline​Stack](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/layout-and-structure/inlinestack) * [Link](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/actions/link) * [Money​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/moneyfield) * [Number​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/numberfield) * [Paragraph](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/typography-and-content/paragraph) * [Password​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/passwordfield) * [Pressable](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/actions/pressable) * [Progress​Indicator](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/feedback-and-status-indicators/progressindicator) * [Section](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/layout-and-structure/section) * [Select](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/select) * [Text](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/typography-and-content/text) * [Text​Area](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/textarea) * [Text​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/textfield) * [URLField](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/urlfield) ### Available APIs * [Action Extension API](https://shopify.dev/docs/api/admin-extensions/2025-07/target-apis/core-apis/action-extension-api) Examples ### Examples * #### ##### Description Add an action extension that exports customer data to an external CRM system. This example shows how to create a modal workflow that fetches customer details and sends them to a third-party service. ##### React ```tsx import React from 'react'; import {useState} from 'react'; import { reactExtension, useApi, AdminAction, Banner, Section, BlockStack, Checkbox, Button, } from '@shopify/ui-extensions-react/admin'; const TARGET = 'admin.customer-details.action.render'; export default reactExtension(TARGET, () => ); function App() { const {data, close, query} = useApi(TARGET); const [loading, setLoading] = useState(false); const [syncOrders, setSyncOrders] = useState(true); const [syncMetafields, setSyncMetafields] = useState(false); const [success, setSuccess] = useState(false); const [error, setError] = useState(false); const handleExport = async () => { setLoading(true); setSuccess(false); setError(false); const customerId = data.selected[0].id; try { // Fetch customer details from GraphQL Admin API const {data: customerData} = await query( ` query GetCustomer($id: ID!) { customer(id: $id) { id firstName lastName email phone ordersCount amountSpent { amount currencyCode } tags addresses { address1 address2 city province country zip } } } `, {variables: {id: customerId}} ); // Export to CRM through your app's backend const response = await fetch('https://your-app.com/api/export-customer', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ customer: customerData.customer, includeOrders: syncOrders, includeMetafields: syncMetafields, }), }); if (response.ok) { setSuccess(true); close(); } else { setError(true); } } catch (err) { setError(true); } finally { setLoading(false); } }; return ( {loading ? 'Exporting...' : 'Export Customer'} } secondaryAction={ } > {success && ( Customer exported successfully! )} {error && ( Failed to export customer. Please try again. )}
Include order history Include metafield data
); } ``` ##### TS ```ts import { extension, AdminAction, Banner, Section, BlockStack, Checkbox, Button, } from '@shopify/ui-extensions/admin'; export default extension( 'admin.customer-details.action.render', (root, api) => { let loading = false; let syncOrders = true; let syncMetafields = false; let success = false; let error = false; const handleExport = async () => { loading = true; success = false; error = false; updateUI(); const customerId = api.data.selected[0].id; try { // Fetch customer details from GraphQL Admin API const {data: customerData} = await api.query( ` query GetCustomer($id: ID!) { customer(id: $id) { id firstName lastName email phone ordersCount amountSpent { amount currencyCode } tags addresses { address1 address2 city province country zip } } } `, {variables: {id: customerId}} ); // Export to CRM through your app's backend const response = await fetch('https://your-app.com/api/export-customer', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ customer: customerData.customer, includeOrders: syncOrders, includeMetafields: syncMetafields, }), }); if (response.ok) { success = true; updateUI(); api.close(); } else { error = true; updateUI(); } } catch (err) { error = true; updateUI(); } finally { loading = false; updateUI(); } }; const primaryAction = root.createFragment(); const secondaryAction = root.createFragment(); const content = root.createFragment(); const updateUI = () => { content.replaceChildren(); if (success) { content.appendChild( root.createComponent( Banner, {tone: 'success', dismissible: true}, 'Customer exported successfully!' ) ); } if (error) { content.appendChild( root.createComponent( Banner, {tone: 'critical', dismissible: true}, 'Failed to export customer. Please try again.' ) ); } const section = root.createComponent(Section, {heading: 'Export options'}); const blockStack = root.createComponent(BlockStack); blockStack.appendChild( root.createComponent( Checkbox, { checked: syncOrders, onChange: (value) => { syncOrders = value; }, }, 'Include order history' ) ); blockStack.appendChild( root.createComponent( Checkbox, { checked: syncMetafields, onChange: (value) => { syncMetafields = value; }, }, 'Include metafield data' ) ); section.appendChild(blockStack); content.appendChild(section); }; primaryAction.appendChild( root.createComponent( Button, { onPress: handleExport, disabled: loading || success, }, loading ? 'Exporting...' : 'Export Customer' ) ); secondaryAction.appendChild( root.createComponent(Button, {onPress: () => api.close()}, 'Cancel') ); updateUI(); const adminAction = root.createComponent( AdminAction, { title: 'Export to CRM', primaryAction, secondaryAction, } ); adminAction.appendChild(content); root.appendChild(adminAction); root.mount(); } ); ``` * #### ##### Description Add an action extension that updates customer loyalty status in an external loyalty platform. This example demonstrates how to use the \[GraphQL Admin API]\(/docs/api/admin-graphql) to fetch customer information and update their loyalty tier. ##### React ```tsx import React from 'react'; import {useState, useEffect} from 'react'; import { reactExtension, useApi, AdminAction, Banner, Section, BlockStack, Box, Select, Text, Button, ProgressIndicator, } from '@shopify/ui-extensions-react/admin'; const TARGET = 'admin.customer-details.action.render'; export default reactExtension(TARGET, () => ); function App() { const {data, close} = useApi(TARGET); const [loading, setLoading] = useState(false); const [fetching, setFetching] = useState(true); const [currentTier, setCurrentTier] = useState(''); const [newTier, setNewTier] = useState(''); const [success, setSuccess] = useState(false); const [error, setError] = useState(false); const tiers = [ {value: 'Bronze', label: 'Bronze'}, {value: 'Silver', label: 'Silver'}, {value: 'Gold', label: 'Gold'}, {value: 'Platinum', label: 'Platinum'}, ]; useEffect(() => { const fetchLoyaltyStatus = async () => { const customerId = data.selected[0].id; try { // Fetch current loyalty status from your app's backend const response = await fetch( `https://your-app.com/api/loyalty-status?customerId=${customerId}` ); const loyaltyData = await response.json(); setCurrentTier(loyaltyData.tier); setNewTier(loyaltyData.tier); } catch (err) { console.error('Error fetching loyalty status:', err); } finally { setFetching(false); } }; fetchLoyaltyStatus(); }, [data]); const handleUpdate = async () => { setLoading(true); setSuccess(false); setError(false); const customerId = data.selected[0].id; try { // Update loyalty tier through your app's backend const response = await fetch('https://your-app.com/api/update-loyalty', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ customerId, tier: newTier, }), }); if (response.ok) { setSuccess(true); close(); } else { setError(true); } } catch (err) { setError(true); } finally { setLoading(false); } }; if (fetching) { return ( Loading loyalty information... ); } return ( {loading ? 'Updating...' : 'Update Tier'} } secondaryAction={ } > {success && ( Loyalty status updated successfully! )} {error && ( Failed to update loyalty status. Please try again. )}
Current tier: {currentTier}
); } ``` ##### TS ```ts import { extension, AdminAction, Banner, Section, BlockStack, Select, Text, Button, } from '@shopify/ui-extensions/admin'; export default extension( 'admin.customer-index.selection-action.render', async (root, api) => { const selectedCustomers = api.data.selected || []; const customerCount = selectedCustomers.length; let loading = false; let listId = ''; let lists = []; let success = false; let error = false; const adminAction = root.createComponent(AdminAction, { title: 'Export to Marketing Platform', }); root.appendChild(adminAction); root.mount(); // Fetch available marketing lists try { const response = await fetch('https://your-app.com/api/marketing-lists'); const listsData = await response.json(); lists = listsData.lists.map(list => ({ value: list.id, label: `${list.name} (${list.subscriberCount} subscribers)`, })); if (listsData.lists.length > 0) { listId = listsData.lists[0].id; } } catch (err) { console.error('Error fetching lists:', err); } const handleExport = async () => { loading = true; success = false; error = false; updateUI(); const customerIds = api.data.selected.map((customer) => customer.id); try { // Fetch customer emails from GraphQL Admin API const {data: customerData} = await api.query( ` query GetCustomers($ids: [ID!]!) { nodes(ids: $ids) { ... on Customer { id email firstName lastName tags } } } `, {variables: {ids: customerIds}} ); // Export to marketing platform through your app's backend const response = await fetch('https://your-app.com/api/export-to-marketing', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ customers: customerData.nodes, listId, }), }); if (response.ok) { success = true; updateUI(); api.close(); } else { error = true; updateUI(); } } catch (err) { error = true; updateUI(); } finally { loading = false; updateUI(); } }; const primaryAction = root.createFragment(); const secondaryAction = root.createFragment(); const content = root.createFragment(); const updateUI = () => { content.replaceChildren(); primaryAction.replaceChildren(); secondaryAction.replaceChildren(); if (success) { content.appendChild( root.createComponent( Banner, {tone: 'success', dismissible: true}, `${customerCount} customers exported successfully!` ) ); } if (error) { content.appendChild( root.createComponent( Banner, {tone: 'critical', dismissible: true}, 'Failed to export customers. Please try again.' ) ); } const section = root.createComponent(Section, {heading: 'Export settings'}); const blockStack = root.createComponent(BlockStack); blockStack.appendChild( root.createComponent( Text, {}, `Exporting ${customerCount} selected customer${customerCount !== 1 ? 's' : ''}` ) ); blockStack.appendChild( root.createComponent(Select, { label: 'Marketing list', value: listId, onChange: (value) => { listId = value; }, options: lists, }) ); section.appendChild(blockStack); content.appendChild(section); primaryAction.appendChild( root.createComponent( Button, { onPress: handleExport, disabled: loading || success || !listId, }, loading ? 'Exporting...' : 'Export Customers' ) ); secondaryAction.appendChild( root.createComponent(Button, {onPress: () => api.close()}, 'Cancel') ); }; updateUI(); adminAction.setProps({ title: 'Export to Marketing Platform', primaryAction, secondaryAction, }); adminAction.appendChild(content); } ); ``` * #### ##### Description Add a selection action extension that applies tags to multiple customers at once. This example demonstrates bulk operations using the Admin GraphQL API. ##### React ```tsx import React from 'react'; import {useState} from 'react'; import { reactExtension, useApi, AdminAction, Banner, Section, BlockStack, TextField, Text, Button, } from '@shopify/ui-extensions-react/admin'; const TARGET = 'admin.customer-index.selection-action.render'; export default reactExtension(TARGET, () => ); function App() { const {data, close} = useApi(TARGET); const [loading, setLoading] = useState(false); const [tags, setTags] = useState(''); const [success, setSuccess] = useState(false); const [error, setError] = useState(false); const customerCount = data.selected?.length || 0; const handleTag = async () => { setLoading(true); setSuccess(false); setError(false); const customerIds = data.selected.map((customer) => customer.id); const tagArray = tags.split(',').map((tag) => tag.trim()).filter(Boolean); try { // Apply tags through your app's backend const response = await fetch('https://your-app.com/api/bulk-tag', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ customerIds, tags: tagArray, }), }); if (response.ok) { setSuccess(true); close(); } else { setError(true); } } catch (err) { setError(true); } finally { setLoading(false); } }; return ( {loading ? 'Applying Tags...' : 'Apply Tags'} } secondaryAction={ } > {success && ( Tags applied to {customerCount} customers! )} {error && ( Failed to apply tags. Please try again. )}
Apply tags to {customerCount} selected customer{customerCount !== 1 ? 's' : ''} Enter one or more tags separated by commas
); } ``` ##### TS ```ts import { extension, AdminAction, Banner, Section, BlockStack, TextField, Text, Button, } from '@shopify/ui-extensions/admin'; export default extension( 'admin.customer-index.selection-action.render', (root, api) => { let loading = false; let tags = ''; let success = false; let error = false; const customerCount = api.data.selected?.length || 0; const handleTag = async () => { loading = true; success = false; error = false; updateUI(); const customerIds = api.data.selected.map((customer) => customer.id); const tagArray = tags.split(',').map((tag) => tag.trim()).filter(Boolean); try { // Apply tags through your app's backend const response = await fetch('https://your-app.com/api/bulk-tag', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ customerIds, tags: tagArray, }), }); if (response.ok) { success = true; updateUI(); api.close(); } else { error = true; updateUI(); } } catch (err) { error = true; updateUI(); } finally { loading = false; updateUI(); } }; const primaryAction = root.createFragment(); const secondaryAction = root.createFragment(); const content = root.createFragment(); const updateUI = () => { content.replaceChildren(); primaryAction.replaceChildren(); secondaryAction.replaceChildren(); if (success) { content.appendChild( root.createComponent( Banner, {tone: 'success', dismissible: true}, `Tags applied to ${customerCount} customers!` ) ); } if (error) { content.appendChild( root.createComponent( Banner, {tone: 'critical', dismissible: true}, 'Failed to apply tags. Please try again.' ) ); } const section = root.createComponent(Section, {heading: 'Tag settings'}); const blockStack = root.createComponent(BlockStack); blockStack.appendChild( root.createComponent( Text, {}, `Apply tags to ${customerCount} selected customer${customerCount !== 1 ? 's' : ''}` ) ); blockStack.appendChild( root.createComponent(TextField, { label: 'Tags (comma-separated)', value: tags, onChange: (value) => { tags = value; }, placeholder: 'VIP, Newsletter, Holiday2024', }) ); blockStack.appendChild( root.createComponent( Text, {tone: 'subdued'}, 'Enter one or more tags separated by commas' ) ); section.appendChild(blockStack); content.appendChild(section); primaryAction.appendChild( root.createComponent( Button, { onPress: handleTag, disabled: loading || success || !tags.trim(), }, loading ? 'Applying Tags...' : 'Apply Tags' ) ); secondaryAction.appendChild( root.createComponent(Button, {onPress: () => api.close()}, 'Cancel') ); }; updateUI(); const adminAction = root.createComponent( AdminAction, { title: 'Bulk Tag Customers', primaryAction, secondaryAction, } ); adminAction.appendChild(content); root.appendChild(adminAction); root.mount(); } ); ``` ### Customer index selection action (should render) target `admin.customer-index.selection-action.should-render` Controls the render state of a selection action extension on the customer index page when multiple customers are selected. Use this target to conditionally show or hide your bulk action extension based on the number of selected customers, their properties, or app configuration. This target returns a boolean value that determines whether the corresponding selection action extension appears in the **More actions** menu. The extension is evaluated each time the selection changes. ### Support Components (0) APIs (1) ### Supported components \- ### Available APIs * [Should Render API](https://shopify.dev/docs/api/admin-extensions/2025-07/target-apis/utility-apis/should-render-api) Examples ### Examples * #### ##### Description Conditionally display a bulk action only when a reasonable number of customers are selected. This example demonstrates how to limit bulk operations based on selection size. ##### React ```tsx import {extension} from '@shopify/ui-extensions/admin'; export default extension( 'admin.customer-index.selection-action.should-render', async (root, api) => { const selectedCount = api.data.selected?.length || 0; // Only show action if between 1 and 100 customers are selected return {render: selectedCount > 0 && selectedCount <= 100}; } ); ``` ##### TS ```ts import {extension} from '@shopify/ui-extensions/admin'; export default extension( 'admin.customer-index.selection-action.should-render', async (root, api) => { const selectedCount = api.data.selected?.length || 0; // Only show action if between 1 and 100 customers are selected return {render: selectedCount > 0 && selectedCount <= 100}; } ); ``` * #### ##### Description Conditionally display a bulk action based on whether selected customers meet specific criteria. This example demonstrates checking customer properties before showing the extension. ##### React ```tsx import {extension} from '@shopify/ui-extensions/admin'; export default extension( 'admin.customer-index.selection-action.should-render', async (root, api) => { const selectedIds = api.data.selected?.map((customer) => customer.id) || []; const selectedCount = selectedIds.length; // Don't show for empty selections if (selectedCount === 0) { return {render: false}; } try { // Check if selected customers are eligible for the action const response = await fetch( 'https://your-app.com/api/check-eligible-customers', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({customerIds: selectedIds}), } ); const {eligibleCount} = await response.json(); // Only show action if at least one selected customer is eligible return {render: eligibleCount > 0}; } catch (err) { console.error('Error checking eligibility:', err); return {render: false}; } } ); ``` ##### TS ```ts import {extension} from '@shopify/ui-extensions/admin'; export default extension( 'admin.customer-index.selection-action.should-render', async (root, api) => { const selectedIds = api.data.selected?.map((customer) => customer.id) || []; const selectedCount = selectedIds.length; // Don't show for empty selections if (selectedCount === 0) { return {render: false}; } try { // Check if selected customers are eligible for the action const response = await fetch( 'https://your-app.com/api/check-eligible-customers', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({customerIds: selectedIds}), } ); const {eligibleCount} = await response.json(); // Only show action if at least one selected customer is eligible return {render: eligibleCount > 0}; } catch (err) { console.error('Error checking eligibility:', err); return {render: false}; } } ); ``` *** ## Customer segment targets Use [action and runnable targets](https://shopify.dev/docs/api/admin-extensions/2025-07#building-your-extension) to extend customer segment pages with workflows that help merchants use and export their customer segments for marketing and analysis. Action targets render UI workflows for segment operations, while runnable targets return data to populate pre-built customer segment templates. ### Customer segment details action target `admin.customer-segment-details.action.render` Renders an admin action extension on the customer segment details page. Merchants can access this extension from the **Use segment** button. Use this target to provide workflows that operate on customer segments, such as exporting segments to marketing platforms, creating targeted campaigns, or syncing with external analytics tools. Extensions at this target can access information about the segment through the `data` property in the [Action Extension API](https://shopify.dev/docs/api/admin-extensions/2025-07/target-apis/core-apis/action-extension-api). The action renders in a modal overlay, providing space for segment-specific workflows. ### Support Components (35) APIs (1) ### Supported components * [Admin​Action](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/settings-and-templates/adminaction) * [Admin​Block](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/settings-and-templates/adminblock) * [Admin​Print​Action](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/settings-and-templates/adminprintaction) * [Badge](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/feedback-and-status-indicators/badge) * [Banner](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/feedback-and-status-indicators/banner) * [Block​Stack](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/layout-and-structure/blockstack) * [Box](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/layout-and-structure/box) * [Button](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/actions/button) * [Checkbox](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/checkbox) * [Choice​List](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/choicelist) * [Color​Picker](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/colorpicker) * [Date​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/datefield) * [Date​Picker](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/datepicker) * [Divider](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/layout-and-structure/divider) * [Email​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/emailfield) * [Form](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/form) * [Function​Settings](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/functionsettings) * [Heading](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/typography-and-content/heading) * [Heading​Group](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/typography-and-content/headinggroup) * [Icon](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/media-and-visuals/icon) * [Image](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/media-and-visuals/image) * [Inline​Stack](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/layout-and-structure/inlinestack) * [Link](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/actions/link) * [Money​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/moneyfield) * [Number​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/numberfield) * [Paragraph](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/typography-and-content/paragraph) * [Password​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/passwordfield) * [Pressable](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/actions/pressable) * [Progress​Indicator](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/feedback-and-status-indicators/progressindicator) * [Section](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/layout-and-structure/section) * [Select](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/select) * [Text](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/typography-and-content/text) * [Text​Area](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/textarea) * [Text​Field](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/textfield) * [URLField](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/urlfield) ### Available APIs * [Action Extension API](https://shopify.dev/docs/api/admin-extensions/2025-07/target-apis/core-apis/action-extension-api) Examples ### Examples * #### ##### Description Add an action extension that exports a customer segment to an email marketing platform. This example shows how to fetch segment data and create a synchronized audience in an external service. ##### React ```tsx import React from 'react'; import {useState, useEffect} from 'react'; import { reactExtension, useApi, AdminAction, Banner, Section, BlockStack, Box, Heading, TextField, Text, Button, ProgressIndicator, } from '@shopify/ui-extensions-react/admin'; const TARGET = 'admin.customer-segment-details.action.render'; export default reactExtension(TARGET, () => ); function App() { const {data, close, query} = useApi(TARGET); const [loading, setLoading] = useState(false); const [fetching, setFetching] = useState(true); const [segmentName, setSegmentName] = useState(''); const [customerCount, setCustomerCount] = useState(0); const [audienceName, setAudienceName] = useState(''); const [success, setSuccess] = useState(false); const [error, setError] = useState(false); useEffect(() => { const fetchSegmentDetails = async () => { const segmentId = data.selected[0].id; try { // Fetch segment details from GraphQL Admin API const {data: segmentData} = await query( ` query GetSegment($id: ID!) { segment(id: $id) { name query } } `, {variables: {id: segmentId}} ); setSegmentName(segmentData.segment.name); setAudienceName(segmentData.segment.name); // Get customer count from your app's backend const countResponse = await fetch( `https://your-app.com/api/segment-count?segmentId=${segmentId}` ); const countData = await countResponse.json(); setCustomerCount(countData.count); } catch (err) { console.error('Error fetching segment:', err); } finally { setFetching(false); } }; fetchSegmentDetails(); }, [data, query]); const handleExport = async () => { setLoading(true); setSuccess(false); setError(false); const segmentId = data.selected[0].id; try { // Export segment through your app's backend const response = await fetch('https://your-app.com/api/export-segment', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ segmentId, audienceName, }), }); if (response.ok) { setSuccess(true); close(); } else { setError(true); } } catch (err) { setError(true); } finally { setLoading(false); } }; if (fetching) { return ( Loading segment details... ); } return ( {loading ? 'Exporting...' : 'Create Audience'} } secondaryAction={ } > {success && ( Segment exported successfully! Audience "{audienceName}" created. )} {error && ( Failed to export segment. Please try again. )}
Source segment {segmentName} Customer count {customerCount.toLocaleString()} customers
); } ``` ##### TS ```ts import { extension, AdminAction, Banner, Section, BlockStack, Box, Heading, TextField, Text, Button, ProgressIndicator, } from '@shopify/ui-extensions/admin'; export default extension( 'admin.customer-segment-details.action.render', async (root, api) => { const segmentId = api.data.selected[0].id; let loading = false; let segmentName = ''; let customerCount = 0; let audienceName = ''; let success = false; let error = false; const adminAction = root.createComponent(AdminAction, {title: 'Export to Email Platform'}); // Show loading state const loadingStack = root.createComponent(BlockStack); loadingStack.appendChild(root.createComponent(ProgressIndicator, {size: 'small-100'})); loadingStack.appendChild(root.createComponent(Text, {}, 'Loading segment details...')); adminAction.appendChild(loadingStack); root.appendChild(adminAction); root.mount(); try { // Fetch segment details from GraphQL Admin API const {data: segmentData} = await api.query( ` query GetSegment($id: ID!) { segment(id: $id) { name query } } `, {variables: {id: segmentId}} ); segmentName = segmentData.segment.name; audienceName = segmentData.segment.name; // Get customer count from your app's backend const countResponse = await fetch( `https://your-app.com/api/segment-count?segmentId=${segmentId}` ); const countData = await countResponse.json(); customerCount = countData.count; } catch (err) { console.error('Error fetching segment:', err); } const handleExport = async () => { loading = true; success = false; error = false; updateUI(); try { // Export segment through your app's backend const response = await fetch('https://your-app.com/api/export-segment', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ segmentId, audienceName, }), }); if (response.ok) { success = true; updateUI(); api.close(); } else { error = true; updateUI(); } } catch (err) { error = true; updateUI(); } finally { loading = false; updateUI(); } }; const primaryAction = root.createFragment(); const secondaryAction = root.createFragment(); const content = root.createFragment(); const updateUI = () => { content.replaceChildren(); primaryAction.replaceChildren(); secondaryAction.replaceChildren(); if (success) { content.appendChild( root.createComponent( Banner, {tone: 'success', dismissible: true}, `Segment exported successfully! Audience "${audienceName}" created.` ) ); } if (error) { content.appendChild( root.createComponent( Banner, {tone: 'critical', dismissible: true}, 'Failed to export segment. Please try again.' ) ); } const section = root.createComponent(Section, {heading: 'Segment information'}); const blockStack = root.createComponent(BlockStack); const sourceBox = root.createComponent(Box); sourceBox.appendChild(root.createComponent(Heading, {}, 'Source segment')); sourceBox.appendChild(root.createComponent(Text, {}, segmentName)); blockStack.appendChild(sourceBox); const countBox = root.createComponent(Box); countBox.appendChild(root.createComponent(Heading, {}, 'Customer count')); countBox.appendChild( root.createComponent(Text, {}, `${customerCount.toLocaleString()} customers`) ); blockStack.appendChild(countBox); blockStack.appendChild( root.createComponent(TextField, { label: 'Audience name', value: audienceName, onChange: (value) => { audienceName = value; }, }) ); section.appendChild(blockStack); content.appendChild(section); primaryAction.appendChild( root.createComponent( Button, { onPress: handleExport, disabled: loading || success || !audienceName.trim(), }, loading ? 'Exporting...' : 'Create Audience' ) ); secondaryAction.appendChild( root.createComponent(Button, {onPress: () => api.close()}, 'Cancel') ); }; // Clear loading state and show form adminAction.replaceChildren(); updateUI(); adminAction.setProps({ title: 'Export to Email Platform', primaryAction, secondaryAction, }); adminAction.appendChild(content); } ); ``` * #### ##### Description Add an action extension that creates a targeted advertising campaign based on a customer segment. This example demonstrates how to integrate segment data with advertising platforms. ##### React ```tsx import React from 'react'; import {useState} from 'react'; import { reactExtension, useApi, AdminAction, Banner, Section, BlockStack, TextField, Select, Button, } from '@shopify/ui-extensions-react/admin'; const TARGET = 'admin.customer-segment-details.action.render'; export default reactExtension(TARGET, () => ); function App() { const {data, close} = useApi(TARGET); const [loading, setLoading] = useState(false); const [campaignName, setCampaignName] = useState(''); const [budget, setBudget] = useState('100'); const [duration, setDuration] = useState('7days'); const [success, setSuccess] = useState(false); const [error, setError] = useState(false); const durations = [ {value: '7days', label: '7 days'}, {value: '14days', label: '14 days'}, {value: '30days', label: '30 days'}, {value: 'ongoing', label: 'Ongoing'}, ]; const handleCreate = async () => { setLoading(true); setSuccess(false); setError(false); const segmentId = data.selected[0].id; try { // Create campaign through your app's backend const response = await fetch('https://your-app.com/api/create-campaign', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ segmentId, campaignName, budget: parseFloat(budget), duration, }), }); if (response.ok) { setSuccess(true); close(); } else { setError(true); } } catch (err) { setError(true); } finally { setLoading(false); } }; return ( {loading ? 'Creating...' : 'Create Campaign'} } secondaryAction={ } > {success && ( Campaign created successfully! )} {error && ( Failed to create campaign. Please try again. )}