--- title: Discounts description: >- Discount pages display information about price reductions and promotional offers, including discount codes, automatic discounts, and usage limits. Extensions on these pages help merchants manage promotions and customize discount workflows. api_version: 2025-10 api_name: admin-extensions source_url: html: 'https://shopify.dev/docs/api/admin-extensions/2025-10/targets/discounts' md: 'https://shopify.dev/docs/api/admin-extensions/2025-10/targets/discounts.md' --- # Discounts Discount pages display information about price reductions and promotional offers, including discount codes, automatic discounts, and usage limits. Extensions on these pages help merchants manage promotions and customize discount workflows. ### Use cases * **Sync discounts externally:** Push discount codes and rules to external marketing platforms, POS systems, or affiliate networks. * **Track promotion performance:** Display analytics and conversion metrics from external tracking systems alongside discount details. * **Bulk discount management:** Enable merchants to update, duplicate, or archive multiple discounts at once from the index page. * **Validate discount rules:** Check discount configurations against business rules or inventory levels before activation. * **Generate unique codes:** Create batches of unique discount codes for influencer campaigns or customer loyalty programs. ![Discounts targets overview](https://shopify.dev/assets/assets/images/templated-apis-screenshots/admin-extensions/targets-overview-images/admin.discount.overview-CrfN7dGb.png) *** ## Discount details targets Use [action targets](https://shopify.dev/docs/api/admin-extensions/2025-10#building-your-extension) to extend the discount details page with workflows. Action targets open as modal overlays from the **More actions** menu. The examples demonstrate fetching data from Shopify's [direct API](https://shopify.dev/docs/api/admin-extensions/2025-10#direct-api-access) or your [app's backend](https://shopify.dev/docs/api/admin-extensions/2025-10#app-authentication). ### Discount details action target `admin.discount-details.action.render` Renders an admin action extension on the discounts details page. Merchants can access this extension from the **More actions** menu. Use this target to provide workflows that operate on discounts data, such as syncing with external systems, exporting discounts information, or managing credit terms. Extensions at this target can access discount data through the `data` property in the [Action Extension API](https://shopify.dev/docs/api/admin-extensions/2025-10/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 (45) APIs (1) ### Supported components * [Admin action](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/settings-and-templates/admin-action) * [Avatar](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/media-and-visuals/avatar) * [Badge](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/feedback-and-status-indicators/badge) * [Banner](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/feedback-and-status-indicators/banner) * [Box](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/box) * [Button](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/button) * [Button group](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/button-group) * [Checkbox](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/checkbox) * [Chip](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/typography-and-content/chip) * [Choice list](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/choice-list) * [Clickable](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/clickable) * [Clickable chip](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/clickable-chip) * [Color field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/color-field) * [Color picker](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/color-picker) * [Date field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/date-field) * [Date picker](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/date-picker) * [Divider](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/divider) * [Drop zone](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/drop-zone) * [Email field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/email-field) * [Grid](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/grid) * [Heading](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/typography-and-content/heading) * [Icon](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/media-and-visuals/icon) * [Image](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/media-and-visuals/image) * [Link](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/link) * [Menu](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/menu) * [Money field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/money-field) * [Number field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/number-field) * [Ordered list](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/ordered-list) * [Paragraph](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/typography-and-content/paragraph) * [Password field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/password-field) * [Query container](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/query-container) * [Search field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/search-field) * [Section](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/section) * [Select](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/select) * [Spinner](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/feedback-and-status-indicators/spinner) * [Stack](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/stack) * [Switch](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/switch) * [Table](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/table) * [Text](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/typography-and-content/text) * [Text area](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/text-area) * [Text field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/text-field) * [Thumbnail](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/media-and-visuals/thumbnail) * [Tooltip](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/typography-and-content/tooltip) * [Url field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/url-field) * [Unordered list](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/unordered-list) ### Available APIs * [Action Extension API](https://shopify.dev/docs/api/admin-extensions/2025-10/target-apis/core-apis/action-extension-api) Examples ### Examples * #### ##### Description Add an action extension that syncs the current discount to an external POS system. This example demonstrates calling an app backend API to push discount details to point-of-sale terminals. ##### jsx ```jsx import {render} from 'preact'; import {useState} from 'preact/hooks'; export default async () => { render(, document.body); }; const Extension = () => { const [loading, setLoading] = useState(false); const [success, setSuccess] = useState(false); const [error, setError] = useState(null); const [selectedLocations, setSelectedLocations] = useState({ mainStore: true, warehouse: false, popup: false, }); const handleSync = async () => { setLoading(true); setError(null); const discountId = shopify.data.selected[0].id; const locations = Object.entries(selectedLocations) .filter(([_, enabled]) => enabled) .map(([loc]) => loc); try { const response = await fetch('https://your-app.com/api/pos/sync-discount', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({discountId, locations}), }); if (response.ok) { setSuccess(true); shopify.close(); } else { const data = await response.json(); setError(data.message || 'Failed to sync discount'); } } catch (err) { setError('Connection error. Please try again.'); } finally { setLoading(false); } }; const handleLocationChange = (location) => (event) => { setSelectedLocations(prev => ({ ...prev, [location]: event.currentTarget.checked, })); }; const anySelected = Object.values(selectedLocations).some(Boolean); return ( {success && ( Discount synced to POS terminals successfully! )} {error && ( {error} )} The discount will be available at selected POS terminals within 5 minutes. {loading ? 'Syncing...' : 'Sync to POS'} shopify.close()}>Cancel ); }; ``` * #### ##### Description Add an action extension that displays performance analytics for the current discount by fetching usage data from the GraphQL Admin API. ##### jsx ```jsx import {render} from 'preact'; import {useState, useEffect} from 'preact/hooks'; export default async () => { render(, document.body); }; const Extension = () => { const [loading, setLoading] = useState(true); const [analytics, setAnalytics] = useState(null); const [error, setError] = useState(false); useEffect(() => { fetchAnalytics(); }, []); const fetchAnalytics = async () => { const discountId = shopify.data.selected[0].id; try { const response = await fetch('shopify:admin/api/graphql.json', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ query: `query GetDiscount($id: ID!) { discountNode(id: $id) { id discount { ... on DiscountCodeBasic { title usageLimit asyncUsageCount startsAt endsAt } ... on DiscountCodeFreeShipping { title usageLimit asyncUsageCount startsAt endsAt } } } }`, variables: {id: discountId}, }), }); const {data} = await response.json(); const discount = data?.discountNode?.discount; if (discount) { const usageRate = discount.usageLimit ? Math.round((discount.asyncUsageCount / discount.usageLimit) * 100) : null; setAnalytics({...discount, usageRate}); } } catch (err) { setError(true); } finally { setLoading(false); } }; if (loading) { return ( Loading analytics... ); } return ( {error && ( Failed to load discount analytics. )} {analytics && ( Total Redemptions: {analytics.asyncUsageCount} Usage Limit: {analytics.usageLimit || 'Unlimited'} {analytics.usageRate !== null && ( Usage Rate: 80 ? 'warning' : 'info'}> {analytics.usageRate}% )} Active: {new Date(analytics.startsAt).toLocaleDateString()} - {analytics.endsAt ? new Date(analytics.endsAt).toLocaleDateString() : 'No end date'} )} shopify.close()}>Close ); }; ``` ### Discount details action (should render) target `admin.discount-details.action.should-render` Controls the render state of an admin action extension on the discounts details page. Use this target to conditionally show or hide your action extension based on the discount's properties, such as status, configuration, or specific business requirements. This target returns a boolean value that determines whether the corresponding action extension appears in the **More actions** menu. The extension evaluates each time the page loads. ### Support Components (0) APIs (1) ### Supported components \- ### Available APIs * [Should Render API](https://shopify.dev/docs/api/admin-extensions/2025-10/target-apis/utility-apis/should-render-api) Examples ### Examples * #### ##### Description Show the analytics action only when the app backend confirms the discount has sufficient redemption data and analytics available for display. ##### jsx ```jsx export default async () => { const discountId = shopify.data.selected[0].id; try { const response = await fetch('https://your-app.com/api/discount-analytics/check', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ discountId, checkType: 'performance-data-available', }), }); if (!response.ok) { return { display: false }; } const result = await response.json(); // Show action if discount has been tracked and has redemption data const hasPerformanceData = result.isTracked && result.redemptionCount > 0; return { display: hasPerformanceData }; } catch (err) { console.error('Failed to check discount performance eligibility:', err); return { display: false }; } }; ``` * #### ##### Description Display the action only when the discount has specific products or collections assigned, querying the GraphQL Admin API to check the discount's product eligibility configuration. ##### jsx ```jsx export default async () => { const discountId = shopify.data.selected[0].id; try { const response = await fetch('shopify:admin/api/graphql.json', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: `query GetDiscountEligibility($id: ID!) { discountNode(id: $id) { discount { ... on DiscountCodeBasic { customerGets { items { ... on DiscountProducts { productVariantsCount { count } collectionsCount { count } } } } } ... on DiscountAutomaticBasic { customerGets { items { ... on DiscountProducts { productVariantsCount { count } collectionsCount { count } } } } } } } }`, variables: { id: discountId }, }), }); const { data } = await response.json(); const discount = data?.discountNode?.discount; const items = discount?.customerGets?.items; // Show action if discount targets specific products or collections const hasProducts = items?.productVariantsCount?.count > 0; const hasCollections = items?.collectionsCount?.count > 0; return { display: hasProducts || hasCollections }; } catch (err) { console.error('Error checking discount eligibility:', err); return { display: false }; } }; ``` *** ## Discount index targets Use [action targets](https://shopify.dev/docs/api/admin-extensions/2025-10#building-your-extension) to extend the discount index page with bulk operations and workflows that help merchants manage multiple discounts efficiently. ### Discount index action target `admin.discount-index.action.render` Renders an admin action extension on the discounts index page. Merchants can access this extension from the **More actions** menu. Use this target to provide workflows that operate on discounts data, such as syncing with external systems, exporting discounts information, or managing credit terms. Extensions at this target can access discount data through the `data` property in the [Action Extension API](https://shopify.dev/docs/api/admin-extensions/2025-10/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 (45) APIs (1) ### Supported components * [Admin action](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/settings-and-templates/admin-action) * [Avatar](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/media-and-visuals/avatar) * [Badge](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/feedback-and-status-indicators/badge) * [Banner](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/feedback-and-status-indicators/banner) * [Box](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/box) * [Button](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/button) * [Button group](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/button-group) * [Checkbox](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/checkbox) * [Chip](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/typography-and-content/chip) * [Choice list](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/choice-list) * [Clickable](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/clickable) * [Clickable chip](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/clickable-chip) * [Color field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/color-field) * [Color picker](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/color-picker) * [Date field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/date-field) * [Date picker](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/date-picker) * [Divider](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/divider) * [Drop zone](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/drop-zone) * [Email field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/email-field) * [Grid](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/grid) * [Heading](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/typography-and-content/heading) * [Icon](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/media-and-visuals/icon) * [Image](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/media-and-visuals/image) * [Link](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/link) * [Menu](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/actions/menu) * [Money field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/money-field) * [Number field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/number-field) * [Ordered list](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/ordered-list) * [Paragraph](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/typography-and-content/paragraph) * [Password field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/password-field) * [Query container](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/query-container) * [Search field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/search-field) * [Section](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/section) * [Select](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/select) * [Spinner](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/feedback-and-status-indicators/spinner) * [Stack](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/stack) * [Switch](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/switch) * [Table](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/table) * [Text](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/typography-and-content/text) * [Text area](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/text-area) * [Text field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/text-field) * [Thumbnail](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/media-and-visuals/thumbnail) * [Tooltip](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/typography-and-content/tooltip) * [Url field](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/forms/url-field) * [Unordered list](https://shopify.dev/docs/api/admin-extensions/2025-10/web-components/layout-and-structure/unordered-list) ### Available APIs * [Action Extension API](https://shopify.dev/docs/api/admin-extensions/2025-10/target-apis/core-apis/action-extension-api) Examples ### Examples * #### ##### Description Add an action extension that syncs selected discounts to an external POS or marketing system. This example demonstrates batch syncing with configurable options for location targeting and overwrite behavior. ##### jsx ```jsx import {render} from 'preact'; import {useState} from 'preact/hooks'; export default async () => { render(, document.body); }; const Extension = () => { const [loading, setLoading] = useState(false); const [success, setSuccess] = useState(false); const [error, setError] = useState(null); const [syncAllLocations, setSyncAllLocations] = useState(true); const [posSystem, setPosSystem] = useState('square'); const handleSync = async () => { setLoading(true); setError(null); try { const response = await fetch('https://your-app.com/api/pos/sync-discount', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ discountIds: shopify.data.selected.map(item => item.id), posSystem, syncAllLocations, }), }); if (response.ok) { setSuccess(true); shopify.close(); } else { const data = await response.json(); setError(data.message || 'Failed to sync discount'); } } catch (err) { setError('Connection error. Please try again.'); } finally { setLoading(false); } }; const selectedCount = shopify.data.selected.length; return ( {success && ( {selectedCount} discount(s) synced to POS successfully! )} {error && ( {error} )} Sync {selectedCount} selected discount(s) to your POS system for in-store use. setPosSystem(e.currentTarget.value)} > Square Clover Lightspeed setSyncAllLocations(e.currentTarget.checked)} /> {loading ? 'Syncing...' : `Sync ${selectedCount} Discount(s)`} shopify.close()}>Cancel ); }; ``` * #### ##### Description Add an action extension that lets merchants tag selected discounts with a campaign name for organization. This example demonstrates working with selected items from the index page and sending batch updates to your app backend. ##### jsx ```jsx import {render} from 'preact'; import {useState} from 'preact/hooks'; export default async () => { render(, document.body); }; const Extension = () => { const [campaignTag, setCampaignTag] = useState(''); const [loading, setLoading] = useState(false); const [success, setSuccess] = useState(false); const [error, setError] = useState(null); const selectedCount = shopify.data.selected?.length || 0; const discountIds = shopify.data.selected?.map((item) => item.id) || []; const handleTagDiscounts = async () => { if (!campaignTag.trim()) { setError('Please enter a campaign tag'); return; } setLoading(true); setError(null); try { const response = await fetch('https://your-app.com/api/discounts/tag', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ discountIds, tag: campaignTag.trim(), }), }); if (response.ok) { setSuccess(true); shopify.close(); } else { const result = await response.json(); setError(result.message || 'Failed to tag discounts'); } } catch (err) { setError('Network error. Please try again.'); } finally { setLoading(false); } }; return ( {success && ( Successfully tagged {selectedCount} discount{selectedCount !== 1 ? 's' : ''} with "{campaignTag}" )} {error && ( {error} )} Add a campaign tag to {selectedCount} selected discount{selectedCount !== 1 ? 's' : ''} for easier organization and filtering. setCampaignTag(e.currentTarget.value)} placeholder="e.g., Summer Sale 2025, Black Friday" /> {loading ? 'Tagging...' : `Tag ${selectedCount} Discount${selectedCount !== 1 ? 's' : ''}`} shopify.close()}>Cancel ); }; ``` ### Discount index action (should render) target `admin.discount-index.action.should-render` Controls the render state of an admin action extension on the discounts index page. Use this target to conditionally show or hide your action extension based on the discount's properties, such as status, configuration, or specific business requirements. This target returns a boolean value that determines whether the corresponding action extension appears in the **More actions** menu. The extension evaluates each time the page loads. ### Support Components (0) APIs (1) ### Supported components \- ### Available APIs * [Should Render API](https://shopify.dev/docs/api/admin-extensions/2025-10/target-apis/utility-apis/should-render-api) Examples ### Examples * #### ##### Description Show the discount performance action only when the app backend confirms the selected discounts are being tracked for analytics and have sufficient redemption data available. ##### jsx ```jsx export default async () => { const selectedDiscounts = shopify.data.selected; if (!selectedDiscounts || selectedDiscounts.length === 0) { return { display: false }; } try { const discountIds = selectedDiscounts.map(discount => discount.id); const response = await fetch('https://your-app.com/api/discounts/check-tracking', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ discountIds, checkType: 'performance_analytics', }), }); if (!response.ok) { return { display: false }; } const result = await response.json(); // Show action if discounts are tracked and have redemption data return { display: result.isTracked && result.hasRedemptionData, }; } catch (err) { console.error('Failed to check discount tracking status:', err); return { display: false }; } }; ``` * #### ##### Description Display the bulk action only when the selected discount is currently active, checking the discount status using the GraphQL Admin API. ##### jsx ```jsx export default async () => { const discountId = shopify.data.selected[0].id; try { const response = await fetch('shopify:admin/api/graphql.json', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ query: `query GetDiscountStatus($id: ID!) { discountNode(id: $id) { discount { ... on DiscountCodeBasic { status startsAt endsAt } ... on DiscountCodeFreeShipping { status startsAt endsAt } ... on DiscountAutomaticBasic { status startsAt endsAt } } } }`, variables: { id: discountId }, }), }); const { data } = await response.json(); const discount = data?.discountNode?.discount; // Only show action for active discounts const isActive = discount?.status === 'ACTIVE'; return { display: isActive }; } catch (err) { console.error('Error checking discount status:', err); return { display: false }; } }; ``` *** ## Best practices * **Differentiate discount types:** Discounts come in multiple types ([basic](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountCodeBasic), [BXGY](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountCodeBxgy), [free shipping](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountCodeFreeShipping), automatic vs code-based). Before displaying discount actions, check the discount type using [GraphQL](https://shopify.dev/docs/api/admin-graphql) to ensure your extension supports it. For example, POS sync may only work with certain discount types. * **Validate discount dates:** Always check `startsAt` and `endsAt` when displaying or syncing discounts. Syncing expired or not-yet-active discounts to external systems can create customer confusion and needs special handling or filtering. * **Show usage vs limits clearly:** When displaying discount analytics, show both [`asyncUsageCount`](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountCodeBasic#field-DiscountCodeBasic.fields.asyncUsageCount) and `usageLimit` together. Merchants need to see how close a discount is to its usage limit to decide whether to extend it or create a new code. * **Handle discount combinations:** Shopify has complex [discount combination rules](https://help.shopify.com/en/manual/discounts/combining-discounts/discount-combinations). If your extension recommends or creates discounts, validate that they're compatible with existing discount configurations to avoid conflicts that prevent customers from completing checkouts. * **Account for attribution delays:** Discount usage counts (`asyncUsageCount`) update asynchronously and may lag by several minutes. When displaying real-time analytics, indicate that counts are approximate and mention the last update time if available from your system. *** ## Limitations * **Single target per module:** Each `[[extensions.targeting]]` entry in your [TOML configuration](https://shopify.dev/docs/api/admin-extensions/2025-10#configuration) maps one target to one module file. * **Multiple discount type schemas:** Discounts are a [GraphQL union type](https://shopify.dev/docs/api/admin-graphql/latest/unions/Discount) with eight possible types: [`DiscountAutomaticBasic`](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountAutomaticBasic), [`DiscountCodeBasic`](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountCodeBasic), [`DiscountAutomaticBxgy`](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountAutomaticBxgy), [`DiscountCodeBxgy`](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountCodeBxgy), [`DiscountAutomaticFreeShipping`](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountAutomaticFreeShipping), [`DiscountCodeFreeShipping`](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountCodeFreeShipping), [`DiscountCodeApp`](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountCodeApp), [`DiscountAutomaticApp`](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountAutomaticApp). Each type has different fields. * **Asynchronous usage count:** The `asyncUsageCount` field on GraphQL `Discount` union types is updated asynchronously and might show a lower count until the process is completed. ***