Skip to main content

Manage categories

Categories are the branches of your product taxonomy — a nested tree that groups products (Apparel → Shirts → T-Shirts) and drives which attributes apply to a product through the attribute groups you attach to each branch. This guide covers building and maintaining that tree: creating branches, renaming and moving them, deleting or archiving them, reassigning the products underneath, and running bulk or import/export operations.

For the model behind the tree — how is_leaf, path, level and the primary-category rule work — see How product taxonomy works. To assign categories to an individual product, see Set a product's categories & attributes.

Before you begin

Managing categories is permissioned separately from viewing products. You need the relevant capability for each action:

ActionPermission
Create a categorycategories.create
Rename / re-parent / assign attributescategories.update
Delete (single or bulk)categories.delete
Archive / restore (single or bulk)categories.archive
Import categoriescategories.import

Reading the tree requires read access to the Products area. See the Product permissions reference for the full list.

How the tree is displayed

SKU exposes the category tree three ways, and you'll see each in a different place:

  • One level at a time (the manage/browser view) — lists the direct children of a given parent, each row showing its product count, attribute-group count and attribute count. This is what you drill through when building the tree or assigning categories to a product.
  • The full nested tree — the complete parent → child structure in one payload, with a subcategories count rolled up at every branch. Used by tree pickers.
  • The flat settings list — a paginated, searchable, sortable table (sort by name, level, created/updated date) used in Settings → Categories. It defaults to 10 per page; a lookup caller can request all rows on one page.

A branch is either a leaf (is_leaf = true, can hold products directly) or a container (has children, holds no products of its own). SKU maintains this flag for you — you never set it by hand.

Create a category

  1. Go to Settings → Categories.
  2. Select New category (or Add subcategory on an existing row to create it under that parent).
  3. Enter a Name. A name must be unique within its parent — you can have two Accessories branches as long as they sit under different parents.
  4. Optionally choose a Parent category. Leave it blank to create a top-level (root) category.
  5. Optionally attach Attribute groups and Attributes now — see Attach attribute groups and attributes below.
  6. Save.

A new category is always created as a leaf so it can immediately hold products.

The "Other" bucket side effect

A leaf category can hold products directly, but a container category can't. So the first time you add a child to a leaf category that already has products assigned to it, SKU has to move those products somewhere — the parent is about to become a container.

When this happens, SKU automatically creates an Other subcategory under that parent and moves the parent's products into it. The save response returns other_bucket_created and the number of products moved, and the UI surfaces a warning toast so you know it happened. This is expected — the products are safe, just relocated one level down into Other. Rename or reassign them from there as needed.

Rename or move a category

Renaming and re-parenting are the same edit action.

  1. Open the category in Settings → Categories and select Edit.
  2. Change the Name and/or the Parent category.
  3. Save.

Notes and guardrails:

  • A category can't be its own parent. Re-parenting a branch onto itself is rejected by validation.
  • Moving a branch moves its whole subtree. When you save, SKU rebuilds the category's path, level and root_id, then rebuilds those same derived fields for every descendant — the full subtree follows the branch to its new home.
  • Root is null. Clearing the parent (or passing 0) makes the category a top-level root; SKU stores that as no parent.
  • Uniqueness follows the new parent. After a move, the name must be unique among the new parent's children.
  • Attribute groups and attributes are left untouched on a rename/move unless you explicitly change them (see below).

Delete a category

Deletion is leaf-only — you can only delete a branch that has no children.

  1. In Settings → Categories, select the category and choose Delete.
  2. Confirm.

What happens on a successful delete:

  • The category's links to products, attribute groups and attributes are detached (the products and attributes themselves aren't deleted — only the association to this category).
  • If deleting this category leaves its parent childless, the parent is flipped back to a leaf so it can hold products directly again.

If the category isn't a leaf, the delete is refused with a NOT_LEAF error that tells you exactly what's in the way — the number of subcategories and the number of products beneath it. Remove or reassign those first, then delete.

Check deletability first

Before offering a Delete button (especially for a multi-select), you can pre-check whether categories are deletable. The deletability check returns, per category:

FieldMeaning
deletabletrue only when the category is a leaf
reasonnull when deletable; otherwise the non-leaf explanation

Deletability is exactly "is this a leaf?" — a container can never be deleted until it's emptied of children.

Archive or restore a category

Archiving hides a category (and everything under it) without deleting anything. It's the reversible alternative to delete, and unlike delete it works on container categories too.

  1. In Settings → Categories, select the category and choose Archive.
  2. To bring it back, filter to archived categories and choose Restore.

