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
titlestringCollection display name.
"title": namehandlestringURL slug. Auto-derived from title if omitted.
"handle": $lowercase(url_key)descriptionHtmlstringCollection description with HTML.
"descriptionHtml": descriptionsortOrderstringHow 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"templateSuffixstringCustom 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_srcstringURL of the collection’s cover image. Setting this is what triggers the image being created.
"image_src": image_urlimage_altstringAlt text for the cover image.
"image_alt": image_alt ? image_alt : nameProducts
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_idsYou 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_titlestringmeta_descriptionstringMenu hierarchy (auto-metafields)
Source platforms with category trees often need this preserved. The staging model auto-converts these to custom metafields.
include_in_menubooleanWhether 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_rootbooleanWhether this category was a top-level / root menu entry. Becomes a
custom.is_menu_root boolean metafield.
parent_idstringSource-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
}Membership-on-product (the recommended pattern)
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
collectionsarray AND the collection’sproductsarray also includes that product, the second load wins. Avoid the conflict by picking one direction. image_srcwithoutimage_altstill loads — the alt is just empty. Set it from the source name as a sensible default.sortOrdervalues 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 (
Newsandnews), sethandleexplicitly 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.