Table of Contents
- Key Highlights
- Introduction
- What analytics targets are and how merchants benefit
- The new Admin GraphQL operations and what each does
- Deduplication rules and status computation
- Filters and ShopifyQL WHERE constraints
- Permissions, authentication, and security considerations
- The two new ColumnDataType enum values and their impact
- Practical integration patterns and end-to-end examples
- Best practices for developers
- Migration and compatibility guidance
- Limitations, edge cases, and known operational concerns
- Business implications and opportunities for partners
- Implementation checklist before you start
- FAQ
Key Highlights
- Shopify’s Admin GraphQL adds four operations—analyticsTargets, analyticsTargetCreate, analyticsTargetUpdate, analyticsTargetsDelete—letting apps create and manage merchant metric targets that appear in the Shopify admin.
- Targets are uniquely identified by metric, date range, and filters; status is computed at query time (In progress, Achieved, Not achieved, Upcoming); and the API requires read_reports and write_reports scopes.
- API version 2026-04 also introduces two new ColumnDataType enum values (UNITLESS_SCALAR and MULTIPLIER) for specific metrics such as CLS percentiles and return-on-ad-spend ratios.
Introduction
Goal-setting and progress tracking sit at the center of modern merchant operations. Shopify has extended that capability to platform partners and app developers with a set of Admin GraphQL operations that let apps create, read, update, and delete analytics targets—the numeric goals merchants set for metrics such as gross sales, conversion rate, or advertising return. Targets created through the API appear in the Shopify admin alongside merchant-created targets and are subject to the same validation and presentation rules. For teams building reporting dashboards, planning tools, or agency dashboards, the new endpoints deliver a single source of truth for merchant objectives.
The release arrives as part of API version 2026-04 and includes a small but important set of changes to metric typing that will affect how some values are displayed and interpreted. The following analysis explains how the new operations work, outlines practical integration patterns, surfaces key technical constraints, and offers implementation guidance grounded in real-world use cases.
What analytics targets are and how merchants benefit
Analytics targets encapsulate a simple idea: set a numeric target for a metric over a defined time range and track progress with a visual gauge. Shopify already exposes this feature to merchants in the admin; the new Admin GraphQL operations let apps participate in the same workflow.
How merchants use targets
- Set a revenue target for a quarter: “Achieve $50K in gross sales this quarter.”
- Monitor conversion rate improvements for a new checkout flow.
- Track return on ad spend (ROAS) for a specific campaign or channel.
- Establish performance thresholds for site health metrics like CLS percentiles (which are now explicitly typed).
Targets appear in Shopify’s Targets index page and can be displayed on merchant dashboards. When an app creates a target, merchants see it in the same interfaces and can modify or delete it through the admin UI. That parity matters: apps and merchants operate on identical data and rules, reducing confusion and keeping the merchant’s analytics environment coherent.
Concrete examples
- A direct-to-consumer (DTC) brand sets a quarterly gross-sales target using a planning app. The app suggests a target equal to last year’s Q2 revenue grown by 12%, creates the target through the API, and shows a progress gauge in its own dashboard that mirrors Shopify admin.
- A media agency automates target creation across multiple client stores. Each client receives a monthly sales target filtered to the ad-driven sales channel.
- A BI vendor reads targets and overlays them onto custom visualizations so merchants see actuals and goals in one place, eliminating the need to cross-reference external spreadsheets.
These examples show how the API helps centralize goal-setting, reduce duplication, and ensure consistency across tools.
The new Admin GraphQL operations and what each does
Four new operations give apps full control over targets:
- analyticsTargets (query): Retrieve targets for a shop, with pagination support.
- analyticsTargetCreate (mutation): Create a new target specifying metric, amount, time period, optional filter, and human-readable name.
- analyticsTargetUpdate (mutation): Update an existing target’s fields, including metric and filters.
- analyticsTargetsDelete (mutation): Remove targets. Deletions are permanent.
Data model essentials Each target includes the following core attributes:
- metric: the analytic metric identifier (for example, gross_sales, conversion_rate, shop_campaign_return_on_ad_spend).
- amount: the numeric goal for the metric.
- time period: a start and end date or a named window (quarter, month).
- filters: an optional single, dimension-based filter expressed through a WHERE statement in ShopifyQL (operators supported: = and IN).
- name: an optional descriptive label.
- status: an enumerated field derived by the API at query time (In progress, Achieved, Not achieved, Upcoming).
Basic read flow The analyticsTargets query returns target objects with pagination. Applications should implement cursor-based pagination to handle shops with many targets. The status field is computed by Shopify using the current metric value; therefore, a single response gives both the static target definition and a real-time status snapshot.
Create flow A typical analyticsTargetCreate mutation requires:
- metric (string)
- amount (numeric)
- date range or time window
- optional filter (dimension + operator + value(s))
- optional name
If a target with the same metric, date range, and filters already exists, the API rejects the creation request and returns a userError with guidance on how to adjust the request.
Update flow analyticsTargetUpdate accepts the target’s unique identifier and the fields to change. Updates follow the same deduplication rules; changing a metric or filters in a way that duplicates an existing target triggers an error.
Delete flow analyticsTargetsDelete removes one or more targets. Deleted targets cannot be recovered. Applications should implement an audit trail or soft-delete alternative before calling the delete mutation if recovery is required for business workflows.
Example mutation skeletons Below are simplified examples to illustrate shape and intent. Replace placeholder values with real inputs in production.
Create a target (simplified)
mutation {
analyticsTargetCreate(input: {
metric: "gross_sales",
name: "Q2 Revenue Goal",
amount: 50000,
startDate: "2026-04-01",
endDate: "2026-06-30",
filter: { dimension: "sales_channel", operator: "=", values: ["online_store"] }
}) {
target {
id
metric
amount
startDate
endDate
filter { dimension operator values }
status
}
userErrors { field message }
}
}
Read targets (page)
query {
analyticsTargets(first: 50, after: "cursor") {
edges { cursor node { id metric amount startDate endDate status } }
pageInfo { hasNextPage endCursor }
}
}
Update a target (simplified)
mutation {
analyticsTargetUpdate(id: "gid://shopify/AnalyticsTarget/123", input: {
name: "Q2 Adjusted Revenue Goal",
amount: 52000
}) {
target { id name amount status }
userErrors { field message }
}
}
Delete targets
mutation {
analyticsTargetsDelete(ids: ["gid://shopify/AnalyticsTarget/123"]) {
deletedIds
userErrors { field message }
}
}
Handle userErrors GraphQL responses include userErrors with field and message. Expect and process these; they provide specific guidance for deduplication and validation failures.
Deduplication rules and status computation
Deduplication is a critical design choice. Each target is uniquely identified by the combination of:
- metric
- date range (start and end)
- filter(s)
Attempting to create another target that matches an existing target on those dimensions triggers a userError. The error explains which fields to modify. This approach prevents accidental duplication when apps retry requests or when multiple apps attempt to create the same objective.
Status computation is handled server-side. The API computes one of four states:
- In progress: the target is active (date range includes the current date) and not yet achieved.
- Achieved: the current metric value meets or exceeds the amount within the target date range.
- Not achieved: the date range has passed and the metric value did not meet the target.
- Upcoming: the start date is in the future.
Because status derives from live metric data, callers receive a real-time view when they query analyticsTargets. That makes the API suitable for dashboards and notifications without reimplementing the metric and status logic in each app.
Real-world handling of deduplication and status
- Idempotent creation: generate a deterministic client-side key based on metric, date range, and filter and check analyticsTargets before calling analyticsTargetCreate, reducing the chance of a userError due to duplication.
- Concurrency: when multiple processes may create targets concurrently, implement optimistic retries: catch userError indicating duplication and fetch the existing target instead of failing.
- Status-driven UX: when status switches to Achieved, notify the merchant and log the achievement in your app. For Not achieved, suggest follow-up actions or post-mortem analytics.
Filters and ShopifyQL WHERE constraints
Targets support exactly one dimension-based filter specified using a WHERE clause in ShopifyQL and limited to equality or membership operators:
- = (equals)
- IN (membership list)
This single-filter constraint keeps the target model simple and predictable. Use filters to limit a target to a sales_channel, a campaign, a product, or any dimension supported by ShopifyQL.
Filter examples
- Limit to a sales channel:
- WHERE sales_channel = "online_store"
- Limit to specific product IDs:
- WHERE product_id IN [123456789, 987654321]
- Limit to a marketing campaign:
- WHERE campaign = "spring_launch"
Practical considerations
- Validation: validate dimension names and values against Shopify’s supported dimensions before calling the API to reduce userErrors.
- Values format: when using IN, supply a list of values typed correctly. For string dimensions, match the expected canonical identifiers; numeric dimensions must be numbers.
- Ambiguity and collisions: two filters that are syntactically different but semantically equal (for example, different order in an IN list) should be normalized client-side to avoid accidental duplication.
Limitations
- Only one filter is permitted. If a use case requires combining multiple dimensions (for example, sales_channel = online_store AND product_type = "shoes"), apps must either create broader or more granular targets outside this single-filter model, or track cross-filters locally and map them into separate targets.
- Operators restricted to = and IN. Range-based or LIKE-style filters are not supported.
Permissions, authentication, and security considerations
Access to targets requires explicit permissions:
- read_reports
- write_reports
Ensure your app requests these scopes during OAuth installation. Both read and write scopes are necessary to create or modify targets; read_reports alone allows reading existing targets.
Authentication and token management
- Use OAuth tokens issued at installation time. Rotate and store tokens securely.
- Respect least privilege: request only the scopes you need and document the need clearly in your app’s installation flow.
- Rate limits: Shopify applies API rate limits. Use cursor-based pagination, efficient queries, and exponential backoff on retries.
Access control and merchant interactions
- Merchant control: anything created by your app appears in the merchant’s admin and can be edited or deleted by the merchant. Build UIs that make ownership clear and allow merchants to revoke app-created targets if desired.
- Deletions: deletes are permanent. If your business requires recoverability, implement an internal archive before calling analyticsTargetsDelete.
- Audit trails: record target creation, updates, and deletions in your app’s logs, including the acting user and timestamp. This supports troubleshooting and merchant trust.
Security best practices
- Validate inputs server-side to prevent injection-like errors in filter values. While ShopifyQL filters are constrained, bad inputs can cause rejections or unpredictable behavior.
- Avoid exposing raw API credentials. Use backend services for calls and pass only necessary identifiers to front-end components.
- Monitor userErrors and quota usage to detect abuse or misconfiguration.
The two new ColumnDataType enum values and their impact
API version 2026-04 adds two ColumnDataType enum values to Shopify’s ShopifyQL table data columns:
- UNITLESS_SCALAR: A dimensionless numeric score. Applied to web performance metrics such as Cumulative Layout Shift percentiles: p50_cls, p75_cls, p90_cls, p99_cls. These values represent scores that have no associated unit.
- MULTIPLIER: A ratio or multiplier value, for example “3.2x.” Applied to metrics like shop_campaign_return_on_ad_spend (ROAS).
Prior to this change, these metrics returned as FLOAT. The new enum values are a signal to callers about how to format and label values in UIs and reports.
Practical UI implications
- Formatting: Display UNITLESS_SCALAR values as plain numbers without units and with appropriate precision (for example, 0.12). Display MULTIPLIER values with an “x” suffix and appropriate decimal precision (for example, 3.2x).
- Axis labels and tooltips: When plotting MULTIPLIER values, label axes to indicate “Multiplier (x)” to avoid confusion with percentage or currency axes.
- Aggregation: Metrics typed as UNITLESS_SCALAR may require different aggregation semantics than currency values; double-check rounding and percentile computations before summarizing.
Compatibility
- Apps using older API versions will continue to see FLOAT for these metrics until they upgrade their GraphQL requests to 2026-04 or later.
- When migrating, update UI formatting logic to respect the new enum values to avoid mislabeling or misunderstanding of metric semantics.
Practical integration patterns and end-to-end examples
This section lays out common implementation patterns and concrete, realistic examples that show how apps will use the new operations.
Pattern: Smart default targets based on historical performance Goal: When onboarding a merchant, suggest targets that are realistic and data-driven.
Flow:
- Query historical metric values (e.g., previous quarter gross sales).
- Compute a suggested target, for example, historical value * 1.10 for a 10% growth target.
- Present the suggested value to the merchant for confirmation.
- On merchant approval, call analyticsTargetCreate with the recommended metric, dates, and an optional name.
Example
- Historical Q2 gross sales (2025): $45,000
- Suggested Q2 2026 target: $45,000 * 1.10 = $49,500
- Create target with startDate = 2026-04-01, endDate = 2026-06-30, amount = 49500
Pattern: Agency dashboard automating targets for clients Goal: An agency wants consistent targets across 25 client stores and needs to create, monitor, and adjust them programmatically.
Flow:
- Iterate over each client store with valid OAuth tokens and required scopes.
- For each store, compute or retrieve a target specification.
- Before creating, check analyticsTargets to avoid duplication.
- Create or update targets as necessary.
- Aggregate target status across clients for a single agency dashboard.
Operational notes:
- Implement rate limit handling for batch operations.
- Use idempotent patterns: query existing targets for the same metric/date/filter before creating.
- Record command timestamps and responses for each client to aid troubleshooting.
Pattern: BI tool aligning visualizations to Shopify goals Goal: Display merchant targets alongside charted actuals.
Flow:
- Query analyticsTargets to retrieve targets for a merchant.
- Render a gauge or overlay the target value on charts showing historical and current metric values.
- Subscribe to periodic updates or refresh on-demand; remember status is live at query time, so scheduled refreshes keep the UI current.
Example graph overlay
- A time-series chart of daily gross sales with a horizontal line representing the target and a label showing current progress and status. The line aligns with the target amount; the label uses status to color the display (green for Achieved, amber for In progress, red for Not achieved).
Pattern: Forecasting app that imports external goals Goal: A planning app stores higher-level business objectives (e.g., corporate revenue targets) and imports them into Shopify analytics.
Flow:
- Translate external targets into Shopify-compatible metrics and filters.
- Create targets via analyticsTargetCreate so merchants can see corporate objectives in their Shopify admin.
- When external goals change, call analyticsTargetUpdate to maintain parity.
Caveats:
- Ensure target semantics match Shopify metrics. For instance, an external goal defined as “net revenue” must map to the correct Shopify metric (gross_sales vs net_sales, if applicable).
- Respect the single-filter constraint by choosing the most representative dimension.
Example GraphQL flows (expanded) Check for an existing target and create if absent:
# 1. Query existing targets for the metric/date range
query GetTargets($metric: String!, $start: Date!, $end: Date!) {
analyticsTargets(first: 10, query: {metric: $metric, startDate: $start, endDate: $end}) {
edges { node { id metric startDate endDate filter { dimension operator values } } }
}
}
# 2. If none exists, create
mutation CreateTarget($input: AnalyticsTargetCreateInput!) {
analyticsTargetCreate(input: $input) {
target { id metric amount startDate endDate status }
userErrors { field message }
}
}
Normalize filter values client-side to ensure consistent ordering and representation before issuing the create mutation.
Best practices for developers
Adopt patterns that reduce friction for merchants, improve reliability, and prevent duplicate or invalid targets.
- Request the minimum scopes required. Explain to merchants why read_reports and write_reports are necessary in install flows.
- Normalize filter representations locally. For example, sort values in IN lists and canonicalize dimension names to prevent false duplicates.
- Implement idempotent creation. Query analyticsTargets with the target signature before creating. If a userError indicates duplication, fetch the existing target instead of retrying blindly.
- Validate inputs prior to the mutation. Check date ranges, amount types, and filter dimensions against supported values to reduce API rejections.
- Respect merchant ownership. Clearly label targets created by your app and provide UI affordances for merchants to edit or revoke targets.
- Archive before delete. Because deletes are permanent, maintain an internal copy or approval workflow if deletion reversibility is required.
- Present status meaningfully. Use the status field to drive alerts and notifications, but avoid over-notifying merchants—suggest actions instead of flooding.
- Handle pagination efficiently. Use cursor-based pagination when enumerating targets for shops with many goals.
- Log userErrors and alert on frequent validation failures to identify UX problems or mismatched assumptions.
- Localize date handling. Date ranges should be presented and interpreted in the merchant’s timezone to avoid confusion about when a target starts and ends.
Migration and compatibility guidance
Apps that previously tracked goals in external systems will find value migrating to Shopify targets to reduce duplication and keep merchant-facing analytics consolidated. Migration requires mapping your internal target schema to Shopify’s shape: metric identifier, amount, date range, and single filter dimension.
Steps for migration
- Inventory targets in your system and map metrics to Shopify metric identifiers.
- Normalize filters to the single-dimension model supported by Shopify. If your system uses multi-dimensional filters, either split them into multiple targets or keep the composite logic internal while creating simplified Shopify targets.
- Determine migration windows to avoid conflicts with existing merchant-created targets. Offer merchants a review step before programmatically creating targets in their stores.
- Update UI formatting to handle new ColumnDataType enum values for metrics that change semantics (UNITLESS_SCALAR and MULTIPLIER).
- Revoke or archive external targets once Shopify targets exist to prevent confusion.
Backward compatibility
- The ColumnDataType enum change does not affect API versions prior to 2026-04. If your app supports multiple API versions, detect the version and adapt formatting accordingly.
- Existing targets in Shopify created before 2026-04 continue to exist; the new operations add creation and management entry points for apps.
Limitations, edge cases, and known operational concerns
Understanding the model’s limits leads to more robust integrations.
Single-filter constraint Complex goal definitions that require more than one filter cannot be represented natively. A merchant wanting “Sales for shoes on mobile channel” (product_type = "shoes" AND sales_channel = "mobile") cannot represent that as a single target. Options:
- Create two targets and combine their semantics in your app.
- Maintain composite goals in your app and project a simplified Shopify target that captures the most important dimension.
Deduplication collisions Because deduplication keys rely on metric/date/filter combinations, two semantically different intentions that map to the same key will collide. Normalize inputs and use explicit naming to help merchants distinguish targets in the Shopify admin.
Deleted targets are permanent Once analyticsTargetsDelete removes a target, it cannot be recovered through the API. Build a soft-delete workflow if your business requires reversible deletions.
Status timing and freshness Status is computed at query time using the latest available metric value. If your app caches target objects, consider refreshing status on a cadence aligned with your needs—stale status can lead to misleading UI signals.
Metric availability and granularity Not every metric may be meaningful for targets in every shop. Confirm metric availability and semantics before creating a target. For example, sampling or delayed metrics could cause temporary gaps in status updates.
Operator limitations on filters Only = and IN operators are supported. Range or regex-style filters are not available. Work within these constraints or maintain additional logic in your app.
Business implications and opportunities for partners
The API unlocks several lines of product innovation and operational efficiency for agencies, app developers, and analytics vendors.
Consolidated goal management Apps can centralize goals from multiple sources—marketing platforms, finance systems, and internal planning tools—by writing them into Shopify Analytics. Merchants get a single view in the admin, reducing cognitive overload and the need to consult multiple dashboards.
Automated operations for agencies Agencies can automate target rollouts across client portfolios and monitor progress centrally. That reduces manual work and enables consistent benchmarking across clients.
Enhanced reporting consistency When BI tools read Shopify targets rather than maintaining separate goal states, the merchant’s reported progress lines up with Shopify admin, eliminating discrepancies and disputes.
New product features
- Automated recommendations: apps can create targets automatically based on historical trends and merchant tolerance, then surface suggested actions if targets fall behind.
- Goal-based automations: trigger messages, discounts, or ad spends when targets reach defined thresholds.
- Cross-channel reconciliation: use filters to focus targets on specific channels and measure the impact of channel-level investments.
Evidence of ROI Consider a hypothetical scenario: a merchant increases quarterly conversion rate by optimizing checkout with a goal-driven experiment. With targets programmed and tracked centrally, the merchant detects a 0.5 percentage point lift and attributes $12K incremental revenue to the optimization. Centralized tracking shortens the feedback loop and clarifies what actions produced results.
Implementation checklist before you start
- Confirm your app requests read_reports and write_reports scopes.
- Build input validation for metric identifiers, amounts, date ranges, and filter dimensions.
- Implement a query step to check for existing targets before creating new ones.
- Normalize filter representations (canonical ordering of IN lists).
- Add audit logging for create/update/delete operations.
- Prepare UI formatting for UNITLESS_SCALAR and MULTIPLIER values.
- Design a recovery plan because deletions are irreversible.
- Handle pagination for analyticsTargets queries at scale.
- Create rate-limit-aware batching logic for multi-client operations.
FAQ
Q: What GraphQL operations do I need to manage analytics targets? A: Use analyticsTargets to read targets, analyticsTargetCreate to create, analyticsTargetUpdate to update, and analyticsTargetsDelete to remove targets.
Q: What permissions does my app need? A: Both read_reports and write_reports scopes are required for full management (read and write) of analytics targets.
Q: Can I create duplicate targets? A: No. The API deduplicates based on metric, date range, and filters. Attempts to create a duplicate return a userError with guidance.
Q: How is target status determined? A: The API computes status at query time using the target’s date range and the current metric value. Status values are In progress, Achieved, Not achieved, and Upcoming.
Q: Can I apply multiple filters to a target? A: No. Each target accepts one dimension-based filter in the ShopifyQL WHERE statement. The filter supports = and IN operators only.
Q: Are deleted targets recoverable? A: No. Deleted targets cannot be recovered through the API. Implement an internal archive if recovery is important to your workflow.
Q: How do the new ColumnDataType enum values affect me? A: API version 2026-04 adds UNITLESS_SCALAR and MULTIPLIER. Use these types to determine formatting and semantics for metrics like CLS percentiles and ROAS. Older API versions still return FLOAT for these metrics.
Q: How should I handle deduplication errors? A: Treat deduplication userErrors as signals to fetch the existing target. Implement idempotency by checking for existing targets before creating, and normalize filter representations to reduce accidental collisions.
Q: Can apps create targets that merchants can’t see or edit? A: No. Targets created by apps appear in the Shopify admin and can be managed by merchants. Apps should make ownership and provenance clear.
Q: What display considerations exist for UNITLESS_SCALAR and MULTIPLIER? A: Display UNITLESS_SCALAR without units and with appropriate precision. Display MULTIPLIER values with an “x” suffix and label axes or tooltips accordingly.
Q: Are there rate limits I should be aware of? A: Shopify enforces API rate limits. Use efficient queries, cursor-based pagination, and exponential backoff on retries when performing batch operations across multiple stores.
Q: Can I set targets for any metric? A: Most commonly used metrics are supported, but confirm metric availability and semantics before creating targets. Some metrics may have delayed or sampled values that influence status computation.
Q: How do I handle timezone differences for date ranges? A: Present and store date ranges in the merchant’s timezone when possible. Confirm how Shopify computes date boundaries for analytics to ensure start and end dates align with merchant expectations.
Q: Should I keep a copy of targets in my system? A: It’s advisable to store a local copy for auditing, recovery, and offline workflows. Remember that Shopify is the source of truth for status and presentation.
Q: How do I migrate existing external targets into Shopify? A: Map your internal metrics and filters to Shopify’s metric identifiers and the single-filter model. Offer a merchant review step before creating targets in the Shopify admin. Archive or delete external targets after migration to avoid confusion.
Q: What happens if multiple apps create targets with the same intent? A: Deduplication prevents exact duplicates, but apps can create overlapping or related targets. Provide clear naming and provenance in your app to help merchants distinguish origins and purposes.
Q: Can I use analyticsTargets for automation or scheduled tasks? A: Yes. Use analyticsTargets in scheduled workflows to read status and trigger notifications or automated actions. Ensure you respect rate limits and implement backoff strategies.
This release provides a practical, consistent way for apps to manage merchant objectives directly within Shopify’s analytics. Developers should focus on normalization, idempotency, and clear UX around ownership and status so that merchants gain a unified, trustworthy view of goals across tools and channels.