Cascade behavior:

  • Archive stamps the whole subtree. Archiving a branch sets archived_at on that category and every descendant in one pass — you don't archive children one by one.
  • Restore clears the whole subtree. Unarchiving clears archived_at on the branch and all its descendants.
  • Archived categories are hidden by default. They're excluded from tree and list views unless you explicitly ask to include archived, thanks to the archived-exclusion scope.
  • Archiving a category that's already archived returns a harmless "already archived" warning rather than an error (and likewise for restore).

Reassign all products from one category to another

Use this to empty a leaf category before deleting it, or to consolidate two branches.

  1. Open the source category in Settings → Categories and choose Reassign products.
  2. Pick the destination category.
  3. Confirm. The response reports the number of product links moved (affected_records_count).

Rules and edge cases:

  • Both categories must be leaves, and the destination must be different from the source.
  • Products already in the destination are de-duplicated. If a product is linked to both categories, its old link is deleted (not moved) so you don't end up with a duplicate association.
  • Moved links become non-primary. Every link that moves is set to is_primary = false. If those products need a primary category, set it afterward on the product's Taxonomy tab.

Attach attribute groups and attributes

A category's attached attribute groups are what make attributes (Color, Material, Warranty…) apply to the products in that category. You can attach them when creating a category or at any later edit.

  1. Open or create the category.
  2. In Attribute groups, select the groups that apply to products in this branch.
  3. Optionally attach individual Attributes directly.
  4. Save.

Behavior to know:

  • Attaching replaces the full set. Saving with a list of attribute groups syncs the category to exactly that list — anything not in the list is removed.
  • Omitting the field leaves it unchanged. On an edit, if you don't touch attribute groups/attributes at all, their current assignments are preserved. (This is why a plain rename doesn't disturb them.)
  • Attribute groups and direct attributes are two independent assignments stored in separate pivots — you can use either or both.

See Manage attribute groups and Manage attributes for building the groups themselves.

Bulk archive, restore or delete

For housekeeping across many categories at once, select multiple rows in Settings → Categories (or use Apply to all to act on everything matching your current filters) and choose Archive, Restore or Delete.

  • Apply to all resolves your active search/filters into the matching set of category IDs, then runs the operation on them.
  • Bulk delete is still leaf-only. Container categories in the selection are refused for the same reason as a single delete — empty them first. Run the deletability check before a bulk delete to see which rows will be blocked.
  • Bulk archive/restore cascade to each selected category's subtree exactly as the single-category action does.

Import and export categories

Export

From Settings → Categories, choose Export and pick CSV or XLSX. The export honors your current search and archived filters — what you've filtered the list to is what you get. The columns are:

ColumnNotes
IDThe category's internal ID — keep it to update existing rows on re-import
Name
Parent Category IDBlank for root categories

Import

From Settings → Categories, choose Import, upload your spreadsheet, and preview before committing.

  • name is the only required column.
  • Each row is matched by id first, then by name — a matching row is updated, otherwise a new category is created.
  • If you supply an id that doesn't exist, that row is skipped with an error rather than silently creating a mismatched record.
  • New categories come in as leaves. Any row with no matching id or name is created fresh with is_leaf = true.
  • parent_id nests the row. Leave it blank to make the category a root; supply an existing category's ID to nest the row under it. This applies to both newly created and updated rows.
  • Parents aren't validated during import, and new categories get system-generated IDs you can't predict mid-file. To build depth reliably, import the categories first, then set their parents in a second pass — either by re-importing with each row's id and parent_id, or with Rename or move a category.

For product imports (not categories), see Import products and Export products.

Category fields

For quick reference, these are the fields on a category:

FieldEditable?Notes
nameYesRequired on create; unique per parent, not globally
parent_idYesnull (or 0) means a root category
is_leafNo — derivedtrue when the category has no children
levelNo — derivedDepth in the tree, rebuilt on every move
pathNo — derivedHuman-readable trail (Apparel -> Shirts -> T-Shirts), rebuilt on move
root_idNo — derivedThe top-most ancestor's ID (null if this is itself a root)
archived_atVia Archive/RestoreSet on the whole subtree when archived
created_at / updated_atNoHidden from the API response

The derived fields (is_leaf, level, path, root_id) are maintained by SKU whenever you create, move, delete or add a child — you never set them directly.

Next steps

Video transcript

Categories are the branches of your product taxonomy — a nested tree that groups products and drives which attributes apply. Settings, Products, Categories lists every category with its parent, its level, and whether it's a leaf that can hold products. Search or sort the list, or add one with Create Category. Switch to the Tree view to see the hierarchy. Expand a branch — here Drinkware holds Water Bottles, Tumblers, and Accessories. A branch with children is a container; only leaf categories hold products directly. You can create under any parent, rename, re-parent, or archive a whole subtree.

Last verified: