Skip to Content

Collection mapping

StagingCollection is a flat shape — title, image, optional product list, and a few menu hierarchy hints that get stored as metafields.

The staging model only handles manual collections. Smart collections (rule-based) need to be configured in Shopify admin post-migration today.

Quick reference — minimum loadable collection

{ "original_id": category_id, "title": name, "handle": $lowercase(url_key) }

Identity & display

titlestring

Collection display name.

"title": name
handlestring

URL slug. Auto-derived from title if omitted.

"handle": $lowercase(url_key)
descriptionHtmlstring

Collection description with HTML.

"descriptionHtml": description
sortOrderstring

How products are ordered within the collection. Common values: MANUAL, BEST_SELLING, ALPHA_ASC, ALPHA_DESC, PRICE_ASC, PRICE_DESC, CREATED_DESC. Defaults to Shopify’s default if omitted.

"sortOrder": "MANUAL"
templateSuffixstring

Custom theme template suffix. Use only if the merchant has a non-default collection template.

Image

Collection cover image. Two flat fields — different shape from product images.

image_srcstring

URL of the collection’s cover image. Setting this is what triggers the image being created.

"image_src": image_url
image_altstring

Alt text for the cover image.

"image_alt": image_alt ? image_alt : name

Products

The product list lives on the collection or on each product — pick one.

productsstring[]

Array of source-platform product IDs to include in the collection. Graftport resolves these to Shopify GIDs at load time using the product migration’s results.

"products": product_ids

You don’t have to populate products here — alternatively, set collections: [<this collection's original_id>] on the product mapping and the membership goes the other direction. Pick one approach per migration; mixing is confusing.

SEO

meta_titlestring
meta_descriptionstring

Menu hierarchy (auto-metafields)

Source platforms with category trees often need this preserved. The staging model auto-converts these to custom metafields.

include_in_menuboolean

Whether the source category was visible in the storefront menu. Becomes a custom.include_in_menu boolean metafield. Useful for post-migration menu rebuilding.

is_menu_rootboolean

Whether this category was a top-level / root menu entry. Becomes a custom.is_menu_root boolean metafield.

parent_idstring

Source-side parent category ID. Useful for reconstructing the tree post-migration. Stored via dict_metafields if you set it.

childrenstring[]

Source-side child category IDs.

Patterns

Magento category → Shopify collection

{ "original_id": entity_id, "title": name, "handle": url_key, "descriptionHtml": description, "image_src": image, "image_alt": name, "include_in_menu": include_in_menu = "1", "is_menu_root": level = 2, "parent_id": parent_id, "meta_title": meta_title, "meta_description": meta_description }

Membership-on-collection (push the product list explicitly)

{ "original_id": entity_id, "title": name, "handle": $lowercase(name), "products": products.product_id }

In the product mapping, list each product’s collection memberships:

{ "original_id": entity_id, "title": name, "collections": $append(category_ids, ["all-products"]), }

Then in the collection mapping, just declare the collection itself — no need to list products:

{ "original_id": entity_id, "title": name, "handle": $lowercase(name) }

Hierarchical category names

If the merchant wants the path encoded in the title:

{ "original_id": entity_id, "title": $join($append(parent_path, [name]), " / "), "handle": $join(parent_path & [name], "-") ~> $lowercase }

Gotchas

Smart collections are out of scope today. The staging model doesn’t emit Shopify’s ruleSet — every loaded collection is manual. If the merchant relies on smart collections, recreate those in Shopify admin after the migration and load only the manual ones here.

  • Membership conflict. If a product references a collection in its collections array AND the collection’s products array also includes that product, the second load wins. Avoid the conflict by picking one direction.
  • image_src without image_alt still loads — the alt is just empty. Set it from the source name as a sensible default.
  • sortOrder values are case-sensitive. Shopify accepts the exact uppercase enum values listed above; "manual" (lowercase) fails.
  • Handle collisions. Two collections with the same auto-derived handle silently overwrite. If two source categories have similar names (News and news), set handle explicitly with a disambiguating suffix.
  • Menu hierarchy isn’t a navigation menu — it’s metadata you store via metafields so a post-migration script (or theme code) can rebuild the menu. Shopify’s actual storefront menu is a separate resource not covered here.
Last updated on