Skip to main content
Version: 3.x

Channels

Introduction

Since version 3.0, Saleor has supported multiple sales channels. This feature allows the shop owner to configure many aspects of the store depending on the channel used.

  • Your store needs at least one channel to display products
  • You can add as many channels as you need
  • Each channel has precisely one currency
  • Channels can be deactivated for customers

Popular use cases:

  • If you sell internationally, you can use separate channels for different currencies or regions
  • If you want to have different prices in the custom mobile app and website, you can set up website-channel and mobile-channel

There are many models you can customize per channel. The details of which fields you can define on a per-channel basis are described in the ChannelListing models:

Permissions

Listing channels is allowed only for users with the active isStaff flag.

You need the MANAGE_CHANNELS permission to create, edit, and remove channels. Changing ChannelListing does not require additional permissions. For example, changing Product availability requires only MANAGE_PRODUCTS permission.

Getting channel details

Use channel query to get channel details.

Available fields:

  • id: Channel object ID
  • name: Channel name
  • isActive: Flag signalling that the channel is available for shop customers.
  • slug: When using channel-dependant queries, the slug is used to select the right one (for example, when requesting Product details)
  • currencyCode: Currency code used by the channel.
  • defaultCountry: Default country for the channel. The default country will be used in checkout to determine the stock quantities or calculate taxes when the country was not explicitly provided, either as a query parameter or through a shipping address.
  • hasOrders: Returns true when there are already created orders using that channel. If that's the only channel using this currency, you won't be able to remove it.
  • warehouses: Warehouses that are available in the given channel.
  • stockSettings: contains all stock-related settings, f.e. the allocation strategy for the channel.

Request:

query {
channel(id: "Q2hhbm5lbDo3") {
id
isActive
name
slug
defaultCountry {
code
country
}
hasOrders
warehouses {
slug
}
stockSettings {
allocationStrategy
}
}
}

Response:

