App development

Migrating to Shopify's flexible collections: a field-by-field guide for app developers

The 2026-07 collections model is non-breaking, but if your app reads or writes collections you still need to move. Here's what maps to what, the 404 gotcha with old API versions, and what stays the same.

Bas Lefeber

Founder, learnshopify.dev · July 8, 2026 · 5 min read

Don't just read it, build it liveThis feature is a hands-on lesson in a live storefront, right in your browser. Free, nothing to install.

If you build apps on Shopify, the new source-based collections model lands with a reassuring headline: it is non-breaking. Your existing calls keep working, nothing switches off overnight. That is true, and it is also the sentence that gets teams into trouble, because "non-breaking" is not the same as "nothing to do." If your app reads, writes, or syncs collections, there is a concrete migration in front of you, and one gotcha that will silently corrupt a merchant's catalog view if you ignore it.

This is the practical companion to the explainer: a field-by-field map from the legacy custom-and-smart shape to the 2026-07 source-based shape, the auth-version trap, and the list of things you genuinely do not need to touch.

TL;DR for the busy

Deprecated fields (ruleSet, collectionAddProducts, collectionCreate(input:)) still work in 2026-07, so nothing breaks today. But collections that use new capabilities cannot be seen by pre-2026-07 versions and may return 404, so bump your app to 2026-07 first. Then move writes from the input: argument to the new collection: argument with sources, and move rule logic from ruleSet to a conditions source. Webhooks, collection.products, and reordering are unchanged.

The legacy shape on the left, the 2026-07 source-based shape on the right. Same intent, new container.

Step 0: bump to 2026-07 before anything else

This is the step that matters most and the one most likely to be skipped, so it goes first. A collection that uses any of the new capabilities (multiple sources, exclusions, sub-collection references, or variant targeting) cannot be represented in an older API version. Per Shopify's guidance, such collections are filtered out of collections query results and can return 404 Not Found when fetched directly by a pre-2026-07 request.

Read that failure mode carefully, because it is quiet. Your app does not throw a loud deprecation error. It just stops seeing a growing subset of the merchant's collections as they adopt the new features, and any sync that assumes it has the full list will drift out of truth. If your app does nothing else in this migration, move its Admin API calls to 2026-07 so it can see the whole catalog.

Test with a real new-model collection

Create a collection that combines a rule with a manual exclusion in a 2026-07 context, then hit it from your app's current API version. Watch it 404 or vanish from the list. That five-minute test is the whole reason to prioritize the version bump, and it is far cheaper to see in staging than in a support ticket.

The field-by-field map

Most of the migration is mechanical once you see the correspondence. The legacy concepts did not disappear, they moved into the source model. Here is how the pieces line up, per the migration guide.

Legacy (pre-2026-07)New (2026-07)What it means
Collection.ruleSetCollection.sourcesThe rules now live inside a conditions source in the sources array, not a single ruleSet on the collection.
disjunctive: true / falsematchType: ANY / ALL"Match any rule" versus "match all rules" is now an explicit match type on the source's inclusion.
CollectionInput.productsinclusion.selectionsManual picks become selections on a source, and each selection can carry variant IDs, not just a product ID.
collectionAddProducts / collectionRemoveProductsselections added / removed via collectionUpdateManual add and remove fold into the update mutation as changes to a source's selections.
collectionCreate(input:)collectionCreate(collection:)A new argument carries the source-based shape. The old input argument is deprecated but still accepted.
(not possible)exclusion on a sourceRule-based collections can now subtract explicit products or variants: the exception case that needed an app before.
Legacy shape to 2026-07 source-based shape. Names are per the current docs and still settling; confirm against the live migration guide.

The shape of a write changes accordingly. Instead of handing Shopify a ruleSet and a product list on one input object, you describe the collection as a set of sources.

Before and after, conceptually (illustrative)
// BEFORE (legacy smart collection)collectionCreate(input: {  title: "Summer sale"  ruleSet: {    appliedDisjunctively: false        // = match ALL    rules: [{ column: TAG, relation: EQUALS, condition: "summer" }]  }}) // AFTER (2026-07 source-based)collectionCreate(collection: {  title: "Summer sale"  sources: [{    conditions: {      inclusion: {        matchType: ALL        conditions: [{ /* tag = "summer", price < 50, ... */ }]        selections: [{ /* hand-forced products/variants */ }]      }      exclusion: { selections: [{ /* pulled-out products */ }] }    }  }]})

Every name in that snippet is versioned

