--- title: Discounts description: >- Discount details pages display information about a specific discount, including its type, value, conditions, and usage limits. Extensions on these pages help merchants manage promotional campaigns and customize discount workflows. api_version: 2026-01 api_name: admin-extensions source_url: html: 'https://shopify.dev/docs/api/admin-extensions/latest/targets/discounts' md: 'https://shopify.dev/docs/api/admin-extensions/latest/targets/discounts.md' --- # Discounts Discount details pages display information about a specific discount, including its type, value, conditions, and usage limits. Extensions on these pages help merchants manage promotional campaigns and customize discount workflows. ### Use cases * **Sync with marketing platforms:** Automatically sync discount codes with external marketing tools like email campaigns, social media ads, or affiliate networks. * **Validate discount rules:** Check discount configurations against business rules or inventory levels before merchants activate promotions. * **Track promotion performance:** Display real-time analytics and conversion metrics for active discount campaigns from external analytics systems. * **Bulk discount management:** Enable merchants to update, duplicate, or archive multiple discounts at once from the discount index page. * **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/2026-01#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/2026-01#direct-api-access) or your [app's backend](https://shopify.dev/docs/api/admin-extensions/2026-01#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/2026-01/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/2026-01/web-components/settings-and-templates/admin-action) * [Avatar](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/media-and-visuals/avatar) * [Badge](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/feedback-and-status-indicators/badge) * [Banner](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/feedback-and-status-indicators/banner) * [Box](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/box) * [Button](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/button) * [Button group](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/button-group) * [Checkbox](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/checkbox) * [Chip](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/typography-and-content/chip) * [Choice list](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/choice-list) * [Clickable](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/clickable) * [Clickable chip](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/clickable-chip) * [Color field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/color-field) * [Color picker](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/color-picker) * [Date field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/date-field) * [Date picker](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/date-picker) * [Divider](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/divider) * [Drop zone](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/drop-zone) * [Email field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/email-field) * [Grid](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/grid) * [Heading](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/typography-and-content/heading) * [Icon](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/media-and-visuals/icon) * [Image](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/media-and-visuals/image) * [Link](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/link) * [Menu](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/menu) * [Money field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/money-field) * [Number field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/number-field) * [Ordered list](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/ordered-list) * [Paragraph](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/typography-and-content/paragraph) * [Password field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/password-field) * [Query container](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/query-container) * [Search field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/search-field) * [Section](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/section) * [Select](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/select) * [Spinner](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/feedback-and-status-indicators/spinner) * [Stack](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/stack) * [Switch](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/switch) * [Table](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/table) * [Text](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/typography-and-content/text) * [Text area](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/text-area) * [Text field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/text-field) * [Thumbnail](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/media-and-visuals/thumbnail) * [Tooltip](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/typography-and-content/tooltip) * [Url field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/url-field) * [Unordered list](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/unordered-list) ### Available APIs * [Action Extension API](https://shopify.dev/docs/api/admin-extensions/2026-01/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 your app backend to push discount details to third-party point-of-sale systems. ##### 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 [posSystem, setPosSystem] = useState('square'); const [syncAllLocations, setSyncAllLocations] = useState(true); const handleSync = async () => { setLoading(true); setError(null); const discountId = shopify.data.selected[0].id; try { const response = await fetch('https://your-app.com/api/sync-discount-to-pos', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ discountId, 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); } }; return ( {success && ( Discount synced to POS successfully! )} {error && ( {error} )} setPosSystem(e.currentTarget.value)} > Square Clover Lightspeed setSyncAllLocations(e.currentTarget.checked)} /> {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, showing key metrics like total redemptions and usage limits. ##### 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 } } } }`, variables: {id: discountId}, }), }); const {data} = await response.json(); const discount = data?.discountNode?.discount; setAnalytics({ title: discount?.title || 'Unknown', usageCount: discount?.asyncUsageCount || 0, usageLimit: discount?.usageLimit || 'Unlimited', startsAt: discount?.startsAt, endsAt: discount?.endsAt, }); } catch (err) { setError(true); } finally { setLoading(false); } }; if (loading) { return ( Loading analytics... ); } return ( {error && ( Failed to load discount analytics. )} {analytics && ( Total Redemptions: {analytics.usageCount} Usage Limit: {analytics.usageLimit} Active since: {new Date(analytics.startsAt).toLocaleDateString()} )} Refresh 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/2026-01/target-apis/utility-apis/should-render-api) Examples ### Examples * #### ##### Description Add an action extension that only appears when the discount is being tracked by your analytics platform, checking with your app backend to determine if performance data is available for this discount. ##### jsx ```jsx export default async () => { const discountId = shopify.data.selected[0].id; try { // Check with app backend if this discount has analytics tracking enabled const response = await fetch('https://your-app.com/api/discount-tracking/check', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ discountId, checkType: 'performance_data', }), }); if (!response.ok) { console.error('Failed to check discount tracking status'); return { display: false }; } const result = await response.json(); // Show action if discount is tracked and has performance data return { display: result.isTracked && result.hasPerformanceData, }; } catch (err) { console.error('Error checking discount analytics:', error); return { display: false }; } }; ``` * #### ##### Description Display the action button only when the discount has specific products or collections assigned, allowing merchants to view and manage eligible items. ##### 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 GetDiscountDetails($id: ID!) { discountNode(id: $id) { discount { ... on DiscountCodeBasic { customerGets { items { ... on DiscountProducts { productVariantsCount { count } collectionsCount: collections { totalCount } } } } } ... on DiscountAutomaticBasic { customerGets { items { ... on DiscountProducts { productVariantsCount { count } collectionsCount: collections { totalCount } } } } } } } }`, 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?.totalCount > 0; return { display: hasProducts || hasCollections }; } catch (err) { console.error('Error checking discount eligibility:', error); return { display: false }; } }; ``` *** ## Discount index targets Use [action targets](https://shopify.dev/docs/api/admin-extensions/2026-01#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/2026-01/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/2026-01/web-components/settings-and-templates/admin-action) * [Avatar](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/media-and-visuals/avatar) * [Badge](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/feedback-and-status-indicators/badge) * [Banner](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/feedback-and-status-indicators/banner) * [Box](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/box) * [Button](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/button) * [Button group](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/button-group) * [Checkbox](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/checkbox) * [Chip](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/typography-and-content/chip) * [Choice list](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/choice-list) * [Clickable](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/clickable) * [Clickable chip](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/clickable-chip) * [Color field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/color-field) * [Color picker](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/color-picker) * [Date field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/date-field) * [Date picker](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/date-picker) * [Divider](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/divider) * [Drop zone](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/drop-zone) * [Email field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/email-field) * [Grid](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/grid) * [Heading](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/typography-and-content/heading) * [Icon](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/media-and-visuals/icon) * [Image](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/media-and-visuals/image) * [Link](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/link) * [Menu](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/actions/menu) * [Money field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/money-field) * [Number field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/number-field) * [Ordered list](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/ordered-list) * [Paragraph](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/typography-and-content/paragraph) * [Password field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/password-field) * [Query container](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/query-container) * [Search field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/search-field) * [Section](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/section) * [Select](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/select) * [Spinner](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/feedback-and-status-indicators/spinner) * [Stack](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/stack) * [Switch](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/switch) * [Table](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/table) * [Text](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/typography-and-content/text) * [Text area](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/text-area) * [Text field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/text-field) * [Thumbnail](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/media-and-visuals/thumbnail) * [Tooltip](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/typography-and-content/tooltip) * [Url field](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/forms/url-field) * [Unordered list](https://shopify.dev/docs/api/admin-extensions/2026-01/web-components/layout-and-structure/unordered-list) ### Available APIs * [Action Extension API](https://shopify.dev/docs/api/admin-extensions/2026-01/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 to POS'); } } 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 terminals. 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/2026-01/target-apis/utility-apis/should-render-api) Examples ### Examples * #### ##### Description Show the discount performance action only when the app backend confirms the selected discount has tracking enabled and sufficient redemption data available for analysis. ##### jsx ```jsx export default async () => { const discountId = shopify.data.selected[0].id; try { const response = await fetch('https://your-app.com/api/discount-tracking/check', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ discountId, checkType: 'performance-eligibility', }), }); if (!response.ok) { console.error('Failed to check discount tracking status'); return { display: false }; } const result = await response.json(); // Show action if discount has tracking enabled and has redemption data const hasTrackingEnabled = result.trackingEnabled === true; const hasRedemptionData = result.redemptionCount > 0; return { display: hasTrackingEnabled && hasRedemptionData }; } catch (err) { console.error('Error checking discount performance eligibility:', error); 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:', error); 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/2026-01#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. ***