Table of Contents
- Key Highlights
- Introduction
- What changed in API version 2026-07
- The GraphQL mechanics: fields, queries, and mutations you’ll use
- How this changes storefront behavior and merchant workflows
- Implications for apps and integrations
- Migration and implementation guidance for developers
- Best practices and real-world examples
- Testing, monitoring and rollout checklist
- Common pitfalls and troubleshooting
- FAQ
Key Highlights
- ProductVariant now implements the Publishable interface in Admin GraphQL API 2026-07, allowing merchants and apps to publish or unpublish individual variants per publication (channel/catalog) without deleting or duplicating products.
- The change is non-breaking: product-level publishing still takes precedence, variants default to published, and APIs provide fields and mutations to read and change variant publication state; webhook behavior for product feeds and incremental syncs has been updated, while variant_publication webhooks are arriving soon.
Introduction
Merchants increasingly need fine-grained control over which product options appear in which sales channels. A single product might offer region-specific sizes, channel-exclusive colors, or limited-edition SKUs that should not be exposed everywhere. Shopify’s Admin GraphQL API now supports that control at the variant level: ProductVariant is a Publishable resource in API version 2026-07. That simple statement changes how stores, channels, and apps manage visibility. The update reduces the need to duplicate products, simplifies staged rollouts, and gives integrations explicit publication metadata to read and act upon.
The change is intentionally additive and backward compatible. Product-level publishing still controls whether any variant can appear in a channel. Variants default to published, preserving existing behavior for apps that do not examine variant publication. For apps and channels that want more precision, the API introduces new fields, mutation targets, and webhook signals. The rest of this article explains what changed, how it works on a technical level, how different classes of apps should adapt, and practical patterns for migration, testing, and rollout.
What changed in API version 2026-07
The update centers on three areas: schema, mutation surface, and webhook behavior.
Schema and interface
- ProductVariant now implements the Publishable interface. That brings ProductVariant into the same publication model as Product and Collection. Key fields surfaced via the interface include resourcePublicationv2 and publishedOnPublication, giving a variant-level representation of which publication entries (channels, catalogs, markets) include the variant.
- Product-level publishing remains authoritative: a product must be active and published to a channel for any of its variants to appear.
Mutations
- publishablePublish and publishableUnpublish now accept ProductVariant IDs alongside Product and Collection IDs. This allows apps to publish or unpublish a single variant without altering the product’s publication state.
Webhook and product feed behavior
- Product feed webhooks (incremental syncs) will fire when variants are added or deleted in feeds’ channels. For channel apps using product feeds, no immediate change is required: the product feed will add or remove variants from the product and trigger incremental sync webhooks, enabling downstream systems to stay in sync.
- Explicit variant_publication/create/update/delete webhooks are still being developed and will be shipped imminently. Until they arrive, apps that do not use product feeds should rely on reading the variant’s resourcePublicationv2 state via the Admin GraphQL API to discover publication changes.
Default and creation behavior
- Variants default to published (opt-out model). Existing integrations that create variants without specifying publication state will see those variants published in all parent product publications by default.
- If an app needs to create a variant in an unpublished state to prevent early exposure, APIs support this directly: productSet and productVariantBulkCreate accept a variant.published: false field to create variants as unpublished.
Why Shopify opted for this model
- The model reduces painful workarounds merchants and developers previously relied upon: deleting variants, duplicating products solely to hide options in a channel, or relying on storefront code to hide options.
- It maintains stability for existing apps while giving new capabilities to apps that require or can take advantage of variant-level visibility.
The GraphQL mechanics: fields, queries, and mutations you’ll use
Understanding exact GraphQL access patterns makes implementation planning straightforward. Below are representative queries and mutations based on the declarations announced for 2026-07.
Reading variant publication state
- The Publishable interface exposes a resourcePublicationsv2 field (often surfaced as resourcePublicationv2 or resourcePublicationsv2 depending on pagination and API naming). Use that field to fetch which publications include the variant and whether it is published on a specific publication.
Example query to fetch a variant’s publication records:
query VariantPublication($id: ID!) {
node(id: $id) {
... on ProductVariant {
id
sku
title
resourcePublicationsv2(first: 10) {
edges {
node {
publication {
id
name
channel
}
publishedOnPublication
status
updatedAt
}
}
}
}
}
}
This returns the publication entries for the variant, whether it is published on each, and timestamps for auditing.
Publishing and unpublishing variants
- The publishablePublish and publishableUnpublish mutations accept variant IDs. Both accept arrays of IDs so you can toggle publication state for multiple variants in one request.
Example publish mutation:
mutation PublishVariants($ids: [ID!]!) {
publishablePublish(ids: $ids) {
publishedResources {
id
__typename
}
userErrors {
field
message
}
}
}
Unpublish uses the same shape with publishableUnpublish.
Creating unpublished variants via bulk APIs
- productSet and productVariantBulkCreate accept variant.published: false so newly created variants remain hidden until the merchant or app explicitly publishes them.
Example bulk create snippet (schema abridged for clarity):
mutation BulkCreateVariants($input: ProductVariantBulkCreateInput!) {
productVariantBulkCreate(input: $input) {
createdVariants {
id
sku
published
}
userErrors {
field
message
}
}
}
Set variant.published: false inside the input to prevent immediate exposure.
Webhook behavior and interim patterns
- Product feed webhooks will trigger incremental syncs for channel apps when variants are added or removed from the feed’s channel.
- The dedicated variant_publication webhooks are pending. Until they’re available, apps that need immediate, event-driven updates should:
- Subscribe to product update webhooks for products belonging to channels the app manages; product updates include changes to product feeds and may contain variant changes.
- Poll or query resourcePublicationsv2 for critical use cases, while avoiding excessive polling by using efficient batching and backoff strategies.
API versioning and non-breaking nature
- The change is additive: it will not break existing calls. Because variants default to published, existing logic that assumes variants are visible remains correct unless a new app or merchant starts leveraging unpublished variants.
How this changes storefront behavior and merchant workflows
A single sentence often misses the practical consequences. This update changes everyday workflows for merchants, channel owners, and app developers.
Product vs variant precedence
- Product must be active and published to a channel for any variant to render in that channel. Publishing a variant has no effect if the parent product remains unpublished or inactive. This preserves the top-level behavior store owners expect.
Use cases unlocked
- Channel-specific options: A retailer can control which sizes or colors appear in a particular marketplace without creating a parallel product catalog. For example, a shoe seller can keep a limited-edition color publishable only on their own site and not in a marketplace.
- Staged rollouts and pre-release inventory: Merchants can create variants for upcoming drops in an unpublished state and toggle them live when ready; the variant retains the same product page and history.
- Regional regulations and compliance: If specific variants fail compliance checks in certain markets, stores can unpublish just those variants without taking down the entire product.
- A/B testing at variant granularity: Marketers can test a variant’s conversion performance on a channel without impacting other variants.
- Promotional exclusivity: Reserving specific SKUs for subscription boxes or point-of-sale channels becomes straightforward.
Practical example: a fashion retailer A brand maintains one product "Classic Tee" with variants for S/M/L and multiple colors. They want:
- Exclusive color “Midnight” only on their DTC site.
- A marketplace that cannot sell size XL due to logistics. Before variant-level publishing, the typical options were to duplicate the product with a different catalog, hide options via storefront logic that can be brittle, or manage inventory and list suppression. Now, the brand can:
- Keep one product published across channels.
- Unpublish the "Midnight" variant on the marketplace publication.
- Unpublish the "XL" variant on the marketplace publication. This reduces catalog duplication, simplifies SKU mapping, and preserves analytics continuity.
Effect on product feeds and channels
- Channels using product feeds will receive updates reflecting variant additions/removals. The feed's channel logic decides whether to include a variant. Product feed webhooks fire with product updates when variants are published to the feed’s channel, enabling incremental sync behavior for downstream systems.
- Channels or integrations that do not use product feeds must implement reading variant publication metadata from the Admin GraphQL API.
Edge cases merchants must watch
- If a merchant unpublishes all variants while leaving the product published, storefront behavior will vary depending on theme logic. A product page might still render but with no selectable options. Themes and apps should be designed to gracefully handle empty option sets.
- Inventory and fulfillment flows must account for variant visibility. Unpublished variants should not appear in channel-specific order flows, but internal systems must ensure stock is tracked appropriately.
Implications for apps and integrations
The update affects several classes of apps differently. Below are recommended actions and architectural considerations for common app types.
Channel apps (marketplaces, catalog integrators)
- Product-feed-based channel apps: no required changes. Feeds will add or remove variants and incremental sync webhooks will be triggered. Confirm your webhook handling correctly interprets variant-level changes in the product payload.
- Channel apps that rely on reading publication state via Admin GraphQL: update to read ProductVariant.resourcePublicationsv2 for accurate variant-level publication information. Do not assume product-level publication equates to variant visibility.
Inventory and PIM systems
- Inventory management platforms should recognize variant-level publication is a presentation concern. Inventory tracking continues regardless of publication state, but channel-specific fulfillment logic may need to exclude unpublished variants.
- When syncing SKUs to external catalogs, respect the publication state to avoid exposing unpublished SKUs to marketplaces.
Merchandising and marketing apps
- Apps that automate promotions or visibility must consider variant-level targeting: promotions attached to a product should verify that targeted variant(s) are published in the intended channel.
- For scheduled campaigns, use variant.published: false when creating variants intended for future release and call publishablePublish at the scheduled time.
Order management and fulfillment apps
- Order routing systems must not assume a variant is always available. Implement checks against publication state if a downstream channel or marketplace is the source of truth for what's sellable in that channel.
- Confirm the storefront and order API semantics: if a channel's storefront hides variants via unpublishing, orders from that channel should not include those variants. Validate with integration tests.
Apps that create variants after product publication
- New variants default to published in all of the parent product’s publications. This behavior avoids surprise invisibility, but it may expose variants earlier than desired.
- If your app needs to create variants in an unpublished state, use the variant.published: false option in productSet or productVariantBulkCreate inputs.
Apps that publish products
- Apps that only publish at the product level do not need changes. They can continue calling publishablePublish on products as before.
- Consider implementing variant publishing support if unpublishing variants is relevant to your workflows, especially when channel-specific exclusions are needed.
Security and permission model considerations
- Ensure your app has permissions to read and modify publication state for variants. Publication mutations and resourcePublicationsv2 access require appropriate scopes. Test under least privilege to avoid over-granting access.
Migration and implementation guidance for developers
This section outlines a practical migration plan, testing strategies, and code-level considerations.
Audit and inventory
- Start by inventorying integrations and flows that assume product-level visibility:
- Which features show or hide variants?
- Which systems consume product feeds?
- Which rely on GraphQL publication queries?
- Catalog cases where creating a variant should remain unpublished by default (e.g., pre-release SKUs).
Update read paths
- Update GraphQL queries that previously fetched only product.publications to include variant publication data:
- Add queries for ProductVariant.resourcePublicationsv2 or publishedOnPublication where appropriate.
- Bundle variant queries to avoid N+1 request patterns, using nodes() or a batched node query where possible.
Adjust write paths
- When creating variants programmatically, explicitly set published flag if the variant should remain hidden:
- productSet and productVariantBulkCreate support variant.published: false.
- Review code that assumes variant creation results in unpublished or published behavior; add explicit handling to match your business rules.
Webhook handling and event-driven sync
- If your app relies on product feeds, verify incremental sync handlers correctly process variant additions/removals.
- For apps not using feeds:
- Implement periodic reconciliation that queries resourcePublicationsv2 for newly changed variants.
- Use product update webhooks as an interim event source until dedicated variant_publication webhooks are available.
- Plan for the arrival of variant_publication webhooks and design handlers that can accept granular create/update/delete events with idempotency.
Concurrency, race conditions, and ordering
- When creating variants and immediately publishing them, be mindful of race conditions. The API will accept publishablePublish on variants, but ensure your code waits for a successful create before publishing or uses transactional sequences where supported.
- Use returned mutation payloads and operation IDs to track status reliably rather than relying on eventual visibility via storefronts.
Bulk operations and rate limiting
- Use bulk APIs (productVariantBulkCreate) for large-scale operations. These endpoints are more efficient and reduce the chance of hitting rate limits on many individual publishablePublish calls.
- Batch publication changes where sensible; publishablePublish accepts multiple IDs.
Testing strategy
- Unit tests: add mocks for resourcePublicationsv2 and publishable mutations.
- Integration tests: create test products and variants in a sandbox shop with multiple publications (channels) and verify expected visibility in each channel when publishing/unpublishing variants and products.
- End-to-end tests: confirm that customer-facing storefronts and third-party channels show or hide variants according to publication settings.
Versioning and progressive rollout
- Because the change is additive and default behavior preserves existing visibility, you can implement support progressively. Start by reading variant publication info and adjusting logic; only change write paths once you’ve validated behavior.
- Monitor for edge cases such as themes that expect at least one selectable variant or external systems that assume product-level equivalence.
Example migration steps for an app team
- Inventory: List endpoints and features that touch variant visibility.
- Add read support: Update queries to fetch resourcePublicationsv2 for variants.
- Observe: Run integration tests to detect differences, particularly in channels that previously relied on product-level only.
- Add create-time option: Update variant creation paths to pass variant.published: false when desired.
- Implement publish/unpublish flows: Add publishablePublish/unpublish support, batching where appropriate.
- Update webhooks: Adjust handlers for product feed incremental updates; prepare for variant_publication webhooks when they are released.
- Rollout gradually and monitor logs, user reports, and analytics to ensure no regressions.
Best practices and real-world examples
Concrete patterns help teams put the API changes into immediate use. Below are recommended practices and three real-world scenarios.
Best practices
- Treat product-level publishing as the gate and variant-level publishing as a filter. Always check both before acting on visibility.
- Use bulk APIs when creating or changing many variants.
- Implement idempotent webhook handlers and use backoff/retry for transient errors.
- Keep operational visibility: log publication operations and include publication state in your app’s admin views so merchant support can troubleshoot easily.
- Avoid polling whenever possible; prefer feeds and webhooks. When polling is necessary, increase batch size and use efficient pagination.
Real-world example 1 — Marketplace channel app A marketplace app uses product feeds to ingest storefront catalogs for multiple stores. Before 2026-07, the app received one product and assumed all variants were global. After 2026-07:
- Behavior: The feed receives product updates when variants change for a specific channel. The incremental sync webhook includes variants added/removed.
- Implementation: No changes required to ingest feed updates. The app’s mapping layer must ensure it doesn’t display unpublished variants for the marketplace publication.
- Benefit: Sellers can now exclude variants from the marketplace without creating separate products.
Real-world example 2 — DTC brand with regional sizing A clothing brand sells internationally but cannot ship size XXL to certain markets. They previously created separate product listings per market or relied on fragile storefront code. After variant-level publishing:
- Behavior: The brand unpublishes the XXL variant on specific market publications.
- Implementation: The brand’s fulfillment integration checks variant publication before enabling local fulfillment options; analytics preserve product continuity.
- Benefit: Reduced catalog duplication, cleaner analytics, fewer merchant errors.
Real-world example 3 — Subscription box with exclusive SKUs An app powering subscription boxes wants to reserve exclusive colorways for subscribers. The app must keep these variants hidden until subscription cycles start.
- Behavior: Variants are created unpublished, scheduled for publish at subscription release dates.
- Implementation: The app uses productVariantBulkCreate with variant.published: false, and schedules publishablePublish calls when release dates occur. It listens to feeds for confirmation and uses the forthcoming variant_publication webhooks when available for robust eventing.
- Benefit: Exclusive SKUs remain hidden to general shoppers while maintaining a single product page.
Testing, monitoring and rollout checklist
Use this checklist to guide a controlled rollout.
Pre-rollout
- Inventory endpoints and flows touching variants.
- Add GraphQL queries for resourcePublicationsv2 and update test fixtures.
- Update creation flows to accept explicit published flags.
- Add tests for both published and unpublished creation flows.
Rollout
- Deploy read-path changes and monitor production logs for errors.
- Add telemetry for publishablePublish/unpublish calls and product feed events.
- Update webhook handlers for incremental product feed events to properly interpret variant additions/removals.
Post-rollout
- Verify merchant-facing reports and analytics show consistent variant lifecycles.
- Test edge-case scenarios: product published with no variants published, product unpublished with variants published (should not display).
- Conduct a merchant support walkthrough showing how to publish/unpublish variants in the admin and how app-controlled publications behave.
Long-term
- Adopt variant_publication webhooks as they arrive for more precise event-driven updates.
- Regularly review usage patterns and optimize batching or bulk operations for large catalogs.
- Keep documentation and developer guides up-to-date for any API changes in subsequent versions.
Common pitfalls and troubleshooting
Developers and merchants will encounter predictable pitfalls. Anticipate and mitigate these issues.
Assuming variant publish implies visibility regardless of product state
- Pitfall: Treating publishablePublish on a variant as sufficient to make it visible.
- Fix: Always check product.active and product publication state. Variant publication is a filter; product-level state remains the gate.
Relying solely on product update webhooks for variant publish events
- Pitfall: Missing real-time publishing events if relying only on product webhooks and not accounting for feeds-specific behavior.
- Fix: For channel apps using feeds, product feed webhooks are sufficient. For apps that do not use feeds, implement polling or prepare to adopt variant_publication webhooks when they arrive.
Race conditions when creating and publishing in quick succession
- Pitfall: Calling publishablePublish immediately after a variant create without an acknowledgement can lead to ordering issues.
- Fix: Wait for the create mutation to complete and verify the variant ID before publishing. Consider using bulk APIs for atomic operations where supported.
Unexpected analytics gaps
- Pitfall: Analytics that tied metrics to product IDs might not reflect variant-level visibility changes.
- Fix: Track variant-level publication events and report them alongside product-level metrics to preserve visibility context.
Misconfigured scopes and permissions
- Pitfall: Mutations or queries fail because the app lacks publication scopes.
- Fix: Validate scopes in OAuth and admin settings; ensure your app requests permissions to read and modify publications for products and variants.
FAQ
Q: Do I need to change my existing publishing workflows? A: Not necessarily. The change is additive and defaults to published for variants, so existing apps that publish at the product level continue to work. Change your workflows if you need variant-level control—read variant publication fields and implement publishablePublish/unpublish for variants when required.
Q: Will a published variant be visible even if the product is unpublished? A: No. Product-level publication takes precedence. A product must be active and published to a channel for any of its variants to render in that channel. Publishing a variant without publishing its parent product does not make it visible.
Q: How do product feeds behave with variant publishing? A: Product feeds will add or remove variants for a feed’s channel and will trigger incremental sync webhooks when variants are published to the feed’s channel. Channel apps that use product feeds should not require changes to work.
Q: What should apps that do not use product feeds do to track variant publication? A: These apps should read the variant’s publication state via ProductVariant.resourcePublicationsv2 and either poll for changes on a schedule or subscribe to product update webhooks as an interim approach. Implement handlers for variant_publication webhooks when Shopify ships them.
Q: Can I create a variant in an unpublished state? A: Yes. productSet and productVariantBulkCreate include a variant.published: false field that lets you create variants unpublished so they aren’t exposed until you publish them explicitly.
Q: Are there new webhooks for variants? A: Shopify will ship variant_publication/create/update/delete webhooks imminently. Until those webhooks are available, product feed updates and product update webhooks provide interim signals for variant additions and removals.
Q: Will this change break my app? A: It is non-breaking. Variants default to published, and product-level behavior is unchanged. However, apps that make assumptions about product-only publication might need to adapt if merchants begin using variant-level publishing.
Q: What are best practices for bulk operations and rate limits? A: Use bulk APIs for large operations such as productVariantBulkCreate and batch publish/unpublish operations. Consolidate publishablePublish calls into multi-ID requests and avoid per-variant API calls when processing large catalogs to reduce rate pressure.
Q: How should merchants and app owners test changes? A: Use sandbox stores with multiple publications (channels) to test variant visibility across channels. Create variants with explicit published flags, perform publish/unpublish operations, and validate storefront and marketplace behavior. Add automated integration tests covering these scenarios.
Q: Where can I get more guidance? A: Consult Shopify’s developer documentation for the product publishing guide and the Admin GraphQL reference for the 2026-07 API. Follow release notes for the variant_publication webhooks as they become available.
Variant-level publishing harmonizes merchant needs with developer workflows. It reduces catalog duplication and brings precision to visibility controls, while preserving existing behavior and integration patterns. App developers and channel owners should start by reading variant publication metadata, update creation flows to allow unpublished variants where required, and prepare to adopt variant_publication webhooks when they appear. With clear migration steps and careful testing, teams can take advantage of the new Publishable ProductVariant to deliver more flexible, accurate, and maintainable commerce experiences.