Setting Up Your App
Build the Shopify sales channel app that powers publication-scoped catalog sync: app creation, the channel_config extension, scopes, deploy/release, and Violet setup.
This page is for channel partners building the Shopify app that will act as their sales channel. It assumes the concepts on Sales Channel Publishing on Shopify.
This guide walks you through creating a Shopify app that installs on a single store and registers as a native sales channel, so a merchant can publish products to your channel and only those products sync to Violet. You (the developer/partner) own the Shopify app; Violet integrates with it.
This document ends where Enablement & Rollout begins: once your app is built, deployed, and released, that page covers configuring Violet and onboarding merchants.
Overview
Publication-scoped catalog sync requires your Shopify app to be a genuine sales channel app, one that owns a channel on the merchant's store. That is what produces the checkbox merchants tick on each product. An ordinary app without a channel configuration cannot do this; Shopify rejects channel creation for it.
A sales channel is declared by deploying a channel_config extension. That's an app-level property, not something that requires a public App Store listing.
Deploying the channel_config extension is irreversible. It permanently declares the app a sales channel. Always build and test against a Shopify development store first, and confirm you are working against the intended app before you deploy.
Building it is a sequence of steps:
Install the Shopify CLI.
Create the app in the Dev Dashboard and link it to a local project.
Add a
channel_configextension and define your channel specification.Set access scopes.
Deploy and release the app version.
Select custom distribution and install on the merchant's store.
Configure the corresponding Violet app to match.
Before you start
Prerequisites
A Shopify Partner account and access to the Dev Dashboard (dev.shopify.com/dashboard). This is the same Partner account described in the general Prerequisites.
Node.js 22.12 or higher, a Node package manager (npm, Yarn 1.x, or pnpm), and Git 2.28 or higher. These are prerequisites for the Shopify CLI.
The Shopify CLI installed (see Step 1).
The
myshopify.comdomain of the store this channel will run on.
Step 1: Install the Shopify CLI
First confirm your Node.js version meets the requirement:
If Node is missing or too old, install the latest LTS from nodejs.org (or via a version manager like nvm) before continuing.
Install the CLI globally using whichever package manager you use:
On macOS you can instead use Homebrew, which also pulls in a compatible Node.js:
Verify the install:
Step 2: Create the app in the Dev Dashboard
Go to dev.shopify.com/dashboard and create a new app.
Give it a name.
Open the app and copy its Client ID; you'll need it in the next step.
Step 3: Link the app to your local project
From an empty project directory in your terminal:
This logs you in and writes a shopify.app.toml into the folder, connecting the directory to your Dev Dashboard app.
Step 4: Add a package.json
The CLI needs a package.json at the project root to treat the folder as an app and hold extensions. Create one:
Then install:
Step 5: Generate the channel config extension
This creates:
Step 6: Define your channel specification
Delete the three example-* spec files (leave the icons/ folder). Then create one specification file describing your channel, named for your channel (e.g. extensions/channel-config/specifications/your-channel.toml). Use your own brand name for handle and label. The label is what merchants see in the Shopify admin, and the handle is the specification handle Violet uses when it creates the channel on the merchant's store.
Field notes:
handleis the specification handle. Note the exact spelling: Violet must send the same value when it creates the channel, and the two must match exactly.merchantOfRecord: set"channel"if you are the merchant of record,"merchant"if the Shopify store is.expectsOnlineStoreParity: keepfalsefor marketplace-style channels. If you settrue, channel creation will fail unless the store has a market with a valid web presence covering your countries.countries: one entry per country, with ISO country/language/currency codes. Each country generates its own product feed.
Also update the extension's own metadata in extensions/channel-config/shopify.extension.toml:
How the specification handle is matched
Violet sends a specification handle when it creates the channel on a merchant's store, and it must match the handle in your deployed spec exactly.
If you set
specification_handleon the Violet app configuration, that value is sent verbatim.If you leave it unset, Violet derives it from the Violet app's name by lowercasing it and replacing runs of whitespace with hyphens. An app named
Violet Marketplaceproducesviolet-marketplace.
Set specification_handle explicitly whenever your deployed handle doesn't follow that convention. A mismatch is the most common setup failure and surfaces as a Channel specification not found error during provisioning, which is non-fatal: affected merchants silently stay on full-catalog syncing.
Step 7: Set access scopes
Open shopify.app.toml and make sure the scopes line includes these, at minimum:
Beyond the product and order scopes a standard integration already uses (see the 26 scopes in the general App Setup guide), a sales channel app needs the channel- and publication-specific scopes below.
read_channels, write_channels
Create and manage the channel on the merchant's store
Required for a sales channel app
read_publications
Identifies the publication attached to your channel, the list of products the merchant has published to you
Required. Without it, provisioning cannot complete and every merchant silently stays on full-catalog syncing
write_publications
Sets the channel's auto-publish behavior for products created after setup
Only if auto-publish is being configured
read_product_listings
Reads the published product listings for the channel
Required for a sales channel app
read_publications is not included in the generalized product scopes. An app requesting only generalized scopes will not receive it. It must be declared explicitly, and it is the easiest prerequisite to miss.
Changing scopes means an existing app will be prompted to re-grant permissions the next time it's installed or opened. Select everything you need up front.
Step 8: Deploy and release the app version
This bundles the config and the extension into a new app version. When prompted, accept the release.
The extension must be both deployed and released. A deployed-but-unreleased version behaves exactly like no extension at all: channel creation fails, and merchants continue on full-catalog syncing with no error surfaced to them. If you deploy without releasing (answering "no", or running non-interactively without --force), the store keeps running the previous version and your new specification won't exist as far as the API is concerned.
To release explicitly if needed:
Verify in the Dev Dashboard → your app → Versions that the active/released version's channel-config extension lists your real spec handle (e.g. your-channel), not the example-* handles.
Step 9: Set custom distribution and install
In the Partner Dashboard → App distribution, select the app → Choose distribution → Custom distribution. This choice is permanent.
Enter the store's
myshopify.comdomain. To lock it to one store, uncheck "Allow multi-store installs for one Plus organization."Click Generate link.
Pre-register the merchant in the Violet Channel Dashboard and complete installation.
This is the same custom-distribution and pre-registration flow used for every Shopify merchant. See Shopify App Setup and Pre-Registration Process for the detailed walkthrough and the Install Link.
After installing, the app appears under the store's Settings → Apps and sales channels and in the Sales channels list.
Step 10: The channel connection (handled by Violet)
Being listed as a sales channel is not enough for products to be publishable to it. A channel only appears in a product's Manage publishing dialog after a channel connection exists, which creates the publication and product feeds.
For reference, this is the Shopify mutation Violet issues against the store's GraphQL Admin API. The specificationHandle must exactly match the handle in your deployed, released spec:
On success, the channel has a publication, appears in the product Manage-publishing dialog, and product feeds begin syncing. From that point the merchant can immediately choose which products are published to your channel.
Configure the Violet app
Set the following on your Violet app configuration so Violet provisions the channel for connecting merchants.
sales_channel_behavior.enabled
Turns on channel provisioning for merchants connecting to this app
sales_channel_behavior.specification_handle
The handle from your deployed extension. Optional; see Step 6 for the derivation rule when omitted
sales_channel_behavior.channel_name
Display name merchants see in their Shopify admin. Optional; defaults to the Violet app name
Verify the setup
On a Shopify development store:
Connect the store to your channel.
Confirm the channel appears in the store's admin under Sales channels, named as you expect.
Open any product and confirm your channel appears in the Sales channels and apps section.
Publish a product and confirm it reaches your Violet catalog.
Unpublish it and confirm it is withdrawn.
If step 2 fails, work through The channel doesn't appear in the merchant's Shopify admin in the troubleshooting guide.
Converting an existing (legacy) app
For legacy merchants you can link their existing app and convert it to a sales channel app:
then follow the extension, scope, and deploy/release steps above. Converted merchants will need to be pre-registered again and re-install the app to accept the new scopes and inherit the new configuration. This is the same re-authorization requirement described in Enablement & Rollout.
Troubleshooting the build
shopify app generate extension → "doesn't have a package.json". config link didn't scaffold a project. Add the package.json from Step 4, run npm install, and retry.
For merchant-facing and provisioning issues, see Troubleshooting & FAQ.
Last updated
Was this helpful?