Product and variant publishing
Publishing controls which products and variants are visible to buyers on a given sales channel, market, or B2B context. The publishing framework is built on catalogs and publications.
Every selling context on a Shopify store has a catalog:
- AppCatalog represents sales channels like the Online Store, Point of Sale, or custom channels.
- MarketCatalog represents international markets such as North America or Europe.
- CompanyLocationCatalog represents B2B company locations.
Each catalog can have an associated publication, which is the group of products and collections visible to buyers in that context. To make a product visible, you publish it to that catalog's publication. To hide it, you unpublish it.
The Publishable interface is implemented by Product, ProductVariant, and Collection, giving you the same publishing controls across all three resource types.
Anchor to RequirementsRequirements
- Your app can make authenticated requests to the GraphQL Admin API.
- Your app has the
read_publicationsandwrite_publicationsaccess scopes. You also needread_productsto query products. - Your store has existing products.
- Your store has at least one active sales channel. Most stores have the Online Store by default.
Anchor to Discovering catalogs and publicationsDiscovering catalogs and publications
Before you can publish products, you need to know what publications exist on the shop. You can discover them in two ways: by querying catalogs, or by querying publications directly.
Anchor to Query publications directlyQuery publications directly
Use the publications query for a flat list of all publications on the shop. This is simpler when you just need publication IDs for mutations.
POST /api/2026-07/graphql.json
GraphQL query
query Publications {
publications(first: 20) {
nodes {
id
autoPublish
supportsFuturePublishing
catalog {
id
title
}
}
}
}JSON response
{
"data": {
"publications": {
"nodes": [
{
"id": "gid://shopify/Publication/123",
"autoPublish": true,
"supportsFuturePublishing": true,
"catalog": {
"id": "gid://shopify/AppCatalog/1",
"title": "Online Store"
}
},
{
"id": "gid://shopify/Publication/456",
"autoPublish": false,
"supportsFuturePublishing": false,
"catalog": {
"id": "gid://shopify/AppCatalog/2",
"title": "Point of Sale"
}
}
]
}
}
}You can filter publications by catalog type using the catalogType argument. For example, publications(first: 20, catalogType: MARKET) returns only publications associated with market catalogs.
You can filter publications by catalog type using the catalogType argument. For example, publications(first: 20, catalogType: MARKET) returns only publications associated with market catalogs.
Anchor to Query catalogsQuery catalogs
Use the catalogs query to discover what selling contexts exist on the shop. The response can include app catalogs, market catalogs, and B2B company location catalogs.
POST /api/2026-07/graphql.json
GraphQL query
query {
catalogs(first: 3) {
nodes {
id
title
status
}
}
}JSON response
{
"data": {
"catalogs": {
"nodes": [
{
"id": "gid://shopify/MarketCatalog/1068177679",
"title": "NA Market",
"status": "ACTIVE"
},
{
"id": "gid://shopify/CompanyLocationCatalog/1068177680",
"title": "B2B Example 1",
"status": "DRAFT"
},
{
"id": "gid://shopify/AppCatalog/1068177681",
"title": "App Catalog Example",
"status": "ARCHIVED"
}
]
}
}
}Anchor to Publishing products to sales channels and catalogsPublishing products to sales channels and catalogs
Use the publishablePublish mutation to publish a product to one or more publications. Pass the product's GID and an array of publication IDs. If the product is already published to a given publication, the mutation succeeds with no change.
POST /api/2026-07/graphql.json
GraphQL mutation
mutation PublishProduct($id: ID!, $input: [PublicationInput!]!) {
publishablePublish(id: $id, input: $input) {
publishable {
... on Product {
id
title
}
availablePublicationsCount {
count
}
resourcePublicationsCount {
count
}
}
userErrors {
field
message
}
}
}Variables
{
"id": "gid://shopify/Product/1",
"input": [
{
"publicationId": "gid://shopify/Publication/123"
},
{
"publicationId": "gid://shopify/Publication/456"
}
]
}JSON response
{
"data": {
"publishablePublish": {
"publishable": {
"id": "gid://shopify/Product/1",
"title": "Classic Snowboard",
"availablePublicationsCount": {
"count": 3
},
"resourcePublicationsCount": {
"count": 3
}
},
"userErrors": []
}
}
}The input field accepts an array, so you can publish to multiple publications in a single mutation call.
Anchor to Unpublish a productUnpublish a product
Use the publishableUnpublish mutation to remove a product from one or more publications. The product isn't deleted. It remains in your store but becomes unavailable to buyers on those channels.
POST /api/2026-07/graphql.json
GraphQL mutation
mutation UnpublishProduct($id: ID!, $input: [PublicationInput!]!) {
publishableUnpublish(id: $id, input: $input) {
publishable {
... on Product {
id
title
}
availablePublicationsCount {
count
}
resourcePublicationsCount {
count
}
}
userErrors {
field
message
}
}
}Variables
{
"id": "gid://shopify/Product/1",
"input": [
{
"publicationId": "gid://shopify/Publication/456"
}
]
}JSON response
{
"data": {
"publishableUnpublish": {
"publishable": {
"id": "gid://shopify/Product/1",
"title": "Classic Snowboard",
"availablePublicationsCount": {
"count": 3
},
"resourcePublicationsCount": {
"count": 2
}
},
"userErrors": []
}
}
}If your app is itself a sales channel, you can use the publishablePublishToCurrentChannel and publishableUnpublishToCurrentChannel convenience mutations to publish resources to your app's own channel without specifying a publication ID. This guide focuses on publishing to any publication using explicit IDs.
If your app is itself a sales channel, you can use the publishablePublishToCurrentChannel and publishableUnpublishToCurrentChannel convenience mutations to publish resources to your app's own channel without specifying a publication ID. This guide focuses on publishing to any publication using explicit IDs.
Anchor to Reading publication stateReading publication state
After publishing or unpublishing products, you can verify their publication state using several fields on the Product object.
Anchor to Check a specific publicationCheck a specific publication
Use publishedOnPublication to check whether a product is published to a specific publication.
POST /api/2026-07/graphql.json
GraphQL query
query ProductPublicationCheck($id: ID!, $publicationId: ID!) {
product(id: $id) {
title
publishedOnPublication(publicationId: $publicationId)
}
}Variables
{
"id": "gid://shopify/Product/1",
"publicationId": "gid://shopify/Publication/123"
}JSON response
{
"data": {
"product": {
"title": "Classic Snowboard",
"publishedOnPublication": true
}
}
}Anchor to List all publications for a productList all publications for a product
Use resourcePublicationsV2 to get a list of all publications a product is published to, along with the publication date.
POST /api/2026-07/graphql.json
GraphQL query
query ProductPublications($id: ID!) {
product(id: $id) {
title
resourcePublicationsV2(first: 20) {
nodes {
publication {
id
}
isPublished
publishDate
}
}
}
}Variables
{
"id": "gid://shopify/Product/1"
}JSON response
{
"data": {
"product": {
"title": "Classic Snowboard",
"resourcePublicationsV2": {
"nodes": [
{
"publication": {
"id": "gid://shopify/Publication/123"
},
"isPublished": true,
"publishDate": "2026-01-15T10:00:00Z"
},
{
"publication": {
"id": "gid://shopify/Publication/456"
},
"isPublished": true,
"publishDate": "2026-01-15T10:00:00Z"
}
]
}
}
}
}Anchor to List publications where a product is not publishedList publications where a product is not published
Use unpublishedPublications to find publications where the product could be published but currently isn't.
POST /api/2026-07/graphql.json
GraphQL query
query ProductUnpublished($id: ID!) {
product(id: $id) {
title
unpublishedPublications(first: 20) {
nodes {
id
}
}
}
}Variables
{
"id": "gid://shopify/Product/1"
}JSON response
{
"data": {
"product": {
"title": "Classic Snowboard",
"unpublishedPublications": {
"nodes": [
{
"id": "gid://shopify/Publication/789"
}
]
}
}
}
}Anchor to Managing publications at scaleManaging publications at scale
The mutations above are resource-centric: you pick a product and manage which publications it appears in. For the inverse pattern, picking a publication and managing which products it contains, use the publicationUpdate mutation.
POST /api/2026-07/graphql.json
GraphQL mutation
mutation UpdatePublication($id: ID!, $input: PublicationUpdateInput!) {
publicationUpdate(id: $id, input: $input) {
publication {
id
}
userErrors {
field
message
}
}
}Variables
{
"id": "gid://shopify/Publication/123",
"input": {
"publishablesToAdd": [
"gid://shopify/Product/1",
"gid://shopify/Product/2"
],
"publishablesToRemove": [
"gid://shopify/Product/3"
]
}
}JSON response
{
"data": {
"publicationUpdate": {
"publication": {
"id": "gid://shopify/Publication/123"
},
"userErrors": []
}
}
}Use publishablePublish when managing a single product's channel presence. Use publicationUpdate when managing a publication's product catalog.
Anchor to Variant-level publishingVariant-level publishing
Variant-level publishing lets you control visibility at the individual variant level. By default, when a product is published to a sales channel or catalog, all of its variants are visible to buyers. With variant-level publishing, you can publish or unpublish specific variants independently.
This is useful for scenarios like:
- Product launches: Prepare new colorways or sizes without exposing them to buyers until you're ready.
- Region-based restrictions: Hide variants from certain markets due to regulatory or shipping constraints.
- Channel-specific catalogs: Show different variant selections on different sales channels.
- Lifecycle management: Retire variants from storefronts without deleting them, preserving historical data and analytics.
Anchor to How it worksHow it works
The ProductVariant object implements the Publishable interface, giving it the same publishing controls that exist for products and collections.
By default, all variants are published on all channels and catalogs where their parent product is published. This ensures apps and merchants can continue their current product creation and publishing flow without implementing variant publishing support.
Anchor to Visibility rulesVisibility rules
A variant is visible to buyers on a given sales channel or catalog when the following are all true:
- The product has an Active status (or Unlisted on supported channels).
- The product is published to that channel or catalog.
- The variant is published to that channel or catalog.
| Product state | Variant state | Visible to buyers |
|---|---|---|
| Published | Published | Yes |
| Published | Unpublished | No |
| Unpublished | Published | No |
| Unpublished | Unpublished | No |
Anchor to Independent stateIndependent state
Variant and product publishing states are independent:
- Publishing or unpublishing a variant doesn't affect the parent product's publication state.
- Publishing or unpublishing a product doesn't change any variant's publication state.
Variant publishing state persists across product publishing changes, so you can configure variant visibility before publishing the product.
Anchor to Query variant publication statusQuery variant publication status
The ProductVariant object includes all fields from the Publishable interface. You can check whether a variant is published to a specific channel, list all of its publications, or count its available publications.
POST /api/2026-07/graphql.json
GraphQL query
query VariantPublicationStatus {
productVariant(id: "gid://shopify/ProductVariant/123") {
title
publishedOnPublication(
publicationId: "gid://shopify/Publication/456"
)
resourcePublicationsCount {
count
}
}
}JSON response
{
"data": {
"productVariant": {
"title": "Red / Small",
"publishedOnPublication": true,
"resourcePublicationsCount": {
"count": 3
}
}
}
}Use resourcePublicationsV2 and unpublishedPublications to get the full picture of where a variant is and isn't published:
POST /api/2026-07/graphql.json
GraphQL query
query VariantPublications {
productVariant(id: "gid://shopify/ProductVariant/123") {
title
resourcePublicationsV2(first: 10) {
nodes {
publication {
id
}
isPublished
publishDate
}
}
unpublishedPublications(first: 10) {
nodes {
id
}
}
}
}JSON response
{
"data": {
"productVariant": {
"title": "Red / Small",
"resourcePublicationsV2": {
"nodes": [
{
"publication": {
"id": "gid://shopify/Publication/123"
},
"isPublished": true,
"publishDate": "2026-01-15T10:00:00Z"
}
]
},
"unpublishedPublications": {
"nodes": [
{
"id": "gid://shopify/Publication/789"
}
]
}
}
}
}Anchor to Publish a variant to a sales channelPublish a variant to a sales channel
Use the publishablePublish mutation with a ProductVariant GID to publish a variant to one or more publications. If the variant is already published to that publication, the mutation succeeds with no change.
POST /api/2026-07/graphql.json
GraphQL mutation
mutation PublishVariant($id: ID!, $input: [PublicationInput!]!) {
publishablePublish(id: $id, input: $input) {
publishable {
... on ProductVariant {
id
title
}
}
userErrors {
field
message
}
}
}Variables
{
"id": "gid://shopify/ProductVariant/123",
"input": [
{
"publicationId": "gid://shopify/Publication/456"
}
]
}JSON response
{
"data": {
"publishablePublish": {
"publishable": {
"id": "gid://shopify/ProductVariant/123",
"title": "Red / Small"
},
"userErrors": []
}
}
}Anchor to Unpublish a variant from a sales channelUnpublish a variant from a sales channel
Use the publishableUnpublish mutation to remove a variant from a specific publication. The variant data isn't deleted. You can republish the variant at any time.
POST /api/2026-07/graphql.json
GraphQL mutation
mutation UnpublishVariant($id: ID!, $input: [PublicationInput!]!) {
publishableUnpublish(id: $id, input: $input) {
publishable {
... on ProductVariant {
id
title
}
}
userErrors {
field
message
}
}
}Variables
{
"id": "gid://shopify/ProductVariant/123",
"input": [
{
"publicationId": "gid://shopify/Publication/456"
}
]
}JSON response
{
"data": {
"publishableUnpublish": {
"publishable": {
"id": "gid://shopify/ProductVariant/123",
"title": "Red / Small"
},
"userErrors": []
}
}
}Anchor to Create a variant in an unpublished stateCreate a variant in an unpublished state
You can create a variant that's unpublished from all publications by setting published to false. This prevents any buyer exposure before you explicitly publish the variant.
Use the published field on the variant input when calling productVariantsBulkCreate or productSet.
POST /api/2026-07/graphql.json
GraphQL mutation
mutation CreateUnpublishedVariant(
$productId: ID!
$variants: [ProductVariantsBulkInput!]!
) {
productVariantsBulkCreate(
productId: $productId
variants: $variants
) {
productVariants {
id
title
}
userErrors {
field
message
}
}
}Variables
{
"productId": "gid://shopify/Product/1",
"variants": [
{
"price": "29.99",
"optionValues": [
{
"optionName": "Color",
"name": "Midnight Blue"
}
],
"published": false
}
]
}JSON response
{
"data": {
"productVariantsBulkCreate": {
"productVariants": [
{
"id": "gid://shopify/ProductVariant/999",
"title": "Midnight Blue"
}
],
"userErrors": []
}
}
}After creating an unpublished variant, you can selectively publish it to specific channels using publishablePublish.
If you don't set published, or set it to true, the variant is created with the default state of published to all channels and catalogs where the parent product is published.
If you don't set published, or set it to true, the variant is created with the default state of published to all channels and catalogs where the parent product is published.
Anchor to Other publishable resourcesOther publishable resources
Collection also implements the Publishable interface. The same publishablePublish, publishableUnpublish, and publicationUpdate mutations shown in this guide work with Collection GIDs to control which sales channels and catalogs a collection is visible in.
Anchor to Next stepsNext steps
- Learn about scheduled product publishing
- Explore the
Publishableinterface reference - Explore the
publishablePublishmutation reference - Explore the
publishableUnpublishmutation reference - Explore the
publicationUpdatemutation reference - Learn about catalogs for different markets
- Learn about building sales channels