Skip to main content

Reordering products within a collection

The collectionReorderProducts mutation efficiently reorders products by requiring only the products whose positions actually change.

Only send the products that changed position. Don't send the full list. Sending n separate moves to relocate a product from position 1 to position n is slow and error-prone.

Not following the recommendation could lead to slow reorders.

Anchor to Key behavior of ,[object Object]Key behavior of collectionReorderProducts

  • Each move is applied sequentially in the order provided.
  • newPosition uses zero-based indexing, evaluated after any prior moves in the request.
  • Products that are not included in moves keep their relative order.
  • If newPosition is greater than or equal to the number of products in the collection, then the product is moved to the end.
  • Up to 250 product moves can be sent for each request.

Anchor to Minimal single‑move pattern: Move a product from index 1 to index NMinimal single‑move pattern: Move a product from index 1 to index N

If your current order is [A, B, C, D, E] and you want to move B from index 1 to index 4, send a single move for B only. The rest of the products will be displaced consistently.

GraphQL mutation collectionReorderProducts

mutation Reorder($collectionId: ID!, $productId: ID!, $newPosition: UnsignedInt64!) {
collectionReorderProducts(
id: $collectionId
moves: [{ id: $productId, newPosition: $newPosition }]
) {
job { id done }
userErrors { field message }
}
}

Input

{
"collectionId": "gid://shopify/Collection/1234567890",
"productId": "gid://shopify/Product/9876543210",
"newPosition": 4
}

This results in [A, E, B, D, C] if you first moved E to index 1 and then moved C to index 4 in the same request, or just [A, C, D, E, B] if you only moved B to the end. The crucial point: send moves only for the products you intend to reposition.

Anchor to Common anti‑pattern to avoidCommon anti‑pattern to avoid

This avoids unnecessary API work, reduces the chance of index drift, and minimizes conflicts with other reorder operations.

  • Incorrect: Sending N moves for every product between the original and target index of the product you’re moving
  • Correct:: Send one move for the product that actually moves, letting the platform handle displacement

Anchor to Multiple moves in one request (still minimal)Multiple moves in one request (still minimal)

You can batch up to 250 moves, evaluated in order. Provide only the products whose positions change. For example, to bring X to the front and move Y to position 10:

GraphQL mutation collectionReorderProducts

mutation Reorder($collectionId: ID!, $moves: [MoveInput!]!) {
collectionReorderProducts(id: $collectionId, moves: $moves) {
job { id done }
userErrors { field message }
}
}

Input

{
"collectionId": "gid://shopify/Collection/1234567890",
"moves": [
{ "id": "gid://shopify/Product/111", "newPosition": 0 },
{ "id": "gid://shopify/Product/222", "newPosition": 10 }
]
}
Note

Remember that each newPosition is evaluated after prior moves in the same request.

Anchor to Placing a product at the endPlacing a product at the end

If newPosition is greater than or equal to the number of products in the collection, the product is placed at the end. You can either supply an exact last index or any large newPosition to append to the end.

  • Compute newPosition using zero‑based indexing
  • Serialize reorder operations per collection in your app to avoid concurrent writes re‑ordering the same collection at the same time
  • For large reorders (>250 changes), split into multiple requests and continue polling jobs sequentially
  • Don’t send the entire product list; only send the items whose positions are changing

By relying on the minimal‑move approach and proper job polling, you’ll achieve efficient, predictable reordering with fewer API calls and less complexity.


Was this page helpful?