The argument names, enum values (matchType: ALL), and nesting above follow Shopify's current docs, but the 2026-07 model is new and the exact input shapes are still settling. Do not copy this into production. Generate against the live schema and read the Migrate to flexible collections guide for the authoritative field list.

New mutations you'll reach for

Beyond the reshaped collectionCreate and collectionUpdate, the docs introduce dedicated mutations for managing conditions sources directly, including the shareable, app-owned kind: collectionConditionsSourceCreate, collectionConditionsSourceUpdate, and collectionConditionsSourceDelete. If your app publishes a source that merchants opt into (say, a "trending now" feed), those are the mutations that own its lifecycle independently of any one collection.

What you do NOT have to change

Just as important as the migration list is the list of things that stay put. Per the docs and the developer-preview thread, these are unchanged:

  • Reading the resulting products. collection.products and pagination over it work exactly as before. If all your app does is read a collection's product IDs, that code does not change (but still bump the API version so you can see new-model collections at all).
  • Webhooks. collections/create, collections/update, and collections/delete fire with the same behavior.
  • Manual sort order. collectionReorderProducts still works. Note the one nuance from the thread: a multi-source collection shares a single sort order across all its sources rather than sorting per-source.

2026-07

Bump to this version

or new collections 404

Non-breaking

Deprecated fields still work

no forced cutover date announced

3 things

Stay unchanged

products read, webhooks, reorder

A sane migration order

  1. Bump the API version to 2026-07 everywhere your app touches collections, and confirm you can read a new-model collection without a 404.
  2. Audit your writes. Find every collectionCreate/collectionUpdate that passes input: or sets ruleSet, and plan the move to the collection: argument with sources.
  3. Map your rule logic. Translate appliedDisjunctively to a matchType and your rule columns to conditions on a conditions source.
  4. Adopt exclusions and variants where they help. Once you are on the new shape, the exception and variant-targeting cases you used to fake with re-syncing become native. Delete the babysitting code.
  5. Re-test reads and webhooks against collections that use the new features, not just legacy ones.

Learn this properly · free lesson

Where should this data live: tag, metafield, or metaobject?

The judgment underneath this migration: where each piece of merchant data actually belongs. Practice it against a live store. Free, in your browser.

Try this lesson — free

The migration itself is small. The discipline is remembering that "non-breaking" describes the old path staying open, not the new one being optional. The moment a merchant builds a collection with an exclusion or a variant target, an app still on the old version goes partially blind, and it does so without a single error in the logs. Bump the version first, and the rest is mechanical.


Sources: Shopify Dev, Migrate to flexible collections and Use the new collections model; the 2026-07 changelog entry; and the developer-preview community thread.

Frequently asked questions

Do I have to migrate my app to the new Shopify collections model?

If your app only reads a collection's product list, your read code does not change, but you should still bump to the 2026-07 Admin API. Collections that use new capabilities (multiple sources, exclusions, sub-collections, or variant targeting) are filtered out of older API versions and can return 404, so an app on an older version silently stops seeing part of the catalog. If your app writes collections or manages rules, plan the field migration to the source-based shape.

What replaces ruleSet in the 2026-07 collections API?

The old ruleSet on the collection moves into a conditions source inside the new sources array. The appliedDisjunctively boolean becomes an explicit matchType (ANY or ALL) on the source's inclusion, and manual products become selections that can also carry variant IDs. The legacy ruleSet field is deprecated but still works in 2026-07.

Will my old collection API calls break?

No. The migration is non-breaking: deprecated fields such as ruleSet, collectionAddProducts, and the collectionCreate(input:) argument still work in 2026-07. Webhooks, reading collection.products, and collectionReorderProducts are unchanged. The only hard requirement is upgrading your API version so your app can see collections that use the new features.

What is the 404 issue with new collections and old API versions?

A collection that uses new-model capabilities cannot be represented in a pre-2026-07 API version. Shopify filters those collections out of list queries and can return 404 Not Found when they are fetched directly by an older request. It fails quietly, with no deprecation error, so any app that reads or syncs collections should move to 2026-07 to avoid drifting out of sync with the merchant's real catalog.

Start free

Ready to become a Shopify developer?

You just read how it works. Now write it yourself: real tickets from a live store, in an editor where the storefront updates as you type. Module 1 is free, no card.

Start your first lesson

Free · No credit card · Your first win in minutes

App developmentCollectionsAdmin APIMigration

About the author

Bas Lefeber, Founder, learnshopify.dev

Bas builds learnshopify.dev, where developers learn production-grade Shopify theme development against a live storefront. He writes about Liquid, theme architecture, and the parts of the job that still matter now that AI writes the code.

Keep going in the curriculum