{
"data": {
"channel": {
"id": "Q2hhbm5lbDo0MzM=",
"isActive": false,
"name": "Mobile",
"slug": "mobile",
"currencyCode": "USD",
"defaultCountry": {
"code": "US",
"country": "United States of America"
},
"hasOrders": false
"warehouses": [
{
"slug": "oceania"
},
{
"slug": "europe"
}
]
"stockSettings": {
"allocationStrategy": "PRIORITIZE_HIGH_STOCK"
}
}
}

Creating a new channel

You can create a new channel using channelCreate mutation. During checkout creation, you can define the allocation strategy. Right now the two possible options are available: PRIORITIZE_HIGH_STOCK and PRIORITIZE_SORTING_ORDER, the PRIORITIZE_SORTING_ORDER strategy is used as default. You can read more about the allocation strategies here.

Request:

mutation {
channelCreate(
input: {
currencyCode: "USD"
defaultCountry: US
name: "Mobile"
slug: "mobile"
stockSettings: { allocationStrategy: PRIORITIZE_HIGH_STOCK }
}
) {
channel {
id
isActive
name
slug
currencyCode
defaultCountry {
code
country
}
stockSettings {
allocationStrategy
}
}
errors {
code
field
message
}
}
}

Response:

{
"data": {
"channelCreate": {
"channel": {
"id": "Q2hhbm5lbDo0MzM=",
"isActive": false,
"name": "Mobile",
"slug": "mobile",
"currencyCode": "USD",
"defaultCountry": {
"code": "US",
"country": "United States of America"
},
"stockSettings": {
"allocationStrategy": "PRIORITIZE_HIGH_STOCK"
}
},
"errors": []
}
}
}

Channel list

Because some of the channels may be considered non-public (for example - a channel for business partners), non-staff users cannot use the channels query.

Request:

query {
channels {
name
}
}

Response:

{
"data": {
"channels": [
{
"name": "Mobile"
},
{
"name": "Website"
}
]
}
}

Activate / Deactivate channel

If you want to make the channel unavailable for customers, you can change it's status to deactivated using channelDeactivate mutation:

mutation {
channelDeactivate(id: "Q2hhbm5lbDoxMQ==") {
channel {
name
isActive
}
errors {
message
}
}
}

Response:

{
"data": {
"channelDeactivate": {
"channel": {
"name": "Facebook",
"isActive": false
},
"channelErrors": []
}
}
}

And to reverse the previous operation use the channelActivate mutation:

mutation {
channelActivate(id: "Q2hhbm5lbDoxMQ==") {
channel {
name
isActive
}
errors {
message
}
}
}

Response:

{
"data": {
"channelDeactivate": {
"channel": {
"name": "Facebook",
"isActive": true
},
"channelErrors": []
}
}
}

Reorder warehouses within channels

The warehouses assigned to the channel can be sorted. The provided order defines the warehouses' order used in PRIORITIZE_SORTING_ORDER allocation strategy. The sort_order in moves input represents the new relative position of the item. So when 1 is provided, the item will be moved one position forward; when -1 - one position backward.

Let's assume that we have a channel with three channels in the following order.

{
"data": {
"channel": {
"id": "Q2hhbm5lbDox",
"warehouses": [
{
"id": "V2FyZWhvdXNlOjU1NTZiOWI0LTc1ZTItNGI3YS1hZWM1LTQxOTY4NDA2OGE4OA==",
"slug": "europe"
},
{
"id": "V2FyZWhvdXNlOjQwZWY1MTQwLWQ5OTYtNDVlNy04NzUzLTlkZThkMTdhMjg1Yw==",
"slug": "oceania"
},
{
"id": "V2FyZWhvdXNlOjY4M2FkMzZhLTRmNjktNDI2ZS1iYzUyLTMyZGJiZTQ2NjUyZA==",
"slug": "americas"
}
]
}
}
}

To move the americas warehouse to the first place and the europe warehouse to third, we can run the following mutation.

mutation {
channelReorderWarehouses(
channelId: "Q2hhbm5lbDox"
moves: [
{
# move for `americas` warehouse
id: "V2FyZWhvdXNlOjY4M2FkMzZhLTRmNjktNDI2ZS1iYzUyLTMyZGJiZTQ2NjUyZA=="
sortOrder: -2
}
{
# move for `europe` warehouse
id: "V2FyZWhvdXNlOjU1NTZiOWI0LTc1ZTItNGI3YS1hZWM1LTQxOTY4NDA2OGE4OA=="
sortOrder: 1
}
]
) {
channel {
id
warehouses {
id
slug
}
}
errors {
field
code
message
warehouses
}
}
}

And as a response, we get:

{
"data": {
"channelReorderWarehouses": {
"channel": {
"id": "Q2hhbm5lbDox",
"warehouses": [
{
"id": "V2FyZWhvdXNlOjY4M2FkMzZhLTRmNjktNDI2ZS1iYzUyLTMyZGJiZTQ2NjUyZA==",
"slug": "americas"
},
{
"id": "V2FyZWhvdXNlOjQwZWY1MTQwLWQ5OTYtNDVlNy04NzUzLTlkZThkMTdhMjg1Yw==",
"slug": "oceania"
},
{
"id": "V2FyZWhvdXNlOjU1NTZiOWI0LTc1ZTItNGI3YS1hZWM1LTQxOTY4NDA2OGE4OA==",
"slug": "europe"
}
]
},
"errors": []
}
}
}

Removing a channel

Channels can be removed only when:

  • There are no orders created in them.
  • If there are orders created, targetChannel is required. Its currency has to be the same as the channel you are about to delete. All orders will be moved to targetChannel.

channelDelete mutation takes input:

  • id: ID of the Channel that will be deleted
  • targetChannel: all existing orders will be moved into this channel
channelDelete(
id: ID!
input: ChannelDeleteInput
): ChannelDelete

input ChannelDeleteInput {
targetChannel: ID!
}

Errors

type ChannelError {
field: String
message: String
code: ChannelErrorCode!
}

enum ChannelErrorCode {
ALREADY_EXISTS
GRAPHQL_ERROR
INVALID
NOT_FOUND
REQUIRED
UNIQUE
CHANNEL_TARGET_ID_MUST_BE_DIFFERENT
CHANNELS_CURRENCY_MUST_BE_THE_SAME
}

ChannelErrorCode values:

  • ALREADY_EXISTS: Object already exists in the database
  • GRAPHQL_ERROR: Wrong query
  • INVALID: Invalid data provided
  • NOT_FOUND: Could not found object
  • REQUIRED: Missing required fields
  • UNIQUE: Provided value for field needs to be unique
  • CHANNEL_TARGET_ID_MUST_BE_DIFFERENT: Cannot move orders into the channel you want to delete
  • CHANNELS_CURRENCY_MUST_BE_THE_SAME: Target channel has to have the same currency